¿Obtener el nuevo ID de la clave primaria de registro de la consulta de inserción mysql?


249

Ok, digamos que estoy haciendo un mysql INSERTen una de mis tablas y la tabla tiene la columna item_idque está configurada en autoincrementy primary key.

¿Cómo consigo que la consulta muestre el valor de la clave primaria recién generada item_iden la misma consulta?

Actualmente estoy ejecutando una segunda consulta para recuperar la identificación, pero esto no parece una buena práctica teniendo en cuenta que esto podría producir un resultado incorrecto ...

Si esto no es posible, ¿cuál es la mejor práctica para garantizar que recupere la identificación correcta?


1
No hay forma de devolver nada de una INSERTconsulta como esa; ¿Por qué crees que podría producir un resultado incorrecto?
Píldoras de explosión

44
Bueno, si el proceso es ejecutado por 2 personas por separado, creo que podría obtener una lista de procesos superpuestos, ya que debe ejecutar 2 consultas separadas.
Amy Neville


@JimFell sí, es básicamente la misma pregunta, pero esta tiene respuestas mucho mejores en general
RozzA

1
Use postgresql y luego haga lo siguiente INSERTAR EN la tabla (col1, col2) VALORES (val1, val2) ID DE RETORNO o INSERTAR EN la tabla (col1, col2) VALORES (val1, val2) RETORNO * o ACTUALIZAR la tabla SET col1 = val1, col2 = val2 Declaración WHERE ID DE RETORNO o ACTUALIZAR tabla SET (col1, col2) = (val1, val2) Declaración WHERE ID DE RETORNO o ACTUALIZAR tabla SET (col1, col2) = (val1, val2) WHERE instrucción RETURNING *
gdarcan

Respuestas:


327

Debe usar la LAST_INSERT_ID()función: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

P.ej:

INSERT INTO table_name (col1, col2,...) VALUES ('val1', 'val2'...);
SELECT LAST_INSERT_ID();

Esto le devolverá el PRIMARY KEYvalor de la última fila que se insertó:

La ID que se generó se mantiene en el servidor por conexión . Esto significa que el valor devuelto por la función a un cliente determinado es el primer valor AUTO_INCREMENT generado para la declaración más reciente que afecta a una columna AUTO_INCREMENT de ese cliente .

Por lo tanto, el valor devuelto por LAST_INSERT_ID()es por usuario y no se ve afectado por otras consultas que otros usuarios puedan estar ejecutando en el servidor .


8
sí, pero ¿qué pasa si en el ínterin (entre consultas en la lista de procesos) se ha insertado otra fila? ¿Hay alguna forma de escribir la consulta de inserción para que salga esto?
Amy Neville

Ok, ya veo ... la última identificación de inserción de la consulta se registra incluso si no está registrada en el resultado ... $ mysqli-> insert_id
Amy Neville

27
Esto le devolverá el PRIMARY KEYvalor de la última fila que se ha insertado, porque es por conexión - cada conexión al servidor mantendrá su propio valor de esta. He actualizado la respuesta para aclarar esto.
Duncan Lock

Supongamos que 3 usuarios publicaron simultáneamente sus formularios y mi base de datos tiene que ingresarlos. Quiero agregar una fila correspondiente a cada ID recién creado de table1 en table2. ¿Se soluciona la concurrencia o tendré que hacerlo en PHP manualmente para las solicitudes de escritura de la base de datos entrante?
bad_keypoints

Si, en el momento en que realiza la inserción de la tabla1, la base de datos conoce toda la información que desea insertar en la tabla2, entonces podría usar un disparador para hacer esto, o combinar esto en una consulta. Si no, entonces necesitaría usar múltiples consultas, es decir, hacerlo en PHP. Depende de cuáles sean los datos y de dónde provienen para la segunda inserción.
Duncan Lock

21

CUIDADO !! de "LAST_INSERT_ID ()" si intenta devolver este valor de clave primaria dentro de PHP.

