Come ottenere il prossimo ID di incremento automatico in mysql


114

Come ottenere il prossimo id in mysql per inserirlo nella tabella

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

1
usa una auto_incrementcolonna
maglia il

Vuoi l' ID successivo o l'ID della riga che stai attualmente inserendo? Cioè, l'id alla fine del codice di pagamento dovrebbe essere l'id della riga in cui è memorizzato il codice di pagamento?
Mike

id della riga che sto attualmente inserendo
faressoft

6
In tal caso, concatena i valori quando li recuperi, non quando li inserisci. È molto più facile in questo modo, ed escludi di ottenere l'ID sbagliato o di dover eseguire un aggiornamento: pensa a cosa accadrebbe se la riga che hai appena inserito fosse richiesta da un altro client, prima che l'aggiornamento abbia avuto la possibilità di essere eseguito: il client finirebbe con un codice di pagamento non valido. Su un sistema a basso traffico, ciò potrebbe non accadere, ma non vedo il motivo per correre il rischio.
Mike

... o come sottolinea @binaryLV, anche il blocco delle risorse potrebbe risolvere il problema. Vedi: dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Mike

Risposte:


12

Usa LAST_INSERT_ID()dalla tua query SQL.

O

Puoi anche usarlo mysql_insert_id()per ottenerlo usando PHP.


13
@ Sarfraz: La domanda riguardava l' ID SUCCESSIVO, non l' ULTIMO come hai detto menzionando LAST_INSERT_ID().
Felipe Pereira

1
Se le righe vengono eliminate nella tabella, il valore massimo sarà errato
peterchaula

solo una nota dal '17 - le funzioni mysql * sono deprecate - sopra può essere fatto conmysqli_insert_id
treyBake

chi l'ha contrassegnato come risposta? la domanda riguarda il prossimo ID di inserimento non ultimo.
Amit Shah

253

Puoi usare

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

o se non desideri utilizzare information_schema puoi usarlo

SHOW TABLE STATUS LIKE 'table_name'

Grazie per le prime due opzioni .. Ma il terzo è solo il numero due chiamato da PHP .. Non sono sicuro di cosa lo renda più veloce su database di grandi dimensioni ...
Gerard ONeill

1
@GerardONeill Rimosso
ravi404

3
poiché una cache viene utilizzata per recuperare i dati da information_schema.tables, questa soluzione non funziona più per mysql 8.
Bruno

1
@Bruno puoi inserire un riferimento?
mvorisek

1
Questo documento ufficiale dichiara che TABLES.AUTO_INCREMENTè memorizzato nella cache dev.mysql.com/doc/refman/8.0/en/… . Il blog Mysql ha anche diversi post a riguardo, ma il sistema che menzionano sembra obsoleto: mysqlserverteam.com/… mysqlserverteam.com/…
Bruno

50

Puoi ottenere il valore di incremento automatico successivo facendo:

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

Si noti che è necessario non usare questo per modificare la tabella, utilizzare una colonna AUTO_INCREMENT per farlo automaticamente, invece.
Il problema è che last_insert_id()è retroattivo e può quindi essere garantito nell'ambito dell'attuale connessione.
Questo bambino è potenziale e quindi non è unico per connessione e non può essere invocato.
Funzionerebbe solo in un singolo database di connessione, ma i database di connessione singola oggi hanno l'abitudine di diventare domani più database di connessione.

Vedere: SHOW TABLE STATUS


5
Non l'ho votato per difetto, ma il problema con il tentativo di utilizzare l'ultimo valore di incremento automatico è che potrebbe non essere l'ultimo nel momento in cui lo utilizzerai, indipendentemente dalla velocità con cui vengono eseguiti SELECT e il successivo INSERT.
Mike

@ Mike, cosa succede se viene eseguita in una singola query? Qualcosa di simile insert into table_name (field1, field2) select 'constant', auto_increment from information_schema.tables where table_name = 'table_name'? after insertlast_insert_id()
Userei l'

