Cómo obtener la siguiente identificación de incremento automático en mysql


113

Cómo obtener la siguiente identificación en mysql para insertarla en la tabla

INSERT INTO payments (date, item, method, payment_code)
VALUES (NOW(), '1 Month', 'paypal', CONCAT("sahf4d2fdd45", id))

1
use una auto_incrementcolumna
knittl

¿Quiere la siguiente identificación o la identificación de la fila que está insertando actualmente? Es decir, ¿la identificación al final del código de pago debería ser la identificación de la fila en la que se almacena el código de pago?
Mike

id de la fila que estoy insertando actualmente
faressoft

6
En ese caso, concatene los valores cuando los recupere, no cuando los inserte. Es mucho más fácil de esa manera, y descarta obtener la identificación incorrecta o tener que ejecutar una actualización; piense en lo que sucedería si otro cliente solicita la fila que acaba de insertar, antes de que la actualización haya tenido la oportunidad de ejecutarse: el cliente terminaría con un código de pago no válido. En un sistema de poco tráfico, eso podría no ocurrir, pero no veo el sentido de correr el riesgo.
Mike

... o como señala @binaryLV, el bloqueo de recursos también podría resolver el problema. Ver: dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Mike

Respuestas:


12

Úselo LAST_INSERT_ID()desde su consulta SQL.

O

También puede usar mysql_insert_id()para obtenerlo usando PHP.


13
@Sarfraz: La pregunta era sobre el ID SIGUIENTE, no el ÚLTIMO como dijiste al mencionar LAST_INSERT_ID().
Felipe Pereira

1
Si las filas se eliminan en la tabla, el máximo será incorrecto
peterchaula

solo una nota del '17 - las funciones de mysql * están en desuso - lo anterior se puede hacer conmysqli_insert_id
treyBake

¿Quién marcó esto como respuesta? la pregunta es sobre la siguiente identificación de inserción, no la última.
Amit Shah

252

Puedes usar

SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'table_name'
AND table_schema = DATABASE( ) ;

o si no desea utilizar information_schema, puede utilizar este

SHOW TABLE STATUS LIKE 'table_name'

Gracias por las dos primeras opciones ... Pero la tercera es solo la número dos llamada desde PHP ... No estoy seguro de qué lo hace más rápido en bases de datos grandes ...
Gerard ONeill

1
@GerardONeill lo eliminó
ravi404

3
debido a que se usa un caché para recuperar los datos de information_schema.tables, esta solución ya no funciona para mysql 8.
Bruno

1
@Bruno, ¿puedes publicar una referencia?
mvorisek

1
Este documento oficial indica que TABLES.AUTO_INCREMENTse almacena en caché dev.mysql.com/doc/refman/8.0/en/… . El blog de Mysql también tiene varias publicaciones al respecto, pero la variable del sistema que mencionan parece obsoleta: mysqlserverteam.com/… mysqlserverteam.com/…
Bruno

50

Puede obtener el siguiente valor de incremento automático haciendo lo siguiente:

SHOW TABLE STATUS FROM tablename LIKE Auto_increment
/*or*/
SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = 'tablename'

Tenga en cuenta que usted debe no usar esto para modificar la tabla, utilice una columna AUTO_INCREMENT de hacerlo de forma automática en su lugar.
El problema es que last_insert_id()es retrospectivo y, por tanto, se puede garantizar dentro de la conexión actual.
Este bebé es prospectivo y, por lo tanto, no es único por conexión y no se puede confiar en él.
Solo en una base de datos de conexión única funcionaría, pero las bases de datos de conexión única de hoy tienen la costumbre de convertirse en bases de datos de conexión múltiple mañana.

Ver: SHOW TABLE STATUS


5
No lo rechacé, pero el problema al intentar usar el último valor de incremento automático es que puede que no sea el último en el momento en que lo use, sin importar qué tan rápido se lleve a cabo SELECT y el INSERT subsiguiente.
Mike

@ Mike, ¿y si se hace en una sola consulta? Algo como insert into table_name (field1, field2) select 'constant', auto_increment from information_schema.tables where table_name = 'table_name'? after insertlast_insert_id()
Usaría la

1
@binaryLV: cuanto menor sea la brecha entre SELECT e INSERT, menor será la posibilidad de que el valor haya cambiado, pero no lo descarta por completo. Imagine un sistema con miles de visitas por minuto en la base de datos: las posibilidades de que el valor haya cambiado aumentan drásticamente. El bloqueo de tablas o filas puede evitar esto si se realiza como una consulta única, pero eso depende de un comportamiento particular del motor de la base de datos que puede no estar bien documentado. Yo iría con una subsecuente UPDATEsi tuviera también. Pero prefiero concatenar los dos en el momento de la visualización y ahorrar toda la molestia.
Mike

3
SHOW TABLE STATUSespera ver database namedespués FROMy 'table name pattern'después LIKE.
x-yuri

2
debido a que se usa un caché para recuperar los datos de information_schema.tables, esta solución ya no funciona para mysql 8.
Bruno

