views:

201

answers:

2

I have two MySQL database tables that are meant to hold data for eshop orders. They're built as such (extremely simplified version):

CREATE TABLE `orders` (
`id` int(11) NOT NULL auto_increment
PRIMARY KEY  (`id`)
);

CREATE TABLE `order_items` (
  `id` int(11) NOT NULL auto_increment,
  `orderID` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
)

The relationship between the two is that orders.id corresponds to order_items.orderID.

I'm using a transaction to place a new order, however have a problem preserving the above relationship. In order to get the new order id. I have to commit the orders INSERT query, get the autoincremented id and then start another transaction for the order items. Which pretty much defeats the point of using transactions.

I could insert the new order in the orders table and then try something like

INSERT INTO order_items(orderID) VALUES(LAST_INSERT_ID())

which I assume would work. However after the first order item is inserted LAST_INSERT_ID() would stop returning the order id and instead return the order item id making it impossible to use this query to insert another order item.

Is there a way to make this whole thing work within a single transaction or should I give up and use a procedure instead?

+2  A: 

WOuld this work?:

INSER QUERY;
SET @insertid = LAST_INSERT_ID();
INSERT INTO `order_items` SET `OrderID` = @insertid;

All in one statement. You will have to double check the syntax

Lizard
or get the value of LAST_INSERT_ID() in your application, and build the insert for order_items there.
longneck
+1  A: 

You can't count on LAST_INSERT_ID() because it also changes when you insert values to order_items because it inserts its id which is also auto_imcrement. Maybe you can try this.

INSERT INTO order_items(orderID) VALUES((SELECT id FROM orders ORDER BY id desc LIMIT 1))
junmats
what you have proposed creates a race condition. if two people insert orders at the same time, one of them will get the wrong id.
longneck