¿Cómo obtengo el "id" después de INSERTAR en la base de datos MySQL con Python?

183

Ejecuto una instrucción INSERT INTO

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

y quiero obtener la clave primaria.

Mi mesa tiene 2 columnas:

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

¿Cómo obtengo el "id" después de insertar esto?

TIMEX
fuente

Respuestas:

244

Use cursor.lastrowidpara obtener la última ID de fila insertada en el objeto del cursor, o connection.insert_id()para obtener la ID de la última inserción en esa conexión.

Ámbar
fuente
3
¿Qué sucede si dos procesos insertan una fila al mismo tiempo usando la misma conexión? ¿Qué identificación volverá insert_id?
xiaohan2012
28
@ xiaohan2012 ¿Cómo utilizan 2 procesos la misma conexión?
hienbt88
55
¿ lastrowidSolo está disponible después de que se confirme la transacción actual?
John Wang
44
@ hienbt88 Probablemente se refería a hilos, lo he hecho y puede causar problemas a menos que utilice correctamente la seguridad de hilos. Personalmente, he decidido crear una nueva conexión para cada subproceso, lo cual es una linda solución, ya que por alguna razón el compromiso (en realidad, la confirmación automática) no funcionó para mí, obtuve algunos entrelazamientos serios debido a que muchos subprocesos concurrentes emitieron algunas consultas. por segundo.
Milan Velebit
No funciona con registros duplicados usando insertar, seleccionar y dónde.
e-info128
114

Además, cursor.lastrowid(una extensión dbapi / PEP249 compatible con 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.lastrowides algo más barato connection.insert_id()y mucho más barato que otro viaje de ida y vuelta a MySQL.

Andrés
fuente
44
¿Por qué es cursor.lastrowidmás barato que connection.insert_id()?
Martin Thoma
3
Solo porque cursor.lastrowid se establece automáticamente en el objeto cursor como parte de cursor.execute () y es solo una búsqueda de atributos. connection.insert_id () es una llamada de función innecesaria adicional, una que ya se ha llamado y cuyo resultado está disponible en el atributo lastrowid.
Andrew
55
Acabo de tener un problema al cursor.lastrowiddevolver algo diferente a connection.insert_id(). cursor.lastrowiddevolvió la última identificación de inserción, connection.insert_id()devuelta 0. ¿Como puede ser?
Martin Thoma
1
@moose, quizás los procesos concurrentes están haciendo una inserción paralela de la base de datos utilizando la misma conexión.
xiaohan2012
1
@FlyingAtom, porque esto se ejecutó en python2 en lugar de python3.
Andrew
35

La especificación DBAPI de Python también define el atributo 'lastrowid' para el objeto cursor, así que ...

id = cursor.lastrowid

... también debería funcionar, y obviamente se basa en la conexión.

Htechno
fuente
7
SELECT @@IDENTITY AS 'Identity';

o

SELECT last_insert_id();
Keith
fuente
2
esto permite condiciones de carrera porque está solicitando la última fila de identificación del servidor. porque yo no quieres ese desastre.
Joshua Burns
1
Quiero señalar que esta parte es igualmente importante: "Cada cliente recibirá la última ID insertada para la última declaración que ejecutó el cliente". Por lo tanto, obtendrá un valor diferente de Workbench que ejecutar exactamente lo mismo select last_insert_id()desde la CLI en una máquina Linux
simplemente codificando el
0

Esto podría ser solo un requisito de PyMySql en Python, pero descubrí que tenía que nombrar la tabla exacta para la que deseaba la ID:

En:

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

Fuera: 5
... o cualquiera que sea el valor correcto de Batch_ID

Eduardo
fuente
@krzys_h Gracias por mirar este K, pero su edición falla en mis pruebas y por eso he rechazado su edición. ¿Si no te importaría también respaldar la edición?
Edward