15

Esto devolverá el valor de incremento automático para la base de datos MySQL y no verifiqué con otras bases de datos. Tenga en cuenta que si está utilizando cualquier otra base de datos, la sintaxis de la consulta puede ser diferente.

SELECT AUTO_INCREMENT 
FROM information_schema.tables
WHERE table_name = 'your_table_name'
     and table_schema = 'your_database_name';

SELECT AUTO_INCREMENT 
FROM information_schema.tables
WHERE table_name = 'your_table_name'
     and table_schema = database();

SELECCIONE AUTO_INCREMENT FROM information_schema.tables DONDE table_name = 'your_table_name' y table_schema = 'your_database_name';
LJay

10

La respuesta principal usa PHP MySQL_ para una solución, pensé que compartiría una solución PHP MySQLi_ actualizada para lograr esto. ¡No hay salida de error en este ejemplo!

$db = new mysqli('localhost', 'user', 'pass', 'database');
$sql = "SHOW TABLE STATUS LIKE 'table'";
$result=$db->query($sql);
$row = $result->fetch_assoc();

echo $row['Auto_increment'];

Lanza el siguiente incremento automático que aparece en una tabla.


debido a que se usa un caché para recuperar los datos de information_schema.tables, esta solución ya no funciona para mysql 8.
Bruno

9

En PHP puedes probar esto:

$query = mysql_query("SELECT MAX(id) FROM `your_table_name`");
$results = mysql_fetch_array($query);
$cur_auto_id = $results['MAX(id)'] + 1;

O

$result = mysql_query("SHOW TABLE STATUS WHERE `Name` = 'your_table_name'");
$data = mysql_fetch_assoc($result);
$next_increment = $data['Auto_increment'];

5
Tenga en cuenta que con el primer método, si se elimina el registro con la identificación más alta, luego creará un nuevo registro con la identificación que solía tener el que se eliminó.
Tom Jenkinson

y si la clave anterior se usó en otras tablas y aún se mantiene allí, puede terminar con una magia muy extraña
Tebe

el primero devuelve una identificación incorrecta si elimina el último registro insertado,
Ali Parsa

6

Solución:

CREATE TRIGGER `IdTrigger` BEFORE INSERT ON `payments`
  FOR EACH ROW
BEGIN

SELECT  AUTO_INCREMENT Into @xId
    FROM information_schema.tables
    WHERE 
    Table_SCHEMA ="DataBaseName" AND
    table_name = "payments";

SET NEW.`payment_code` = CONCAT("sahf4d2fdd45",@xId);

END;

"DataBaseName" es el nombre de nuestra base de datos


5

Una consulta simple haría SHOW TABLE STATUS LIKE 'table_name'



3

No puede usar el ID mientras lo inserta, ni tampoco lo necesita. MySQL ni siquiera conoce el ID cuando inserta ese registro. Podrías simplemente guardar "sahf4d2fdd45"en la payment_codetabla y usar idy payment_codemás adelante.

Si realmente necesita que su payment_code tenga la ID, ACTUALICE la fila después de la inserción para agregar la ID.


+1 Para hacer esto un poco más explícito: si toma el valor 'último' de una columna, solo se garantiza que sea el valor más reciente en el momento exacto en que lo toma. Puede que no sea el último valor cuando se utiliza ese valor en una inserción posterior. En el caso de una columna de incremento automático, siempre existe la posibilidad de que se haya agregado otro valor entre el momento en que recuperó la identificación y el momento en que lo inserta en otro lugar. Si está haciendo referencia a una fila que acaba de insertar, usar LAST_INSERT_ID () está bien. Si está tratando de garantizar un valor único, no lo es.
Mike

@cularis, MySQL conoce la siguiente identificación de auto_increment, está listada en la information_schema.tablestabla.
Johan

1
@faressoft: Si la idea es tener un código de pago que comprenda una cadena única más la identificación de la fila que contiene ese código de pago, simplemente combine los dos cuando recupere la fila, ya sea con a SELECT ... CONCAT(payment_code, id), o en su código de aplicación. Incluso puede envolver el SELECTen a VIEW, para que siempre devuelva el valor correcto, sin preocuparse por el CONCAT en cada SELECCIÓN de su aplicación.
Mike

3

¿Para qué necesita el próximo ID incremental?

MySQL solo permite un campo de incremento automático por tabla y también debe ser la clave principal para garantizar la exclusividad.

Tenga en cuenta que cuando obtenga el siguiente ID de inserción, es posible que no esté disponible cuando lo use, ya que el valor que tiene está solo dentro del alcance de esa transacción. Por lo tanto, dependiendo de la carga en su base de datos, es posible que ese valor ya se haya utilizado para cuando llegue la siguiente solicitud.

Le sugiero que revise su diseño para asegurarse de que no necesita saber qué valor de incremento automático asignar a continuación


