Como obtenho o "id" após INSERT no banco de dados MySQL com Python?

183

Eu executo uma instrução INSERT INTO

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

e quero obter a chave primária.

Minha tabela possui 2 colunas:

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

Como obtenho o "id" depois de inseri-lo?

TIMEX
fonte

Respostas:

243

Use cursor.lastrowidpara obter o último ID da linha inserido no objeto cursor, ou connection.insert_id()para obter o ID da última inserção nessa conexão.

Âmbar
fonte
3
E se dois processos inserirem uma linha ao mesmo tempo usando a mesma conexão. Qual id insert_idretornará?
xiaohan2012
27
@ xiaohan2012 Como 2 processos usam a mesma conexão?
precisa saber é o seguinte
5
lastrowidSó está disponível após a transação atual ser confirmada?
John Wang
4
@ hienbt88 Ele provavelmente quis dizer threads, eu fiz isso e isso pode causar problemas, a menos que você utilize corretamente a segurança de threads. Pessoalmente, instalei uma nova conexão para cada thread, o que é uma solução alternativa fofa, porque, por algum motivo, o comprometimento (na verdade, na verdade) não funcionou para mim, tive uma interligação séria devido a muitos threads simultâneos, todos fazendo algumas consultas por segundo.
Milan Velebit
Não funciona com registros duplicados usando insert, select e where.
e-info128
114

Além disso, cursor.lastrowid(uma extensão dbapi / PEP249 suportada pelo 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é um pouco mais barato que connection.insert_id()e muito mais barato que outra viagem de ida e volta ao MySQL.

Andrew
fonte
4
Por que é cursor.lastrowidmais barato que connection.insert_id()?
Martin Thoma
3
Somente porque cursor.lastrowid é definido automaticamente no objeto cursor como parte de cursor.execute () e é apenas uma pesquisa de atributo. connection.insert_id () é uma chamada de função desnecessária adicional - uma que já foi chamada e cujo resultado está disponível no atributo lastrowid.
Andrew
5
Acabei de ter um problema em que cursor.lastrowidretornou algo diferente connection.insert_id(). cursor.lastrowidretornou o último ID de inserção, connection.insert_id()retornado 0. Como pode ser?
Martin Thoma
1
@ moose, talvez processos concorrentes estejam fazendo a inserção paralela de banco de dados usando a mesma conexão.
xiaohan2012
1
@ FlyingIdom, porque isso foi executado em python2 em vez de python3.
18716 Andrew Andrew
35

A especificação DBAPI do Python também define o atributo 'lastrowid' para o objeto cursor, então ...

id = cursor.lastrowid

... deve funcionar também, e é obviamente baseado em cada conexão.

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

ou

SELECT last_insert_id();
Keith
fonte
2
isso permite condições de corrida porque você está solicitando o último código de linha do servidor. porque eu, você não quer essa bagunça.
21412 Joshua Burns
1
Quero ressaltar que esta parte é igualmente importante: "Cada cliente receberá o último ID inserido para a última instrução que o cliente executou." Portanto, você obterá um valor diferente do Workbench do que executar exatamente o mesmo select last_insert_id()da CLI em uma máquina Linux
simplesmente codificando
0

Isso pode ser apenas um requisito do PyMySql no Python, mas descobri que precisava nomear a tabela exata para a qual queria o ID:

No:

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 qualquer que seja o valor correto de Batch_ID

Edward
fonte
@krzys_h Obrigado por olhar para este K, mas sua edição falha nos meus testes e, por isso, rejeitei sua edição. Se você não se importa de também fazer o backup da edição?
Edward