Вопрос

Skip to "My Code" at the bottom of the question to get straight to the point.


$con = mysql_connect('localhost', 'mysql_user', 'mysql_password');


General Examples:

Multiple query strings can be executed within a single mysql_query, like this...

mysql_query("
    INSERT INTO table_one (a,b,c) VALUES (1,2,3);
    INSERT INTO table_two (x,y,z) VALUES (7,8,'a text value');
    ", $con);

Multiple rows can be added to each query string, like this...

mysql_query("
    INSERT INTO table_one (a,b,c) VALUES (1,2,3), (2,3,1), (3,1,2);
    INSERT INTO table_two (x,y,z) VALUES (7,8,9), (8,9,7), (9,7,8);
    ", $con);

With an array of values, like this...

$array(
  [0] => array(1,2,3),
  [1] => array(2,'text',1),
  [2] => array(3,1,2)
);

...a query string can be dynamically created using a loop, like this...

$a = "INSERT INTO table_one (a,b,c) VALUES ";
foreach($array as $val){
  $a .= "(". implode(",",$val) ."),";
}
$a = trim($a, ",") . ";";

The Question:

How to write a single MySQL query that executes multiple INSERT query strings, each with multiple rows, so that each row inserted by the second query string can reference the corresponding row inserted by the first query string. Thus $var in this snippet would correspond to the auto_increment row ID of the first INSERT.

mysql_query("
    INSERT INTO table_one (a,b,c) VALUES (1,2,3), (2,3,1), (3,1,2);
    INSERT INTO table_two (x,y,z) VALUES ($var,8,9), ($var,9,7), ($var,7,8);
    ", $con);

My Code:

This is a simplified version of my code...

$q1 = "INSERT INTO `table_one` (t1c1,t1c2) VALUES ";
$q2 = "INSERT INTO `table_two` (t2c1,t2c2,t2c3) VALUES ";

foreach($array as $item){
  $q1 .= "('". $item ."','blah'),";
  $q2 .= "('". $row_ID_from_first_insert ."','something','whatever'),";
}

$q1 = trim($q1,",") .";";
$q2 = trim($q2,",") .";";
$q = $q1.$q2;

mysql_query($q, $this->connect);

What is a safe way to generate $row_ID_from_first_insert?

From my understanding using LAST_INSERT_ID() in the query string will not work because when multiple rows are inserted with a single query string it only returns the first inserted row ID. Is it safe to use LAST_INSERT_ID()+1 where 1 is replaced with a incremental variable in the foreach loop? What if multiple submits occur at the same time from different users?

Это было полезно?

Решение

Generally you'll have to fetch back out the id values of the inserted rows. This is unless you can create another key that is used in place of that which can be procedurally generated in advance.

While INSERT statements with multiple rows is significantly faster, the price you pay is a lack of precision. If your id values are issued sequentially, which is the default behavior, then you can be reasonably assured that the LAST_INSERT_ID() represents the ID of the first row inserted, so you could perhaps calculate the ID of the rows using the method you propose, though starting at index 0.

Remember that multiple submissions do not affect the LAST_INSERT_ID() result because this value is per-connection. It is only changed if you perform a subsequent query on the same database handle. Operations in other requests will not affect it.

Databases that are clustered or multi-master may issue non-sequential identifiers in which case this won't work. This is also unreliable in an INSERT IGNORE situation where the number of rows actually inserted could be less than the number of rows provided.

Другие советы

The LAST_INSERT_ID() is generated at the end of each successful query from the same connection handle. Therefore your example code will not give you the result you are looking for. See below:

mysql_query("
    INSERT INTO table_two (x,y,z) VALUES (LAST_INSERT_ID(),8,9), (LAST_INSERT_ID(),9,7), (LAST_INSERT_ID(),7,8);
", $con);

The above result will be (where x is the value LAST_INSERT_ID() produces):

 x    y    z
 5    8    9
 5    9    7
 5    7    8

To receive the result you seek, using the same format you used in your example (which i don't recommend for risk of sql injection - use mysqli instead) you can do so like:

 mysql_query("
    INSERT INTO table_two (x,y,z) VALUES (LAST_INSERT_ID(),8,9);
    INSERT INTO table_two (x,y,z) VALUES (LAST_INSERT_ID(),9,7);
    INSERT INTO table_two (x,y,z) VALUES (LAST_INSERT_ID(),7,8); 
", $con);

This will give you (where x is the value LAST_INSERT_ID() produces):

 x    y    z
 5    8    9
 6    9    7
 7    7    8
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top