No es una buena idea asumir el tipo de aplicación que requiere la identificación. Hay aplicaciones como en la que estoy trabajando en este momento que necesita la siguiente ID incremental y el valor recuperado no corre peligro de ser asignado a otro script.
JG Estiot

3

Sugiero que reconsidere lo que está haciendo. Nunca experimenté un solo caso de uso en el que se requiera ese conocimiento especial. La siguiente identificación es un detalle de implementación muy especial y no contaría con que sea seguro para ACID.

Haga una transacción simple que actualice su fila insertada con la última identificación:

BEGIN;

INSERT INTO payments (date, item, method)
     VALUES (NOW(), '1 Month', 'paypal');

UPDATE payments SET payment_code = CONCAT("sahf4d2fdd45", LAST_INSERT_ID())
     WHERE id = LAST_INSERT_ID();

COMMIT;

Puedo decir uno de esos casos de uso, estoy tratando de diagnosticar un problema de producción, por lo que necesito averiguar si la última fila de una tabla es realmente la última fila o si se agregó una después de la que de alguna manera se eliminó, tabla tiene un campo auto_increment, por lo que al encontrar esta información puedo concluir si la fila se eliminó o nunca se agregó.
Usman

1
Eso podría funcionar para usted, pero no confiaría en eso ya que no creo que tenga ninguna garantía al respecto: dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html " cuando la columna AUTO_INCREMENT es parte de un índice de varias columnas), los valores de AUTO_INCREMENT se reutilizan si elimina la fila con el valor de AUTO_INCREMENT más grande en cualquier grupo ".
Markus Malkusch

Gracias, información útil, también según su enlace compartido, auto_increment se puede restablecer insertando manualmente un número, así que sí, no es confiable.
Usman

2

Tiene que conectarse a MySQL y seleccionar una base de datos antes de poder hacer esto

$table_name = "myTable"; 
$query = mysql_query("SHOW TABLE STATUS WHERE name='$table_name'"); 
$row = mysql_fetch_array($query); 
$next_inc_value = $row["AUTO_INCREMENT"];  

2

utilice "mysql_insert_id ()". mysql_insert_id () actúa sobre la última consulta realizada, asegúrese de llamar a mysql_insert_id () inmediatamente después de la consulta que genera el valor.

A continuación se muestra el ejemplo de uso:

<?php
    $link = mysql_connect('localhost', 'username', 'password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');

mysql_query("INSERT INTO mytable  VALUES('','value')");
printf("Last inserted record has id %d\n", mysql_insert_id());
    ?>

Espero que el ejemplo anterior sea útil.


Gracias, lo sé.
Mr.Javed Multani


1
SELECT id FROM `table` ORDER BY id DESC LIMIT 1

Aunque dudo de su productividad pero es 100% confiable


Yo también estoy de acuerdo en que este es el enfoque más simple. No estoy seguro de por qué fue rechazado, pero lo compensaré con un voto a favor.
recurse

No mencioné la necesidad de la transacción, si no lo envuelve dentro de la transacción, este código es pésimo lo antes posible que se encuentre con una carga real.
Tebe

1
¿Qué pasa si se eliminó la última fila? ¿O se han eliminado varias filas más recientes?
Liam W

Las claves liberadas que no son de emisión no se usan a menos que lo especifique explícitamente
Tebe

1

usando la respuesta de ravi404:

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

usando en su consulta de inserción, para crear un Hash SHA1. ex.:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( getAutoincrementalNextval ('document') ),
    'Title',
    'Body'
);

¿Esto siempre funciona? ¿Existe una condición de carrera si se realizan dos inserciones al mismo tiempo?
Jmons

0

Mejora de @ ravi404, en caso de que su compensación de autoincremento NO ES 1:

SELECT (`auto_increment`-1) + IFNULL(@@auto_increment_offset,1) 
FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = your_table_name
AND table_schema = DATABASE( );

( auto_increment-1): db engine parece que siempre considera un desplazamiento de 1. Por lo tanto, debe deshacerse de esta suposición, luego agregar el valor opcional de @@ auto_increment_offset, o por defecto a 1: IFNULL (@@ auto_increment_offset, 1)


0

Para mí funciona y parece simple:

 $auto_inc_db = mysql_query("SELECT * FROM my_table_name  ORDER BY  id  ASC ");
 while($auto_inc_result = mysql_fetch_array($auto_inc_db))
 {
 $last_id = $auto_inc_result['id'];
 }
 $next_id = ($last_id+1);


 echo $next_id;//this is the new id, if auto increment is on

Bastante innecesario asignar $last_idrepetidamente cuando puede DESC. Tu whilebloque hizo un montón de trabajo inútil.
Tiw

sí, claro ... Me acabo de dar cuenta de que no es perfecto ... :( final, uno puede repetir la identificación, si se eliminó antes ... :(
Toncsiking

0

Si no devuelve AUTO_INCREMENT correcto, inténtelo:

ANALYZE TABLE `my_table`;
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE (TABLE_NAME = 'my_table');

Esta caché clara para la tabla, en BD

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.