Jak uzyskać identyfikator ostatniego zaktualizowanego wiersza w MySQL za pomocą PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Jak uzyskać identyfikator ostatniego zaktualizowanego wiersza w MySQL za pomocą PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Odpowiedzi:
Znalazłem odpowiedź na ten problem :)
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;
EDYCJA przez aefxx
Technikę tę można dodatkowo rozszerzyć, aby pobrać identyfikator każdego wiersza, na który ma wpływ instrukcja aktualizacji:
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
Spowoduje to zwrócenie ciągu znaków ze wszystkimi identyfikatorami połączonymi przecinkami.
WHERE
klauzulę, możesz po prostu użyć tej samej WHERE
klauzuli w następnym zapytaniuSELECT id FROM footable WHERE fooid > 5
LAST_INSERT_ID()
może przyjąć argument, który ustawi wartość zwracaną przez następne wywołanie funkcji LAST_INSERT_ID()
. Na przykład: UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';
. Teraz SELECT LAST_INSERT_ID();
zwróci zaktualizowany identyfikator. Aby uzyskać więcej informacji, zobacz odpowiedź newtover.
UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);
. Jednak nie pobiera wielu identyfikatorów, więc ta odpowiedź jest lepsza.
Hm, dziwię się, że wśród odpowiedzi nie widzę najłatwiejszego rozwiązania.
Załóżmy, że item_id
jest to kolumna będąca liczbą całkowitą w items
tabeli i aktualizujesz wiersze za pomocą następującej instrukcji:
UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';
Następnie, aby poznać najnowszy wiersz, którego dotyczy problem, tuż po instrukcji, należy nieznacznie zaktualizować instrukcję do następującego:
UPDATE items
SET qwe = 'qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();
Jeśli chcesz zaktualizować tylko naprawdę zmieniony wiersz, musisz dodać warunkową aktualizację item_id poprzez LAST_INSERT_ID sprawdzając, czy dane zmienią się w wierszu.
UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
Jest to oficjalnie proste, ale niezwykle sprzeczne z intuicją. Jeśli robisz:
update users set status = 'processing' where status = 'pending'
limit 1
Zmień to na:
update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id)
limit 1
Dodanie last_insert_id(user_id)
w where
klauzuli mówi MySQL, aby ustawić swoją wewnętrzną zmienną na identyfikator znalezionego wiersza. Kiedy przekazujesz taką wartość last_insert_id(expr)
, w końcu zwraca tę wartość, która w przypadku identyfikatorów takich jak tutaj jest zawsze dodatnią liczbą całkowitą i dlatego zawsze zwraca wartość true, nigdy nie kolidując z klauzulą where. Działa to tylko wtedy, gdy rzeczywiście znaleziono jakiś wiersz, więc pamiętaj, aby sprawdzić wiersze, których dotyczy problem. Następnie możesz uzyskać identyfikator na wiele sposobów.
Możesz generować sekwencje bez wywoływania LAST_INSERT_ID (), ale użyteczność korzystania z tej funkcji w ten sposób polega na tym, że wartość ID jest utrzymywana na serwerze jako ostatnia automatycznie wygenerowana wartość. Jest bezpieczny dla wielu użytkowników, ponieważ wielu klientów może wydać instrukcję UPDATE i uzyskać własną wartość sekwencji za pomocą instrukcji SELECT (lub mysql_insert_id ()), bez wpływu lub wpływu innych klientów, którzy generują własne wartości sekwencji.
Zwraca wartość wygenerowaną dla kolumny AUTO_INCREMENT przez poprzednią instrukcję INSERT lub UPDATE. Użyj tej funkcji po wykonaniu instrukcji INSERT w tabeli zawierającej pole AUTO_INCREMENT lub po użyciu instrukcji INSERT lub UPDATE do ustawienia wartości kolumny z LAST_INSERT_ID (wyrażenie).
Przyczyną różnic między LAST_INSERT_ID () a mysql_insert_id () jest to, że LAST_INSERT_ID () jest łatwy w użyciu w skryptach, podczas gdy mysql_insert_id () próbuje podać dokładniejsze informacje o tym, co dzieje się z kolumną AUTO_INCREMENT.
Wykonanie instrukcji INSERT lub UPDATE za pomocą funkcji LAST_INSERT_ID () również zmodyfikuje wartość zwracaną przez funkcję mysqli_insert_id ().
Kładąc wszystko razem:
$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, że klasa DB jest tutaj .)
Jest to ta sama metoda, co odpowiedź Salmana A, ale oto kod, którego naprawdę potrzebujesz, aby to zrobić.
Najpierw edytuj tabelę, aby automatycznie śledziła modyfikacje wiersza. Usuń ostatni wiersz, jeśli chcesz wiedzieć tylko, kiedy wiersz został pierwotnie wstawiony.
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
Następnie, aby znaleźć ostatni zaktualizowany wiersz, możesz użyć tego kodu.
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
Cały ten kod pochodzi z MySQL vs PostgreSQL: Dodanie kolumny „Last Modified Time” do tabeli i MySQL Manual: Sorting Rows . Właśnie go złożyłem.
Zapytanie:
$sqlQuery = "UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
Funkcja PHP:
function updateAndGetId($sqlQuery)
{
mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
return mysql_insert_id();
}
To dla mnie praca;)
Więcej informacji na temat powyżej zaakceptowanej odpowiedzi
Dla tych, którzy zastanawiali się nad :=
&=
Istotna różnica między :=
i =
, która :=
działa jako operator przypisania zmiennej wszędzie, podczas gdy =
działa w ten sposób tylko w instrukcjach SET, a wszędzie indziej jest operatorem porównania.
Więc SELECT @var = 1 + 1;
pozostawi @var
niezmienione i zwróci wartość logiczną (1 lub 0 w zależności od bieżącej wartości @var), podczas gdy SELECT @var := 1 + 1;
zmieni się @var
na 2 i zwróci 2 .
[Źródło]
Hej, po prostu potrzebowałem takiej sztuczki - rozwiązałem to w inny sposób, może to zadziała. Należy pamiętać, że nie jest to rozwiązanie skalowalne i będzie bardzo niekorzystne w przypadku dużych zestawów danych.
Podziel zapytanie na dwie części -
najpierw wybierz identyfikatory wierszy, które chcesz zaktualizować, i zapisz je w tabeli tymczasowej.
po drugie, wykonaj oryginalną aktualizację ze stanem w instrukcji aktualizacji zmienionym na where id in temp_table
.
Aby zapewnić współbieżność, musisz zablokować tabelę przed tymi dwoma krokami, a następnie zwolnić blokadę na końcu.
Ponownie, działa to dla mnie w przypadku zapytania, które kończy się na limit 1
, więc nie używam nawet tabeli tymczasowej, ale zamiast tego po prostu zmienną do przechowywania wyniku pierwszej select
.
Wolę tę metodę, ponieważ wiem, że zawsze będę aktualizować tylko jeden wiersz, a kod jest prosty.
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;
Musiałem PRZESŁAĆ identyfikator (nie wiem dlaczego) ... lub nie mogę pobrać zawartości @uids (to była kropelka). Przy okazji wielkie dzięki za odpowiedź Pomyka!
Identyfikator ostatniego zaktualizowanego wiersza to ten sam identyfikator, którego używasz w zapytaniu „updateQuery”, aby znaleźć i zaktualizować ten wiersz. Więc po prostu zapisz (zadzwoń) ten identyfikator w dowolny sposób.
last_insert_id()
zależy od AUTO_INCREMENT
, ale ostatni zaktualizowany identyfikator nie.
Moje rozwiązanie jest takie, że najpierw wybierz "id" (@uids) za pomocą polecenia select, a po zaktualizowaniu tego identyfikatora za pomocą @uids.
SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;
zadziałało przy moim projekcie.
Jeśli robisz tylko wstawki i chcesz mieć jedną z tej samej sesji, zrób zgodnie z odpowiedzią peirix. Jeśli dokonujesz modyfikacji, będziesz musiał zmodyfikować schemat bazy danych, aby przechowywać wpis, który był ostatnio aktualizowany.
Jeśli chcesz mieć identyfikator z ostatniej modyfikacji, która mogła pochodzić z innej sesji (tj. Nie tej, która została właśnie wykonana przez aktualnie działający kod PHP, ale wykonaną w odpowiedzi na inne żądanie), możesz dodać TIMESTAMP do tabeli o nazwie last_modified (więcej informacji można znaleźć pod adresem http://dev.mysql.com/doc/refman/5.1/en/datetime.html ), a następnie podczas aktualizacji ustaw last_modified = CURRENT_TIME.
Po ustawieniu tego możesz użyć zapytania takiego jak: SELECT id FROM table ORDER BY last_modified DESC LIMIT 1; aby pobrać ostatnio zmodyfikowany wiersz.