Come posso ottenere l'ID dell'ultima riga aggiornata in MySQL usando PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1?
Come posso ottenere l'ID dell'ultima riga aggiornata in MySQL usando PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1?
Risposte:
Ho trovato una risposta a questo problema :)
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 di aefxx
Questa tecnica può essere ulteriormente espansa per recuperare l'ID di ogni riga interessata da un'istruzione di aggiornamento:
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
Ciò restituirà una stringa con tutti gli ID concatenati da una virgola.
WHEREclausola puoi semplicemente usare la stessa WHEREclausola nella tua prossima querySELECT id FROM footable WHERE fooid > 5
LAST_INSERT_ID()può accettare un argomento che imposterà il valore restituito dalla chiamata successiva a LAST_INSERT_ID(). Ad esempio: UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';. Ora SELECT LAST_INSERT_ID();restituirà l'id aggiornato. Vedi la risposta di newtover per maggiori dettagli.
UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);. Tuttavia, non recupera più ID, quindi questa risposta è superiore.
Hm, sono sorpreso che tra le risposte non vedo la soluzione più semplice.
Supponiamo che item_idsia una colonna di identità intera nella itemstabella e aggiorni le righe con la seguente istruzione:
UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';
Quindi, per conoscere l'ultima riga interessata subito dopo l'istruzione, è necessario aggiornare leggermente l'istruzione nel modo seguente:
UPDATE items
SET qwe = 'qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();
Se è necessario aggiornare solo la riga realmente modificata, è necessario aggiungere un aggiornamento condizionale di item_id tramite LAST_INSERT_ID verificando se i dati cambieranno nella riga.
UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
Questo è ufficialmente semplice ma straordinariamente controintuitivo. Se stai facendo:
update users set status = 'processing' where status = 'pending'
limit 1
Modificalo in questo:
update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id)
limit 1
L'aggiunta last_insert_id(user_id)nella whereclausola dice a MySQL di impostare la sua variabile interna sull'ID della riga trovata. Quando si passa un valore a last_insert_id(expr)questo, finisce per restituire quel valore, che nel caso di ID come qui è sempre un numero intero positivo e quindi viene sempre valutato come vero, senza mai interferire con la clausola where. Funziona solo se è stata effettivamente trovata una riga, quindi ricorda di controllare le righe interessate. È quindi possibile ottenere l'ID in più modi.
È possibile generare sequenze senza chiamare LAST_INSERT_ID (), ma l'utilità di utilizzare la funzione in questo modo è che il valore ID viene mantenuto nel server come ultimo valore generato automaticamente. È sicuro per più utenti perché più client possono emettere l'istruzione UPDATE e ottenere il proprio valore di sequenza con l'istruzione SELECT (o mysql_insert_id ()), senza influenzare o essere influenzati da altri client che generano i propri valori di sequenza.
Restituisce il valore generato per una colonna AUTO_INCREMENT dall'istruzione INSERT o UPDATE precedente. Utilizzare questa funzione dopo aver eseguito un'istruzione INSERT in una tabella che contiene un campo AUTO_INCREMENT o aver utilizzato INSERT o UPDATE per impostare un valore di colonna con LAST_INSERT_ID (expr).
Il motivo delle differenze tra LAST_INSERT_ID () e mysql_insert_id () è che LAST_INSERT_ID () è reso facile da usare negli script mentre mysql_insert_id () cerca di fornire informazioni più precise su ciò che accade alla colonna AUTO_INCREMENT.
L'esecuzione di un'istruzione INSERT o UPDATE mediante la funzione LAST_INSERT_ID () modificherà anche il valore restituito dalla funzione mysqli_insert_id ().
Mettere tutto insieme:
$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();
}
(Cordiali saluti che la classe DB è qui .)
Questo è lo stesso metodo della risposta di Salman A, ma ecco il codice che devi effettivamente fare.
Innanzitutto, modifica la tabella in modo che tenga automaticamente traccia di ogni modifica di una riga. Rimuovere l'ultima riga se si desidera sapere solo quando è stata inizialmente inserita una riga.
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
Quindi, per scoprire l'ultima riga aggiornata, è possibile utilizzare questo codice.
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
Questo codice è stato estratto da MySQL vs PostgreSQL: aggiunta di una colonna "Ora dell'ultima modifica" a una tabella e Manuale MySQL: Ordinamento delle righe . L'ho appena assemblato.
Query:
$sqlQuery = "UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
Funzione PHP:
function updateAndGetId($sqlQuery)
{
mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
return mysql_insert_id();
}
È lavoro per me;)
Ulteriori informazioni sulla risposta sopra accettata
per coloro che si chiedevano :=e=
Differenza significativa tra :=e =, e cioè che :=funziona come un operatore di assegnazione variabile ovunque, mentre =funziona così solo nelle istruzioni SET, ed è un operatore di confronto ovunque.
Quindi SELECT @var = 1 + 1;rimarrà @varinvariato e restituirà un valore booleano (1 o 0 a seconda del valore corrente di @var), mentre SELECT @var := 1 + 1;cambierà @varin 2 e restituirà 2 .
[Fonte]
Ehi, avevo solo bisogno di un simile trucco - l'ho risolto in un modo diverso, forse funzionerà per te. Nota che questa non è una soluzione scalabile e sarà molto male per grandi set di dati.
Dividi la query in due parti:
in primo luogo, selezionare gli ID delle righe che si desidera aggiornare e archiviarli in una tabella temporanea.
in secondo luogo, eseguire l'aggiornamento originale con la condizione nell'istruzione di aggiornamento modificata in where id in temp_table.
E per garantire la concorrenza, è necessario bloccare la tabella prima di questi due passaggi e quindi rilasciare il blocco alla fine.
Ancora una volta, questo funziona per me, per una query che termina con limit 1, quindi non uso nemmeno una tabella temporanea, ma semplicemente una variabile per memorizzare il risultato del primo select.
Preferisco questo metodo poiché so che aggiornerò sempre solo una riga e il codice è semplice.
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;
Ho dovuto lanciare l'id (non so perché) ... o non riesco a ottenere il contenuto @uids (era un blob) Tra le molte grazie per la risposta di Pomyk!
L'ID dell'ultima riga aggiornata è lo stesso ID utilizzato in 'updateQuery' per trovare e aggiornare quella riga. Quindi, salva (chiama) quell'ID su come desideri.
last_insert_id()dipende da AUTO_INCREMENT, ma l'ultimo ID aggiornato no.
La mia soluzione è, prima di decidere "id" (@uids) con il comando select e dopo aggiornare questo id con @uids.
SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;
ha funzionato sul mio progetto.
Se stai facendo solo inserimenti e ne desideri uno dalla stessa sessione, fai come da risposta peirix. Se si stanno apportando modifiche, sarà necessario modificare lo schema del database per memorizzare la voce aggiornata più di recente.
Se vuoi l'ID dall'ultima modifica, che potrebbe essere stata da una sessione diversa (cioè non quella che è stata appena eseguita dal codice PHP attualmente in esecuzione, ma uno fatto in risposta a una richiesta diversa), puoi aggiungere un TIMESTAMP nella colonna della tabella denominata last_modified (vedere http://dev.mysql.com/doc/refman/5.1/en/datetime.html per informazioni), quindi quando si aggiorna, impostare last_modified = CURRENT_TIME.
Dopo aver impostato questo, è quindi possibile utilizzare una query come: SELEZIONARE ID DA tabella ORDER BY last_modified DESC LIMIT 1; per ottenere la riga modificata più di recente.