MySQL НА ДУБЛИРУЮЩЕМСЯ КЛЮЧЕ - идентификатор последней вставки?

StackOverflow https://stackoverflow.com/questions/778534

  •  13-09-2019
  •  | 
  •  

Вопрос

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

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

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

Есть ли способ ВСТАВИТЬ / ОБНОВИТЬ и получить идентификатор строки без выполнения двух запросов?

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

Решение

Ознакомьтесь с этой страницей: 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 ...ОБНОВЛЕНИЕ вставляет строку, функция LAST_INSERT_ID() возвращает значение AUTO_INCREMENT.Если вместо этого оператор обновляет строку, LAST_INSERT_ID() не имеет смысла.Однако вы можете обойти это, используя LAST_INSERT_ID(выражение).Предположим, что 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;

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

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

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 ...Обновить вставляет строку, функция LAST_INSERT_ID() возвращает значение AUTO_INCREMENT.Если вместо этого оператор обновляет строку, LAST_INSERT_ID() не имеет смысла.Однако вы можете обойти это используя LAST_INSERT_ID(выражение).Предположим, что id является столбцом AUTO_INCREMENT .

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

Я не знаю, какая у вас версия 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

Стоит отметить, и это может быть очевидно (но я все равно скажу это для ясности здесь), что REPLACE удалит существующую соответствующую строку перед вставкой ваших новых данных.ПРИ ОБНОВЛЕНИИ ДУБЛИРУЮЩЕГО КЛЮЧА будут обновлены только указанные вами столбцы и сохранена строка.

Из руководство пользователя:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top