Ottieni il nuovo ID chiave primaria record dalla query di inserimento mysql?


249

Ok, quindi diciamo che sto facendo un mysql INSERTin una delle mie tabelle e la tabella ha la colonna item_idche è impostata su autoincremente primary key.

Come posso ottenere la query per generare il valore della chiave primaria appena generata item_idnella stessa query?

Attualmente sto eseguendo una seconda query per recuperare l'id, ma questa non sembra quasi una buona pratica considerando che potrebbe produrre il risultato sbagliato ...

Se ciò non è possibile, quali sono le migliori pratiche per garantire il recupero dell'ID corretto?


1
Non c'è modo di restituire nulla da una INSERTquery del genere; perché pensi che potrebbe produrre il risultato sbagliato?
Esplosione di pillole

4
Bene, se il processo viene eseguito separatamente da 2 persone, allora potresti ottenere un elenco di processi sovrapposti credo - dal momento che devi eseguire 2 query separate?
Amy Neville,


@JimFell sì, è sostanzialmente la stessa domanda, ma questa ha risposte molto migliori in generale
RozzA

1
Usa postgresql, quindi fai come segue INSERT INTO table (col1, col2) VALUES (val1, val2) RETURNING id o INSERT INTO table (col1, col2) VALUES (val1, val2) RETURNING * o UPDATE table SET col1 = val1, col2 = val2 Istruzione WHERE RETURNING id o UPDATE tabella SET (col1, col2) = (val1, val2) Istruzione WHERE RETURNING id o UPDATE tabella SET (col1, col2) = (val1, col2) Istruzione WHERE RETURNING *
gdarcan

Risposte:


327

È necessario utilizzare la LAST_INSERT_ID()funzione: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

Per esempio:

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

Questo ti restituirà il PRIMARY KEYvalore dell'ultima riga che hai inserito:

L'ID che è stato generato viene gestito nel server in base alla connessione . Ciò significa che il valore restituito dalla funzione a un determinato client è il primo valore AUTO_INCREMENT generato per l'ultima istruzione che interessa una colonna AUTO_INCREMENT da quel client .

Quindi il valore restituito da LAST_INSERT_ID()è per utente e non è influenzato da altre query che potrebbero essere in esecuzione sul server da altri utenti .


