2009-09-07 3 views
110

Как получить идентификатор последней обновленной строки в MySQL с помощью PHP?Как получить идентификатор последней обновленной строки в MySQL?

+0

если вам понравился мой ответ, вы могли бы рассмотреть upvoting и установить его в качестве принятого ответа .. (: – peirix

+2

mysqli_insert_id ($ link) вернет точно идентификатор последней обновленной строки.Я использую это funtion в своих проектах с той же целью.Изображение можно использовать как в синхронных, так и в асинхронных запросах. Просто вставьте $ lastupdated_row_id = mysqli_insert_id ($ link) в свой код и он будет работать для вас. –

+1

Do вы уже не знаете идентификатор строки, если вы обновляете? Я предполагаю, что в некоторых случаях у вас нет. – JCharette

ответ

199

Я нашел ответ на этот вопрос :)

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; 

EDIT по aefxx

Этот метод может быть дополнительно расширена до получения идентификатора каждой строки, пострадавших от оператора обновления:

SET @uids := null; 
UPDATE footable 
    SET foo = 'bar' 
WHERE fooid > 5 
    AND (SELECT @uids := CONCAT_WS(',', fooid, @uids)); 
SELECT @uids; 

Это вернет строку со всеми идентификаторами, объединенными двоеточием.

+6

Не могу поверить, что у него было 0 upvotes, а комментарий mysql_insert_id(), который не соответствует требованиям OP, имеет 13. Спасибо Pomyk, умный трюк! –

+1

Поскольку у вас есть предложение WHERE, вы можете просто использовать одно и то же предложение WHERE в следующем запросе. SELECT id FROM footable WHERE fooid> 5' –

+4

Возможно, все это понимают, но если вы используете mysql_query(); вы должны разделить это на три разных вызова, но это сработает. –

1

Если вы делаете только вставки и хотите один из того же сеанса, сделайте это в соответствии с ответом peirix. Если вы вносите изменения, вам нужно будет изменить схему базы данных, чтобы сохранить, какая запись была обновлена ​​в последний раз.

Если вы хотите получить идентификатор из последней модификации, которая, возможно, была из другого сеанса (то есть не того, который был только что выполнен с помощью PHP-кода, работающего в настоящее время, но один был выполнен в ответ на другой запрос) вы можете добавить столбец TIMESTAMP в вашу таблицу с именем last_modified (см. http://dev.mysql.com/doc/refman/5.1/en/datetime.html для информации), а затем при обновлении установите last_modified = CURRENT_TIME.

Установив это, вы можете использовать запрос типа: SELECT id FROM table ORDER BY last_modified DESC LIMIT 1; , чтобы получить последнюю измененную строку.

+1

Это связано с условиями гонки с одновременными изменениями. – Ryaner

2

ID последней обновленной строки - это тот же идентификатор, который вы используете в 'updateQuery', чтобы найти & обновите эту строку. Поэтому просто сохраните (вызовите) этот идентификатор в любом случае.

last_insert_id() зависит от AUTO_INCREMENT, но последний обновленный ID нет.

+3

Что делать, если обновление не выполняется из идентификатора, а другого набора атрибутов? – Sebas

-8

Не нужно так долго указывать код Mysql. В PHP, запрос должен выглядеть следующим образом:

$updateQuery = mysql_query("UPDATE table_name SET row='value' WHERE id='$id'") or die ('Error'); 
$lastUpdatedId = mysql_insert_id(); 
+3

... это неправильно, что получит последний -интернет-идентификатор ... – Kzqai

+0

согласен, вы получите последний идентификатор вставки, а не обновленный номер строки – Macumbaomuerte

2

Эй, я просто нужен такой трюк - я решил ее по-другому, может быть, она будет работать для вас. Обратите внимание, что это не масштабируемое решение и будет очень плохо для больших наборов данных.

Split ваш запрос на две части -

первый, выберите идентификаторы строк, которые вы хотите обновить и сохранить их во временной таблице.

Во-вторых, сделайте исходное обновление с условием в заявлении об обновлении, измененным на where id in temp_table.

И для обеспечения параллелизма вам необходимо сделать lock таблицу перед этими двумя шагами, а затем отпустить блокировку в конце.

Снова это работает для меня, для запроса, который заканчивается limit 1, поэтому я даже не использую временную таблицу, а вместо этого просто переменную для хранения результата первого select.

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

9

Это тот же метод, что и ответ Салмана А, но вот код, который вам действительно нужно сделать.

Сначала отредактируйте таблицу так, чтобы она автоматически отслеживала всякий раз, когда строка была изменена. Удалите последнюю строку, если хотите узнать, когда была вставлена ​​строка.

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: Adding a 'Last Modified Time' Column to a Table и MySQL Manual: Sorting Rows. Я только что собрал его.

+5

Этот метод может получить неверный идентификатор, если вторая вставка выполняется сразу после первого запроса на вставку. Однако если мы используем «WHERE» с этим запросом, то есть SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1 WHERE (некоторые условия, связанные с последним запросом на вставку), то он может предотвратить выбор неправильного идентификатора. –

+1

@ TheNoble-Coder Это правда. Если вам нужно, чтобы идентификатор строки затрагивал конкретный запрос на обновление, используйте технику Помика. Этот метод здесь более полезен при асинхронном использовании, когда вам просто нужно абсолютное последнее обновление. –

1
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; 

Я должен был CAST идентификатор (знаю почему) ... или я не могу получить содержимое @uids (это была капля) Btw большое спасибо за Pomyk ответ!

27

Хм, я удивлен, что среди ответов я не вижу самого простого решения.

Предположит, 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 проверки, если данные собираются сп ange в строке.

+2

Это многопользовательский сейф, поскольку несколько клиентов могут выдавать инструкцию UPDATE и получать собственное значение последовательности с помощью инструкции SELECT (или mysql_insert_id()), не затрагивая или не подвергаясь воздействию других клиентов, которые генерируют свои собственные значения последовательности. В соответствии с https://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id – brutuscat

+1

Не будет ли это установить item_id в последнюю вставленную запись? – arleslie

+2

@arleslie, если вы перейдете по ссылке к документам в комментарии брутуската выше, вы увидите, что этого не произойдет. Это предполагаемое поведение именно для этого случая. – newtover

4

Запрос:

$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(); 
} 

