MySQL ON DUPLICATE KEY - последний идентификатор вставки?

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

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

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

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

Ответ 1

Проверьте эту страницу: https://web.archive.org/web/20150329004325/https://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;

Ответ 2

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

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 столбец.

Ответ 3

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

Ответ 5

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

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

REPLACE работает точно так же, как INSERT, за исключением того, что если старая строка в таблице имеет такое же значение, как новая строка для PRIMARY KEY или UNIQUE индекс, старый строка удаляется до того, как новая строка будет вставлены.

Ответ 6

Существующие решения работают, если вы используете автоинкремент. У меня есть ситуация, когда пользователь может определить префикс, и он должен перезапустить последовательность на 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.