1
@binaryLV: minore è lo spazio tra SELECT e INSERT, minore è la possibilità che il valore sia cambiato, ma non lo esclude completamente. Immagina un sistema con migliaia di accessi al minuto sul database: le possibilità che il valore sia cambiato aumentano notevolmente. Il blocco di tabelle o righe può impedirlo se viene eseguito come una singola query, ma si basa su un comportamento particolare del motore di database che potrebbe non essere ben documentato. Andrei con un successivo UPDATEse lo avessi fatto anch'io. Ma preferisco solo concatenare i due al momento della visualizzazione e risparmiare tutta la seccatura.
Mike

3
SHOW TABLE STATUSsi aspetta di vedere database namedopo FROMe 'table name pattern'dopo LIKE.
x-yuri

2
poiché una cache viene utilizzata per recuperare i dati da information_schema.tables, questa soluzione non funziona più per mysql 8.
Bruno

15

Questo restituirà il valore di incremento automatico per il database MySQL e non ho controllato con altri database. Si noti che se si utilizza qualsiasi altro database, la sintassi della query potrebbe essere diversa.

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();

SELEZIONA INCREMENTO_UTENTE DA information_schema.tables WHERE table_name = 'your_table_name' e table_schema = 'your_database_name';
LJay

10

La risposta principale utilizza PHP MySQL_ per una soluzione, ho pensato di condividere una soluzione PHP MySQLi_ aggiornata per raggiungere questo obiettivo. Non vi è alcun output di errore in questo esempio!

$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'];

Esegue il successivo incremento automatico in arrivo in una tabella.


poiché una cache viene utilizzata per recuperare i dati da information_schema.tables, questa soluzione non funziona più per mysql 8.
Bruno

9

In PHP puoi provare questo:

$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
Tieni presente che con il primo metodo se il record con l'id più alto viene eliminato, creerai quindi un nuovo record con l'id che aveva quello eliminato.
Tom Jenkinson

e se la chiave precedente è stata utilizzata in altre tabelle ed è ancora conservata lì, puoi finire con una magia molto strana
Tebe

il primo restituisce un ID sbagliato se si rilascia l'ultimo record inserito,
Ali Parsa

6

Soluzione:

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" è il nome del nostro Data Base


5

Una semplice query andrebbe bene SHOW TABLE STATUS LIKE 'table_name'



3

Non puoi utilizzare l'ID durante l'inserimento, né ne hai bisogno. MySQL non conosce nemmeno l'ID quando inserisci quel record. Potresti semplicemente salvare "sahf4d2fdd45"nella payment_codetabella e utilizzare ide in payment_codeseguito.

Se hai davvero bisogno che il tuo payment_code contenga l'ID, AGGIORNA la riga dopo l'inserimento per aggiungere l'ID.


+1 Per renderlo un po 'più esplicito: se prendi il valore "più recente" da una colonna, è garantito che sarà l'ultimo valore solo nel momento esatto in cui lo prendi. Potrebbe non essere l'ultimo valore quando si utilizza quel valore in un inserimento successivo. Nel caso di una colonna di incremento automatico, c'è sempre la possibilità che sia stato aggiunto un altro valore tra il momento in cui hai recuperato l'id e il momento in cui lo inserisci altrove. Se stai facendo riferimento a una riga che hai appena inserito, usare LAST_INSERT_ID () va bene. Se stai cercando di garantire un valore univoco, non lo è.
Mike

@cularis, MySQL conosce il prossimo id auto_increment, è elencato nella information_schema.tablestabella.
Johan

1
@faressoft: se l'idea è di avere un codice di pagamento che comprenda una stringa univoca più l'id della riga che contiene quel codice di pagamento, combina i due quando recuperi la riga, con a SELECT ... CONCAT(payment_code, id)o nel codice dell'applicazione. Puoi anche racchiudere il SELECTin un VIEW, in modo da restituire sempre il valore corretto, senza preoccuparti del CONCAT in ogni SELECT dalla tua app.
Mike

3

A cosa serve il prossimo ID incrementale?

MySQL consente solo un campo di incremento automatico per tabella e deve anche essere la chiave primaria per garantire l'unicità.

