Comment obtenir l '«id» après INSERT dans la base de données MySQL avec Python?

183

J'exécute une instruction INSERT INTO

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

et je veux obtenir la clé primaire.

Mon tableau comporte 2 colonnes:

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

Comment puis-je obtenir l '"identifiant" après avoir inséré ceci?

TIMEX
la source

Réponses:

244

Utilisez cursor.lastrowidpour obtenir l'ID de la dernière ligne insérée sur l'objet curseur, ou connection.insert_id()pour obtenir l'ID de la dernière insertion sur cette connexion.

ambre
la source
3
Et si deux processus inséraient une ligne en même temps en utilisant la même connexion. Quel identifiant insert_idreviendra?
xiaohan2012
28
@ xiaohan2012 Comment 2 processus utilisent-ils la même connexion?
hienbt88
5
N'est- lastrowidil disponible qu'après la validation de la transaction en cours?
John Wang
4
@ hienbt88 Il parlait probablement de threads, je l'ai fait et cela peut causer des problèmes à moins que vous n'utilisiez correctement threadsafety. Je suis personnellement allé pour instancier une nouvelle connexion pour chaque thread, ce qui est une solution de contournement intéressante car pour une raison quelconque, la validation (l'autocommit en fait) ne fonctionnait pas pour moi, j'ai eu de sérieuses imbrications en raison de nombreux threads simultanés émettant tous quelques requêtes. par seconde.
Milan Velebit
Ne fonctionne pas avec les enregistrements dupliqués en utilisant insérer, sélectionner et où.
e-info128
114

Aussi, cursor.lastrowid(une extension dbapi / PEP249 prise en charge par 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.lastrowidest un peu moins cher connection.insert_id()et beaucoup moins cher qu'un autre aller-retour vers MySQL.

Andrew
la source
4
Pourquoi est cursor.lastrowidmoins cher que connection.insert_id()?
Martin Thoma
3
Uniquement parce que cursor.lastrowid est automatiquement défini sur l'objet curseur dans le cadre de cursor.execute () et n'est qu'une recherche d'attribut. connection.insert_id () est un appel de fonction supplémentaire inutile - un qui a déjà été appelé et dont le résultat est disponible sur l'attribut lastrowid.
Andrew
5
J'ai juste eu un problème où cursor.lastrowidrenvoyé quelque chose de différent de connection.insert_id(). cursor.lastrowida renvoyé le dernier identifiant d'insertion, connection.insert_id()renvoyé 0. Comment est-ce possible?
Martin Thoma
1
@moose, peut-être que des processus simultanés effectuent une insertion de base de données parallèle en utilisant la même connexion.
xiaohan2012
1
@FlyingAtom, car cela a été exécuté sur python2 au lieu de python3.
Andrew
35

La spécification Python DBAPI définit également l'attribut 'lastrowid' pour l'objet curseur, donc ...

id = cursor.lastrowid

... devrait fonctionner aussi, et c'est évidemment basé sur la connexion.

Htechno
la source
7
SELECT @@IDENTITY AS 'Identity';

ou

SELECT last_insert_id();
Keith
la source
2
cela permet des conditions de concurrence parce que vous demandez l'ID de dernière ligne du serveur. parce que moi, tu ne veux pas de ce bordel.
Joshua Burns
1
Je tiens à souligner que cette partie est tout aussi importante: "Chaque client recevra le dernier ID inséré pour la dernière instruction exécutée par le client." Ainsi, vous obtiendrez une valeur différente de Workbench que d'exécuter exactement la même chose à select last_insert_id()partir de la CLI sur une machine Linux
codage simplement le
0

Cela pourrait être juste une exigence de PyMySql en Python, mais j'ai trouvé que je devais nommer la table exacte pour laquelle je voulais l'ID:

Dans:

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
... ou quelle que soit la valeur Batch_ID correcte

Edward
la source
@krzys_h Merci d'avoir regardé ce K mais votre modification échoue lors de mes tests et j'ai donc rejeté votre modification. Si cela ne vous dérange pas de sauvegarder également la modification?
Edward le