Как с помощью PHP получить идентификатор последней обновленной строки в MySQL?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Как с помощью PHP получить идентификатор последней обновленной строки в MySQL?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Ответы:
Я нашел ответ на эту проблему :)
SET @update_id := 0;
UPDATE some_table SET column_name = 'value', id = (SELECT @update_id := id)
WHERE some_other_column = 'blah' LIMIT 1;
SELECT @update_id;
РЕДАКТИРОВАТЬ по aefxx
Этот метод может быть дополнительно расширен для получения идентификатора каждой строки, затронутой оператором обновления:
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
Это вернет строку со всеми идентификаторами, объединенными запятой.
WHERE
предложение, вы можете просто использовать то же WHERE
предложение в следующем запросеSELECT id FROM footable WHERE fooid > 5
LAST_INSERT_ID()
может принять аргумент, который установит значение, возвращаемое при следующем вызове LAST_INSERT_ID()
. Например: UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';
. Теперь SELECT LAST_INSERT_ID();
вернет обновленный идентификатор. См. Ответ newtover для более подробной информации.
UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);
. Однако он не извлекает несколько идентификаторов, поэтому этот ответ лучше.
Хм, меня удивляет, что среди ответов я не вижу самого простого решения.
Предположим, item_id
есть столбец целочисленной идентичности в items
таблице, и вы обновляете строки с помощью следующего оператора:
UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';
Затем, чтобы узнать последнюю затронутую строку сразу после оператора, вы должны немного обновить оператор следующим образом:
UPDATE items
SET qwe = 'qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();
Если вам нужно обновить только действительно измененную строку, вам нужно будет добавить условное обновление item_id с помощью LAST_INSERT_ID, проверяющего, будут ли данные изменяться в строке.
UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
Официально это просто, но на удивление нелогично. Если вы делаете:
update users set status = 'processing' where status = 'pending'
limit 1
Измените это на это:
update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id)
limit 1
Добавление last_insert_id(user_id)
в where
предложение говорит MySQL установить его внутреннюю переменную на ID найденной строки. Когда вы передаете значение, last_insert_id(expr)
подобное этому, оно в конечном итоге возвращает это значение, которое в случае таких идентификаторов, как здесь, всегда является положительным целым числом и, следовательно, всегда оценивается как истинное, никогда не вмешиваясь в предложение where. Это работает, только если какая-то строка действительно была найдена, поэтому не забудьте проверить затронутые строки. Затем вы можете получить идентификатор несколькими способами.
Вы можете генерировать последовательности без вызова LAST_INSERT_ID (), но полезность использования функции таким образом заключается в том, что значение ID сохраняется на сервере как последнее автоматически сгенерированное значение. Это безопасно для многих пользователей, поскольку несколько клиентов могут выполнить оператор UPDATE и получить собственное значение последовательности с помощью оператора SELECT (или mysql_insert_id ()), не затрагивая и не подвергаясь влиянию других клиентов, которые генерируют свои собственные значения последовательности.
Возвращает значение, созданное для столбца AUTO_INCREMENT предыдущим оператором INSERT или UPDATE. Используйте эту функцию после того, как вы выполнили оператор INSERT в таблице, содержащей поле AUTO_INCREMENT, или использовали INSERT или UPDATE для установки значения столбца с LAST_INSERT_ID (expr).
Причина различий между LAST_INSERT_ID () и mysql_insert_id () заключается в том, что LAST_INSERT_ID () упрощено для использования в скриптах, в то время как mysql_insert_id () пытается предоставить более точную информацию о том, что происходит со столбцом AUTO_INCREMENT.
Выполнение оператора INSERT или UPDATE с использованием функции LAST_INSERT_ID () также изменит значение, возвращаемое функцией mysqli_insert_id ().
Собираем все вместе:
$affected_rows = DB::getAffectedRows("
update users set status = 'processing'
where status = 'pending' and last_insert_id(user_id)
limit 1"
);
if ($affected_rows) {
$user_id = DB::getInsertId();
}
(К вашему сведению, этот класс DB находится здесь .)
Это тот же метод, что и ответ Салмана А, но вот код, который вам действительно нужен.
Сначала отредактируйте таблицу, чтобы она автоматически отслеживала изменение строки. Удалите последнюю строку, если вы хотите знать, когда строка была изначально вставлена.
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
Затем, чтобы узнать последнюю обновленную строку, вы можете использовать этот код.
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
Этот код взят из MySQL vs PostgreSQL: Добавление столбца «Время последнего изменения» в таблицу и Руководства по MySQL: Сортировка строк . Я только что собрал.
Запрос:
$sqlQuery = "UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
PHP функция:
function updateAndGetId($sqlQuery)
{
mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
return mysql_insert_id();
}
У меня это работает;)
Дополнительные сведения о принятом выше ответе
Для тех, кто интересовался :=
&=
Значительная разница между :=
и =
, и является то , что :=
работает в качестве оператора переменного назначения всюду, в то время как =
работает только таким образом в отчетности SET, и оператор сравнения везде.
Таким образом SELECT @var = 1 + 1;
, оставим @var
без изменений и вернем логическое значение (1 или 0 в зависимости от текущего значения @var), тогда как SELECT @var := 1 + 1;
изменится @var
на 2 и вернет 2 .
[Источник]
Эй, просто нужна была такая уловка - решил по-другому, может у тебя сработает. Обратите внимание, что это не масштабируемое решение, и оно будет очень плохим для больших наборов данных.
Разделите свой запрос на две части -
сначала выберите идентификаторы строк, которые вы хотите обновить, и сохраните их во временной таблице.
во-вторых, выполните исходное обновление, изменив условие в операторе обновления на where id in temp_table
.
И для обеспечения параллелизма вам необходимо заблокировать таблицу перед этими двумя шагами, а затем снять блокировку в конце.
Опять же, это работает для меня для запроса, который заканчивается на limit 1
, поэтому я даже не использую временную таблицу, а вместо этого просто переменную для хранения результата первой select
.
Я предпочитаю этот метод, так как знаю, что всегда буду обновлять только одну строку, а код прост.
SET @uids := "";
UPDATE myf___ingtable
SET id = id
WHERE id < 5
AND ( SELECT @uids := CONCAT_WS(',', CAST(id AS CHAR CHARACTER SET utf8), @uids) );
SELECT @uids;
Мне пришлось ОТПРАВИТЬ идентификатор (не знаю почему) ... или я не могу получить контент @uids (это был капля) Кстати, большое спасибо за ответ Pomyk!
Идентификатор последней обновленной строки - это тот же идентификатор, который вы использовали в updateQuery для поиска и обновления этой строки. Итак, просто сохраните (позвоните) этот идентификатор как хотите.
last_insert_id()
зависит от AUTO_INCREMENT
, но не от последнего обновленного идентификатора.
Мое решение: сначала определите «id» (@uids) с помощью команды select, а затем обновите этот идентификатор с помощью @uids.
SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;
это сработало над моим проектом.
Если вы только делаете вставки и хотите одну из той же сессии, сделайте так, как ответили peirix. Если вы вносите изменения, вам нужно будет изменить схему базы данных, чтобы сохранить, какая запись была недавно обновлена.
Если вам нужен идентификатор из последней модификации, которая могла быть из другого сеанса (т. Е. Не из того, что было выполнено только что запущенным PHP-кодом в данный момент, а из того, что было выполнено в ответ на другой запрос), вы можете добавить TIMESTAMP столбец в таблицу под названием LAST_MODIFIED (см http://dev.mysql.com/doc/refman/5.1/en/datetime.html для информации), а затем , когда вы обновляете, набор LAST_MODIFIED = CURRENT_TIME.
Установив это, вы можете использовать запрос, такой как: SELECT id ИЗ таблицы ORDER BY last_modified DESC LIMIT 1; чтобы получить последнюю измененную строку.