Tieni presente che quando ottieni l'ID di inserimento successivo, potrebbe non essere disponibile quando lo utilizzi poiché il valore che hai è solo nell'ambito di quella transazione. Pertanto, a seconda del carico sul database, tale valore potrebbe essere già utilizzato al momento dell'arrivo della richiesta successiva.

Ti suggerisco di rivedere il tuo progetto per assicurarti di non aver bisogno di sapere quale valore di incremento automatico assegnare successivamente


Non è una buona idea assumere il tipo di applicazione che richiede l'ID. Ci sono applicazioni come quella su cui sto lavorando al momento che necessita del successivo ID incrementale e il valore recuperato non corre il rischio di essere assegnato a un altro script.
JG Estiot

3

Suggerisco di ripensare a quello che stai facendo. Non ho mai sperimentato un singolo caso d'uso in cui è richiesta quella conoscenza speciale. Il prossimo ID è un dettaglio di implementazione molto speciale e non conterei sul fatto che sia ACID sicuro.

Effettua una semplice transazione che aggiorna la riga inserita con l'ultimo ID:

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;

Posso dire a uno di questi casi d'uso, sto cercando di diagnosticare un problema di produzione, quindi devo scoprire se l'ultima riga in una tabella è davvero l'ultima riga o se ne è stata aggiunta una dopo quella che in qualche modo è stata eliminata, tabella contiene un campo auto_increment, quindi trovando queste informazioni posso concludere se la riga è stata eliminata o non è mai stata aggiunta.
Usman

1
Potrebbe forse funzionare per te, ma non ci farei affidamento perché non credo che tu abbia alcuna garanzia su questo: dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html " quando la colonna AUTO_INCREMENT fa parte di un indice a più colonne), i valori AUTO_INCREMENT vengono riutilizzati se si elimina la riga con il valore AUTO_INCREMENT più grande in qualsiasi gruppo. "
Markus Malkusch

Grazie, informazione utile, inoltre secondo il tuo link condiviso auto_increment può essere resettato inserendo manualmente un numero, quindi sì non affidabile.
Usman

2

Devi connetterti a MySQL e selezionare un database prima di poterlo fare

$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

usa "mysql_insert_id ()". mysql_insert_id () agisce sull'ultima query eseguita, assicurati di chiamare mysql_insert_id () immediatamente dopo la query che genera il valore.

Di seguito gli esempi di utilizzo:

<?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());
    ?>

Spero che l'esempio sopra sia utile.


Grazie ne sono consapevole.
signor Javed Multani


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

Anche se dubito della sua produttività, ma è affidabile al 100%


Anch'io sono d'accordo che questo è l'approccio più semplice. Non sono sicuro del motivo per cui sei stato votato verso il basso, ma compenserò con un voto positivo.
ricorso

Non ho menzionato la necessità della transazione, se non lo avvolgi nella transazione questo codice è scadente al più presto incontra il caricamento reale.
Tebe

1
E se l'ultima riga fosse stata eliminata? O più righe più recenti sono state eliminate?
Liam W

Le chiavi non emesse e liberate non vengono utilizzate a meno che tu non lo specifichi esplicitamente
Tebe

1

usando la risposta di 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

utilizzando nella tua query di inserimento, per creare un hash SHA1. ex.:

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

Funziona sempre? Ci sono condizioni di gara se due inserti avvengono contemporaneamente?
Jmons

0

Miglioramento di @ ravi404, nel caso in cui l'offset dell'incremento automatico NON È 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): il motore db sembra considerare sempre un offset di 1. Quindi è necessario abbandonare questo presupposto, quindi aggiungere il valore opzionale di @@ auto_increment_offset o il valore predefinito a 1: IFNULL (@@ auto_increment_offset, 1)


0

Per me funziona e sembra semplice:

 $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

Abbastanza inutile assegnare $last_idripetutamente quando puoi semplicemente DESC. Il tuo whileblocco ha fatto un sacco di lavoro inutile.
Tiw

sì, giusto ... mi sono appena reso conto che non è perfetto ... :( alla fine si può ripetere l'id, se è stato cancellato prima ... :(
Toncsiking

0

Se non restituisce AUTO_INCREMENT corretto, provalo:

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

Questa cache libera per la tabella, in BD

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.