MySQL ON DUPLICATE KEY - последний идентификатор вставки? - PullRequest
117 голосов
/ 22 апреля 2009

У меня следующий запрос:

INSERT INTO table (a) VALUES (0)
  ON DUPLICATE KEY UPDATE a=1

Я хочу идентификатор вставки или обновления. Обычно я запускаю второй запрос, чтобы получить его, так как считаю, что insert_id () возвращает только вставленный идентификатор, а не обновленный идентификатор.

Есть ли способ вставить / обновить и получить идентификатор строки без выполнения двух запросов?

Ответы [ 6 ]

149 голосов
/ 23 апреля 2009

Проверьте эту страницу: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
Внизу страницы они объясняют, как можно сделать LAST_INSERT_ID значимым для обновлений, передав выражение этой функции MySQL.

Из примера документации MySQL:

Если таблица содержит столбец AUTO_INCREMENT и INSERT ... UPDATE вставляет строку, функция LAST_INSERT_ID () возвращает значение AUTO_INCREMENT. Если инструкция обновляет строку, LAST_INSERT_ID () не имеет смысла. Однако вы можете обойти это, используя LAST_INSERT_ID (expr). Предположим, что id является столбцом AUTO_INCREMENT. Чтобы LAST_INSERT_ID () имел смысл для обновлений, вставьте строки следующим образом:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
31 голосов
/ 10 августа 2012

Если быть точным, если это оригинальный запрос:

INSERT INTO table (a) VALUES (0)
 ON DUPLICATE KEY UPDATE a=1

и 'id' - это первичный ключ с автоинкрементом, чем это будет рабочее решение:

INSERT INTO table (a) VALUES (0)
  ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), a=1

Это все здесь: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

Если таблица содержит столбец AUTO_INCREMENT и INSERT ... UPDATE вставляет строку, функция LAST_INSERT_ID () возвращает Значение AUTO_INCREMENT. Если оператор обновляет строку вместо, LAST_INSERT_ID () не имеет смысла. Тем не менее, вы можете обойти это используя LAST_INSERT_ID (expr). Предположим, что id это AUTO_INCREMENT колонка.

2 голосов
/ 23 апреля 2009

Я не знаю, какая у вас версия MySQL, но с InnoDB была ошибка с autoinc

ошибка в 5.1.20 и исправлена ​​в 5.1.23 http://bugs.mysql.com/bug.php?id=27405

ошибка в 5.1.31 и исправлена ​​в 5.1.33 http://bugs.mysql.com/bug.php?id=42714

2 голосов
/ 22 апреля 2009

Вы можете посмотреть на REPLACE, который по сути является удалением / вставкой, если запись существует. Но это изменило бы поле автоинкремента, если оно присутствует, что могло бы нарушить отношения с другими данными.

0 голосов
/ 02 июня 2015

Существующие решения работают, если вы используете автоинкремент. У меня есть ситуация, когда пользователь может определить префикс, и он должен перезапустить последовательность на 3000. Из-за этого различного префикса я не могу использовать автоинкремент, который делает last_insert_id пустым для вставок. Я решил это со следующим:

INSERT INTO seq_table (prefix, id) VALUES ('$user_prefix', LAST_INSERT_ID(3000)) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id + 1);
SELECT LAST_INSERT_ID();

Если префикс существует, он будет увеличивать его и заполнять last_insert_id. Если префикс не существует, он вставит префикс со значением 3000 и заполнит last_insert_id 3000.

0 голосов
/ 05 ноября 2009

Стоит отметить, и это может быть очевидным (но я все равно скажу это для ясности здесь), что REPLACE уничтожит существующую строку соответствия перед вставкой ваших новых данных. ON DUPLICATE KEY UPDATE обновит только указанные вами столбцы и сохранит строку.

Из руководства :

REPLACE работает точно так же, как INSERT, за исключением того, что если старая строка в таблице имеет то же значение, что и новая строка для ПЕРВИЧНЫЙ КЛЮЧ или УНИКАЛЬНЫЙ индекс, старый строка удаляется до того, как новая строка вставлена.

...