Как я могу вставить много строк в таблицу MySQL и вернуть новые идентификаторы? - PullRequest
67 голосов
/ 07 сентября 2011

Обычно я могу вставить строку в таблицу MySQL и получить обратно last_insert_id.Теперь, однако, я хочу массово вставить много строк в таблицу и получить обратно массив идентификаторов.Кто-нибудь знает, как я могу это сделать?

Есть несколько похожих вопросов, но они не совсем одинаковые.Я не хочу вставлять новый идентификатор в любую временную таблицу;Я просто хочу получить обратно массив идентификаторов.

Могу ли я получить lastInsertId из массовой вставки?

Mysql инструкция вставки из нескольких строк сlast_insert_id ()

Ответы [ 5 ]

63 голосов
/ 16 мая 2013

Старый поток, но только что рассмотрел это, так что здесь: если вы используете InnoDB в последней версии MySQL, вы можете получить список идентификаторов, используя LAST_INSERT_ID() и ROW_COUNT().

InnoDB гарантирует последовательные числа для АВТОМАТИЧЕСКОГО УВЕЛИЧЕНИЯ при выполнении массовых вставок, при условии, что innodb_autoinc_lock_mode установлено в 0 (традиционный) или 1 (последовательный). Следовательно, вы можете получить первый идентификатор из LAST_INSERT_ID() и последний , добавив ROW_COUNT()-1.

13 голосов
/ 07 сентября 2011

Единственный способ, которым я могу думать, это сделать, если вы сохраняете уникальный идентификатор для каждого набора вставленных строк (guid) затем выберите идентификаторы строк. например:

INSERT INTO t1
(SELECT col1,col2,col3,'3aee88e2-a981-1027-a396-84f02afe7c70' FROM a_very_large_table);
COMMIT;

SELECT id FROM t1 
WHERE guid='3aee88e2-a981-1027-a396-84f02afe7c70';

Вы также можете сгенерировать guid в базе данных, используя uuid()

3 голосов
/ 11 июня 2015

Предположим, у нас есть таблица с именем temptable с двумя столбцами: col1, где uid - поле с автоматическим приращением. Выполнение чего-либо, подобного приведенному ниже, вернет все вставленные идентификаторы в наборе результатов. Вы можете просмотреть список результатов и получить свои идентификаторы. Я понимаю, что это старый пост, и это решение может не работать для каждого случая. Но для других это может, и поэтому я отвечаю на это.

# lock the table
lock tables temptable write;

#bulk insert the rows;
insert into temptable(col1) values(1),(2),(3),(4);

#get the value of first inserted row. when bulk inserting last_insert_id() #should give the value of first inserted row from bulk op.
set @first_id = last_insert_id();

#now select the auto increment field whose value is greater than equal to #the first row. Remember since you have write lock on that table other #sessions can't write to it. This resultset should have all the inserted #id's
select uid from temptable where uid >=@first_id;

#now that you are done don't forget to unlock the table.
unlock tables;
0 голосов
/ 23 сентября 2011

Я думаю, вам придется либо обрабатывать идентификатор транзакции в вашем приложении, либо идентификатор элемента в вашем приложении, чтобы сделать это безупречно.

Один из способов сделать это, который может работать, при условии, что всеВаши вставки успешны (!), следующие:

Затем вы можете получить вставленные идентификаторы с циклом для числа затронутых строк, начиная с lastid (который является первым вставленным идентификатором массовой вставки).И, таким образом, я проверил, что это работает отлично ... просто будьте осторожны, например, HeidiSQL не вернет правильное значение для ROW_COUNT (), вероятно, потому что это дерьмовый графический интерфейс, который делает случайное дерьмо, мы его не просим - однако это совершенно правильно с обеих сторон.командная строка или PHP mysqli -

START TRANSACTION;
BEGIN;
INSERT into test (b) VALUES ('1'),('2'),('3');
SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;
COMMIT;

В PHP это выглядит так (local_sqle - это прямой вызов mysqli_query, local_sqlec - это вызов mysqli_query + преобразование набора результатов в массив PHP):

local_sqle("START TRANSACTION;
BEGIN;
INSERT into test (b) VALUES ('1'),('2'),('3');");
$r=local_sqlec("SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;");
local_sqle("
COMMIT;");
$i=0;
echo "last id =".($r[0]['lastid'])."<br>";
echo "Row count =".($r[0]['rowcount'])."<br>";

while($i<$r[0]['rowcount']){
    echo "inserted id =".($r[0]['lastid']+$i)."<br>";
    $i++;
}

Причина, по которой запросы разделяются, заключается в том, что иначе я бы не получил свой результат, используя свои собственные функции. Если вы сделаете это со стандартными функциями, вы можете поместить его обратно в один оператор, а затем получить нужный вам результат (это должнобыть результатом номер 2 - при условии, что вы используете расширение, которое обрабатывает более одного результирующего набора / запроса).

0 голосов
/ 09 сентября 2011
$query = "INSERT INTO TABLE (ID,NAME,EMAIL) VALUES (NULL,VALUE1, VALUE2)";
$idArray = array();
foreach($array as $key) {
 mysql_query($query);
 array_push($idArray, mysql_insert_id());
}
print_r($idArray);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...