tags:

views:

61

answers:

3

I have a single procedure that has two insert statements in it for two different tables. I must insert data into table1 before I can insert into table2. I'm using PHP to do the data collection. What I'd like to know is how to insert multiple rows into table2, which can have many rows associated with table1. How would I do this?

I want to only store the person in table1 just one time but table2 requires multiple rows. If these insert statements were in separate procedures, I wouldn't have a problem but I just don't know how I would insert more than one row into table2 without table1 rejecting a second duplicate record.

BEGIN

INSERT INTO user(name, address, city) VALUES(Name, Address, City);

INSERT INTO order(order_id, desc) VALUES(OrderNo, Description);

END
A: 

I'd suggest you do it separately, otherwise you'd need a complicated solution which is prone to error if something changes.

The complicated solution is:

  • join all orderno and descriptions with a separator. (orderno#description)
  • join all orders with a different separator. (orderno#description/orderno#description/...)
  • pass it to the procedure
  • in the procedure, split the string by order separator, then loop through each of them
  • for each order, split the string by the first separator, then insert into the appropriate columns

As you can see, this is bad.

Tor Valamo
Hi Tor. Yes, this is bad. I've had someone else tell me that this is very simple and that I need to issue a single call to this procedure but I'm not seeing how this is possible. I wanted to verify first.
B52s
I must agree, this **is** bad.
shylent
@B52s - you can't pass lists to a procedure without serializing them first, so this is the only way to insert multiple rows through one procedure.
Tor Valamo
Tor, please have a look at what Shylent is saying. Would his suggestion work?
B52s
Don't use ignore. Hiding errors is no solution.
Tor Valamo
OK, thanks Tor. I agree, actually. I'll seperate the inserts.
B52s
A: 

I am sorry, but what's stopping you from inserting data into these (seemingly unrelated) tables in separate queries? If you don't like the idea of it failing halfway through, you can wrap it into a transaction. I know, mysqli and pdo can do that just fine.

Answering your question directly, insert's ignore mode turns errors during insertion into warnings, so upon attempting to insert a duplicate row the warning is issued and the row is not inserted, but there is no error.

shylent
Hi shylent. Thanks for the help. "Seemingly unrelated" but they are in fact related. My bad because I should have shown, at the very least the common key between the two. I'm using mysqli and I can certainly use a transaction. I have already tried to enter a single record into t1 and 3 records into t2 but t2 only took one. I believe that the transaction rolled back. So if I use IGNORE, then I will get all three rows into table2?
B52s
Yes, I said "seemingly", because the code indicated in no way, that they were related :) So anyway, what do you mean by "t2 only took one"? You issued *four* inserts before calling `commit()` and it only inserted two (one for t1, one for t2)?
shylent
A: 

You could use the IGNORE keyword on the first statement.
http://dev.mysql.com/doc/refman/5.1/en/insert.html:

If you use the IGNORE keyword, errors that occur while executing the INSERT statement are treated as warnings instead. For example, without IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY value in the table causes a duplicate-key error and the statement is aborted. With IGNORE, the row still is not inserted, but no error is issued.
But somehow this seems rather inefficient to me, a "stabbed from behind through the chest in the eye"-solution.

VolkerK
lol... I'd agree. I've never quite imagined it like that but you are right. :) So, should I then seperate the insert statements? Is this the right way to do it?
B52s