Sé que este hilo no está etiquetado como php, pero para cualquiera que haya encontrado esta respuesta que busca devolver una identificación de inserción de MySQL desde una inserción con script PHP usando llamadas estándar mysql_query, no funcionará y no es obvio sin capturar errores de SQL.

El mysqli más nuevo admite múltiples consultas, que LAST_INSERT_ID () en realidad es una segunda consulta del original.

IMO un SELECT separado para identificar la última clave primaria es más seguro que la función opcional mysql_insert_id () que devuelve el ID de AUTO_INCREMENT generado a partir de la operación INSERT previa.


77
LAST_INSERT_IDes una función MySQL por conexión. Si consulta la última ID de inserción, es posible que una conexión separada haya realizado una escritura y tenga la ID incorrecta.
Píldoras de explosión

@ExplosionPills mysql_insert_id()también funciona por conexión, pero también sufre un comportamiento extraño como se ve aquí stackoverflow.com/a/897374/1305910 en el comentario de Cliffordlife - no importa que todos deberíamos haber estado usandomysqli
RozzA

¿Puedes aclarar a qué te refieres cuando te quedas "no funcionará"?
john ktejik

18

De la LAST_INSERT_ID()documentación:

La ID que se generó se mantiene en el servidor por conexión

Es decir, si tiene dos solicitudes separadas para el script simultáneamente, no se afectarán entre sí LAST_INSERT_ID()(a menos que esté usando una conexión persistente, tal vez).


2
Creo que es dudoso si su tabla tiene un activador que inserta en otra tabla ... LAST_INSERT_ID () devolverá el valor de id de la otra tabla ...
bgies

15

Aquí lo que buscas !!!

select LAST_INSERT_ID()

Esta es la mejor alternativa de SCOPE_IDENTITY()función utilizada SQL Server.

También debe tener en cuenta que esto solo funcionará si Last_INSERT_ID()se activa después de su Insertconsulta. Es decir, la consulta devuelve la identificación insertada en el esquema. No puede obtener la última identificación de tabla específica insertada.

Para obtener más detalles, consulte el enlace ¿ El equivalente de la función SQLServer SCOPE_IDENTITY () en mySQL?


6

Si necesita el valor antes de insertar una fila:

CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
    RETURNS BIGINT
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

    DECLARE Value BIGINT;

    SELECT
        AUTO_INCREMENT INTO Value
    FROM
        information_schema.tables
    WHERE
        table_name = TableName AND
        table_schema = DATABASE();

    RETURN Value;

END

Puede usar esto en una inserción:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);

1
¿Esta no parece ser una buena idea? Si 2 clientes llaman a esa función al mismo tiempo, pensarán que están insertando la misma identificación cuando en realidad no lo están ... uno será un poco más lento en la inserción y obtendrá la siguiente ID sin que lo sepa.
CarCar

5

Recibirá estos parámetros en el resultado de su consulta:

    "fieldCount": 0,
    "affectedRows": 1,
    "insertId": 66,
    "serverStatus": 2,
    "warningCount": 1,
    "message": "",
    "protocol41": true,
    "changedRows": 0

El insertIdes exactamente lo que necesitas.

(NodoJS-mySql)


4

Si está en Python usando pymysql, desde el cursor puede usar cursor.lastrowid


2

simplemente use "$ last_id = mysqli_insert_id ($ conn);"


2
De hecho, tropecé aquí buscando la versión php de esta respuesta gracias a Google, así que voté esta respuesta. Si bien técnicamente el OP no solicitó php, esto podría ser útil para muchas personas que también tropiezan aquí.
Fotógrafo Britt

Muchas gracias Arnav! I
JuanSedano



0

Solo quiero compartir mi enfoque sobre esto en PHP, algunos de ustedes pueden encontrar que no es una forma eficiente, pero esto es 100 mejor que otras opciones disponibles.

generar una clave aleatoria e insertarla en la tabla creando una nueva fila. entonces puede usar esa clave para recuperar la clave primaria. usa la actualización para agregar datos y hacer otras cosas.

hacer esto ayuda a asegurar una fila y a tener la clave primaria correcta.

Realmente no recomiendo esto a menos que no tenga otras opciones.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.