¿Cómo obtengo el ID de la última fila actualizada en MySQL usando PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
¿Cómo obtengo el ID de la última fila actualizada en MySQL usando PHP?
UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
?
Respuestas:
He encontrado una respuesta a este 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;
EDITAR por aefxx
Esta técnica se puede ampliar aún más para recuperar el ID de cada fila afectada por una declaración de actualización:
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
Esto devolverá una cadena con todos los ID concatenados por una coma.
WHERE
cláusula, simplemente puede usar la misma WHERE
cláusula en su próxima consultaSELECT id FROM footable WHERE fooid > 5
LAST_INSERT_ID()
puede aceptar un argumento que establecerá el valor devuelto por la próxima llamada a LAST_INSERT_ID()
. Por ejemplo: UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';
. Ahora, SELECT LAST_INSERT_ID();
devolverá la identificación actualizada. Vea la respuesta de newtover para más detalles.
UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);
. Sin embargo, no recupera múltiples identificadores, por lo que esta respuesta es superior.
Hm, me sorprende que entre las respuestas no veo la solución más fácil.
Supongamos que item_id
es una columna de identidad entera en la items
tabla y actualiza las filas con la siguiente instrucción:
UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';
Luego, para conocer la última fila afectada justo después de la declaración, debe actualizar ligeramente la declaración en lo siguiente:
UPDATE items
SET qwe = 'qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();
Si necesita actualizar solo una fila realmente cambiada, necesitaría agregar una actualización condicional del item_id a través de LAST_INSERT_ID comprobando si los datos van a cambiar en la fila.
UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
Esto es oficialmente simple pero notablemente contra-intuitivo. Si estas haciendo:
update users set status = 'processing' where status = 'pending'
limit 1
Cámbialo a esto:
update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id)
limit 1
La adición de last_insert_id(user_id)
en la where
cláusula le dice a MySQL que establezca su variable interna en la ID de la fila encontrada. Cuando pasas un valor alast_insert_id(expr)
como este, termina devolviendo ese valor, que en el caso de ID como este siempre es un entero positivo y, por lo tanto, siempre se evalúa como verdadero, sin interferir nunca con la cláusula where. Esto solo funciona si se encontró alguna fila, así que recuerde verificar las filas afectadas. Luego puede obtener la identificación de varias maneras.
Puede generar secuencias sin llamar a LAST_INSERT_ID (), pero la utilidad de usar la función de esta manera es que el valor de ID se mantiene en el servidor como el último valor generado automáticamente. Es seguro para múltiples usuarios porque varios clientes pueden emitir la instrucción UPDATE y obtener su propio valor de secuencia con la instrucción SELECT (o mysql_insert_id ()), sin afectar ni verse afectados por otros clientes que generan sus propios valores de secuencia.
Devuelve el valor generado para una columna AUTO_INCREMENT por la instrucción INSERT o UPDATE anterior. Utilice esta función después de haber realizado una instrucción INSERT en una tabla que contiene un campo AUTO_INCREMENT, o haya utilizado INSERT o UPDATE para establecer un valor de columna con LAST_INSERT_ID (expr).
La razón de las diferencias entre LAST_INSERT_ID () y mysql_insert_id () es que LAST_INSERT_ID () se hace fácil de usar en scripts mientras mysql_insert_id () intenta proporcionar información más exacta sobre lo que sucede en la columna AUTO_INCREMENT.
Realizar una instrucción INSERT o UPDATE utilizando la función LAST_INSERT_ID () también modificará el valor devuelto por la función mysqli_insert_id ().
Poniendolo todo junto:
$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();
}
(Para su información, la clase DB está aquí ).
Este es el mismo método que la respuesta de Salman A, pero aquí está el código que realmente necesita para hacerlo.
Primero, edite su tabla para que realice un seguimiento automático de cada vez que se modifique una fila. Elimine la última línea si solo desea saber cuándo se insertó inicialmente una fila.
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
Luego, para averiguar la última fila actualizada, puede usar este código.
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
Todo este código se ha eliminado de MySQL vs PostgreSQL: Agregar una columna de 'Última hora modificada' a una tabla y Manual de MySQL: Ordenar filas . Lo acabo de armar.
Consulta :
$sqlQuery = "UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
Función PHP:
function updateAndGetId($sqlQuery)
{
mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
return mysql_insert_id();
}
Es trabajo para mí;)
Más allá de la respuesta aceptada arriba
para aquellos que se preguntaban sobre :=
&=
Diferencia significativa entre :=
y =
, y es que :=
funciona como un operador de asignación variable en todas partes, mientras=
solo funciona de esa manera en las instrucciones SET, y es un operador de comparación en cualquier otro lugar.
Por SELECT @var = 1 + 1;
lo tanto , dejará @var
sin cambios y devolverá un valor booleano (1 o 0 según el valor actual de @var), mientras SELECT @var := 1 + 1;
que cambiará @var
a 2 y devolverá 2 .
[Fuente]
Oye, solo necesitaba un truco: lo resolví de una manera diferente, tal vez funcione para ti. Tenga en cuenta que esta no es una solución escalable y será muy mala para grandes conjuntos de datos.
Divida su consulta en dos partes:
primero, seleccione los identificadores de las filas que desea actualizar y guárdelos en una tabla temporal.
segundo, realice la actualización original con la condición en la declaración de actualización cambiada a where id in temp_table
.
Y para garantizar la concurrencia, debe bloquear la tabla antes de estos dos pasos y luego liberar el bloqueo al final.
Nuevamente, esto funciona para mí, para una consulta que termina con limit 1
, por lo que ni siquiera uso una tabla temporal, sino simplemente una variable para almacenar el resultado de la primeraselect
.
Prefiero este método porque sé que siempre actualizaré solo una fila, y el código es sencillo.
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;
Tuve que CASTAR la identificación (no sé por qué) ... o no puedo obtener el contenido de @uids (fue una gota) Por cierto, ¡muchas gracias por la respuesta de Pomyk!
El ID de la última fila actualizada es el mismo ID que usa en 'updateQuery' para encontrar y actualizar esa fila. Por lo tanto, solo guarde (llame) esa ID de la forma que desee.
last_insert_id()
depende de AUTO_INCREMENT
, pero la última ID actualizada no.
Mi solución es, primero decidir el "id" (@uids) con el comando select y luego actualizar este id con @uids.
SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;
Funcionó en mi proyecto.
Si solo está haciendo inserciones y desea una de la misma sesión, hágalo según la respuesta de peirix. Si está realizando modificaciones, deberá modificar el esquema de su base de datos para almacenar qué entrada se actualizó más recientemente.
Si desea la identificación de la última modificación, que puede haber sido de una sesión diferente (es decir, no la que acaba de hacer el código PHP que se está ejecutando actualmente, sino una respuesta a una solicitud diferente), puede agregar un Columna TIMESTAMP en su tabla llamada last_modified (consulte http://dev.mysql.com/doc/refman/5.1/en/datetime.html para obtener información) y luego, cuando actualice, configure last_modified = CURRENT_TIME.
Una vez configurado esto, puede usar una consulta como: SELECCIONAR ID de la tabla ORDER BY last_modified DESC LIMIT 1; para obtener la fila modificada más recientemente.