Come posso ottenere "id" dopo INSERT nel database MySQL con Python?


183

Eseguo un'istruzione INSERT INTO

cursor.execute("INSERT INTO mytable(height) VALUES(%s)",(height))

e voglio ottenere la chiave primaria.

La mia tabella ha 2 colonne:

id      primary, auto increment
height  this is the other column.

Come ottengo "id", dopo averlo appena inserito?


Risposte:


243

Utilizzare cursor.lastrowidper inserire l'ultimo ID riga nell'oggetto cursore o connection.insert_id()per ottenere l'ID dall'ultimo inserimento su quella connessione.


3
Che cosa succede se due processi inseriscono una riga contemporaneamente utilizzando la stessa connessione. Quale ID insert_idrestituirà?
xiaohan2012,

27
@ xiaohan2012 In che modo 2 processi utilizzano la stessa connessione?
hienbt88,

5
È lastrowiddisponibile solo dopo il commit della transazione corrente?
John Wang

4
@ hienbt88 Probabilmente intendeva i thread, l'ho fatto e può causare problemi a meno che non si utilizzi correttamente la sicurezza dei thread. Personalmente ho cercato un'istanza di una nuova connessione per ogni thread, il che è una soluzione alternativa poiché per qualche motivo il commit (in realtà autocommitting) non ha funzionato per me, ho avuto un serio intreccio a causa di molti thread simultanei che emettevano alcune query al secondo.
Milan Velebit,

Non funziona con record duplicati usando insert, select e where.
e-info128,

114

Inoltre, cursor.lastrowid(un'estensione dbapi / PEP249 supportata da MySQLdb):

>>> import MySQLdb
>>> connection = MySQLdb.connect(user='root')
>>> cursor = connection.cursor()
>>> cursor.execute('INSERT INTO sometable VALUES (...)')
1L
>>> connection.insert_id()
3L
>>> cursor.lastrowid
3L
>>> cursor.execute('SELECT last_insert_id()')
1L
>>> cursor.fetchone()
(3L,)
>>> cursor.execute('select @@identity')
1L
>>> cursor.fetchone()
(3L,)

cursor.lastrowidè un po 'più economico connection.insert_id()e molto più economico di un altro viaggio di andata e ritorno su MySQL.


4
Perché cursor.lastrowidcosta meno connection.insert_id()?
Martin Thoma,

3
Solo perché cursor.lastrowid viene automaticamente impostato sull'oggetto cursore come parte di cursor.execute () ed è solo una ricerca di attributi. connection.insert_id () è una chiamata di funzione non necessaria aggiuntiva, che è già stata chiamata e il cui risultato è disponibile sull'attributo lastrowid.
Andrew,

5
Ho appena avuto un problema in cui è cursor.lastrowidtornato qualcosa di diverso connection.insert_id(). cursor.lastrowidha restituito l'ultimo ID di inserimento, connection.insert_id()restituito 0. Come può essere?
Martin Thoma,

1
@moose, forse i processi simultanei stanno facendo l'inserimento parallelo del database usando la stessa connessione.
xiaohan2012,

1
@FlyingAtom, perché è stato eseguito su python2 anziché su python3.
Andrew,

35

Le specifiche Python DBAPI definiscono anche l'attributo 'lastrowid' per l'oggetto cursore, quindi ...

id = cursor.lastrowid

... dovrebbe funzionare anche ed è ovviamente basato sulla connessione.


7
SELECT @@IDENTITY AS 'Identity';

o

SELECT last_insert_id();

2
questo consente le condizioni di gara perché stai richiedendo l'ultimo ID riga dal server. perché io non vuoi quel casino.
Joshua Burns,


1
Voglio sottolineare che questa parte è altrettanto importante: "Ogni client riceverà l'ultimo ID inserito per l'ultima dichiarazione eseguita dal client." Quindi otterrai un valore diverso da Workbench che eseguire esattamente lo stesso select last_insert_id()dalla CLI su una macchina Linux
codificando il

0

Questo potrebbe essere solo un requisito di PyMySql in Python, ma ho scoperto che dovevo nominare la tabella esatta per cui volevo l'ID:

Nel:

cnx = pymysql.connect(host='host',
                            database='db',
                            user='user',
                            password='pass')
cursor = cnx.cursor()
update_batch = """insert into batch set type = "%s" , records = %i, started = NOW(); """
second_query = (update_batch % ( "Batch 1", 22  ))
cursor.execute(second_query)
cnx.commit()
batch_id = cursor.execute('select last_insert_id() from batch')
cursor.close()

batch_id

Out: 5
... o qualunque sia effettivamente il valore Batch_ID corretto


@krzys_h Grazie per aver guardato questo K ma la tua modifica non riesce nei miei test e quindi ho rifiutato la tua modifica. Se non ti dispiace sostenere anche la modifica?
Edward,
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.