Это работа для меня;)

+1

Спасибо, что это работает. –

+0

Мне это очень понравилось, но бежал differntly ref: http://forums.mysql.com/read.php?52,390616,390619 – AMB

0

Мое решение, сначала решить, "ID" (@uids) с избранной командой и после обновления этого id с помощью @uids.

SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1); 
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids; 

он работал над моим проектом.

1

Дальше больше к вышесказанному Принято Ответ
Для тех, кто интересно о := & =

Значительная разница между := и =, и что это то, что := работает как оператор переменной назначения всюду, в то время как = работает только в операторах SET, а оператор сравнения - везде.

Так SELECT @var = 1 + 1; оставит @var без изменений и возвращать булево (1 или 0 в зависимости от текущего значения @var), в то время как SELECT @var := 1 + 1; изменится @var к и возвращение 2. [Source]

+0

Эй, спасибо. То, что они имеют в виду, на самом деле более интересно, чем принятый ответ выше. – Green

3

Это официально прост, но замечательно противоинтуитивно. Если вы делаете:

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, чтобы установить свою внутреннюю переменную идентификатору найденной строки. Когда вы передаете значение last_insert_id(expr), оно возвращает это значение, которое в случае идентификаторов, подобных здесь, всегда является положительным целым числом и поэтому всегда оценивает значение true, никогда не вмешиваясь в предложение where. Это работает только в том случае, если определенная строка действительно найдена, поэтому не забудьте проверить затронутые строки. Затем вы можете получить идентификатор несколькими способами.

MySQL last_insert_id()

Вы можете генерировать последовательности без вызова LAST_INSERT_ID(), но полезность с помощью функции таким образом, что значение идентификатора сохраняется на сервере в качестве последнего автоматически сгенерированного значения. Он является многопользовательским безопасным, поскольку несколько клиентов могут выдавать инструкцию UPDATE и получать свое собственное значение последовательности с помощью оператора SELECT (или mysql_insert_id()), не затрагивая или не подвергаясь воздействию других клиентов , которые генерируют свои собственные значения последовательности.

MySQL mysql_insert_id()

Возвращает значение, сгенерированный для столбца AUTO_INCREMENT по предыдущей вставки или обновления заявления. Используйте эту функцию после того, как выполнил оператор INSERT в таблицу, содержащую поле AUTO_INCREMENT , или использовали INSERT или UPDATE для установки значения с LAST_INSERT_ID (expr).

Причина различий между LAST_INSERT_ID() и mysql_insert_id() является то, что LAST_INSERT_ID() производится легко использовать в сценариях во время mysql_insert_id() пытается обеспечить более точную информации о том, что происходит с AUTO_INCREMENT колонка.

PHP mysqli_insert_id()

Выполнение оператора 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(); 
} 

(FYI, что DB class is here.)

Смежные вопросы