8
sì, e se nel frattempo (tra le query nell'elenco dei processi) fosse stata inserita un'altra riga? C'è un modo per scrivere la query di inserimento in modo che emetta questo?
Amy Neville,

Ok, vedo ... l'ultimo ID di inserimento della query viene registrato anche se non è registrato nel risultato ... $ mysqli-> insert_id
Amy Neville

27
Questo ti riporterà il PRIMARY KEYvalore dell'ultima riga che hai inserito, perché è per connessione - ogni connessione al server manterrà il proprio valore per questo. Ho aggiornato la risposta per chiarire questo.
Duncan Lock,

Supponiamo quindi che 3 utenti abbiano pubblicato contemporaneamente i loro moduli e che il mio database debba inserirli. Voglio aggiungere una riga corrispondente a ciascun ID appena creato di table1 in table2. La concorrenza è curata o dovrò farlo manualmente in PHP, per le richieste di scrittura del database in arrivo?
bad_keypoints

Se, nel momento in cui si esegue l'inserimento di table1, il database conosce tutte le informazioni che si desidera inserire in table2, è possibile utilizzare un trigger per eseguire questa operazione o combinarlo in una query. In caso contrario, dovrai utilizzare più query, ad esempio farlo in PHP. Dipende da quali sono i dati e da dove provengono per il secondo inserto.
Duncan Lock,

21

ATTENZIONE !! di "LAST_INSERT_ID ()" se si tenta di restituire questo valore di chiave primaria all'interno di PHP.

So che questo thread non è taggato php, ma per chiunque abbia trovato questa risposta cercando di restituire un ID inserto MySQL da un inserto con script PHP usando chiamate mysql_query standard - non funzionerà e non è ovvio senza acquisire errori SQL.

Il più recente mysqli supporta più query, che LAST_INSERT_ID () è in realtà una seconda query dall'originale.

IMO un SELECT separato per identificare l'ultima chiave primaria è più sicuro della funzione opzionale mysql_insert_id () che restituisce l'ID AUTO_INCREMENT generato dall'operazione INSERT precedente.


7
LAST_INSERT_IDè una funzione MySQL per connessione. Se si esegue una query per l'ultimo ID di inserimento, è possibile che una connessione separata abbia eseguito una scrittura e si avrà l'ID errato.
Pillole di esplosione

@ExplosionPills mysql_insert_id()funziona anche in base alla connessione, ma soffre anche di comportamenti strani come visto qui stackoverflow.com/a/897374/1305910 nel commento di Cliffordlife - non importa che avremmo dovuto usare tuttimysqli
RozzA

puoi chiarire cosa intendi quando rimani "non funzionerà"?
john ktejik,

18

Dalla LAST_INSERT_ID()documentazione:

L'ID che è stato generato viene gestito nel server in base alla connessione

Cioè se hai due richieste separate allo script simultaneamente, queste non si influenzeranno a vicenda LAST_INSERT_ID()(a meno che tu non stia usando una connessione persistente forse).


2
Penso che sia discutibile se la tua tabella ha un trigger che inserisce in un'altra tabella .... LAST_INSERT_ID () restituirà il valore ID dell'altra tabella ..
bgies

15

Ecco cosa stai cercando !!!

select LAST_INSERT_ID()

Questa è la migliore alternativa alla SCOPE_IDENTITY()funzione utilizzata in SQL Server.

È inoltre necessario tenere presente che funzionerà solo se Last_INSERT_ID()viene attivato dalla Insertquery. Cioè la query restituisce l'id inserito nello schema. Non è possibile ottenere l'ultimo ID inserito della tabella specifica.

Per maggiori dettagli, consultare il link L'equivalente della funzione SQLServer SCOPE_IDENTITY () in mySQL?


6

Se è necessario il valore prima di inserire una riga:

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

Puoi usarlo in un inserto:

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

1
Questa non sembra essere una buona idea? Se 2 client chiamano quella funzione contemporaneamente, penseranno di inserire lo stesso ID quando in realtà non lo sono .... uno sarà leggermente più lento sull'inserto e otterrà l'ID successivo senza che lo sappia.
Cárcar

5

Riceverai questi parametri sul risultato della tua query:

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

Il insertIdè esattamente quello che ti serve.

(NodeJS-mysql)


4

Se in Python si utilizza pymysql, dal cursore è possibile utilizzare cursor.lastrowid


2

usa semplicemente "$ last_id = mysqli_insert_id ($ conn);"


2
In realtà sono inciampato qui cercando la versione php di questa risposta grazie a Google, quindi ho votato questa risposta. Mentre tecnicamente l'OP non ha richiesto php, questo potrebbe essere utile a molte persone che inciampano anche qui.
Fotografo Britt

Grazie mille Arnav! I
JuanSedano,

1

Se stai usando PHP: su un oggetto PDO puoi semplicemente invocare il metodo lastInsertId dopo l'inserimento.

Altrimenti con un LAST_INSERT_ID puoi ottenere il valore in questo modo:SELECT LAST_INSERT_ID();



0

Voglio solo condividere il mio approccio a questo in PHP, alcuni di voi potrebbero trovarlo non un modo efficiente ma questo è un 100 migliore rispetto ad altre opzioni disponibili.

genera una chiave casuale e inseriscila nella tabella creando una nuova riga. quindi è possibile utilizzare quella chiave per recuperare la chiave primaria. usa l'aggiornamento per aggiungere dati e fare altre cose.

in questo modo è possibile proteggere una riga e disporre della chiave primaria corretta.

Non lo consiglio davvero a meno che tu non abbia altre opzioni.

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.