Як отримати "id" після INSERT в базу даних MySQL з Python?


183

Я виконую операцію INSERT INTO

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

і я хочу отримати первинний ключ.

Моя таблиця має 2 стовпці:

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

Як отримати "id", після того як я тільки що вставив це?


Відповіді:


243

Використовуйте cursor.lastrowidдля отримання ідентифікатора останнього рядка, вставленого на об'єкт курсору, або connection.insert_id()для отримання ідентифікатора з останньої вставки цього з'єднання.


3
Що робити, якщо два процеси вставляють рядок одночасно за допомогою одного і того ж з'єднання. Який ідентифікатор insert_idповернеться?
xiaohan2012

27
@ xiaohan2012 Як два процеси використовують одне і те ж з'єднання?
hienbt88

5
Доступна lastrowidлише після здійснення поточної транзакції?
Джон Ван

4
@ hienbt88 Він, мабуть, мав на увазі теми, я це зробив, і це може спричинити проблеми, якщо ви належним чином не використовуєте безпеку потоків. Я особисто пішов на інстанціювання нового з'єднання для кожної нитки, що є милим способом вирішення, оскільки з якихось причин вчинення (автокомісія насправді) не працювало для мене, я отримав серйозне переплетення через багато паралельних потоків, які видають кілька запитів. за секунду
Мілан Велебіт

Не працює з дублюються записами за допомогою вставки, вибору та де.
e-info128

114

Також cursor.lastrowid(розширення dbapi / PEP249, що підтримується 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дещо дешевше connection.insert_id()і набагато дешевше, ніж чергова поїздка в MySQL.


4
Чому cursor.lastrowidдешевше connection.insert_id()?
Мартін Тома

3
Тільки тому, що cursor.lastrowid автоматично встановлюється на об'єкт курсору як частина cursor.execute () і є лише пошуком атрибутів. connection.insert_id () - додатковий непотрібний виклик функції - виклик, який вже був викликаний і результат якого доступний в атрибуті lastrowid.
Андрій

5
У мене просто була проблема, де cursor.lastrowidповернуто щось інше, ніж connection.insert_id(). cursor.lastrowidповернув останній ідентифікатор вставки, connection.insert_id()повернуто 0. Як це може бути?
Мартін Тома

1
@moose, можливо, паралельні процеси роблять паралельну вставку бази даних, використовуючи те саме з'єднання.
xiaohan2012

1
@FlyingAtom, тому що це було запущено на python2 замість python3.
Андрій

35

Специфікація Python DBAPI також визначає атрибут 'lastrowid' для об’єкта курсору, тому ...

id = cursor.lastrowid

... також має працювати, і це очевидно, що базується на з'єднанні.


7
SELECT @@IDENTITY AS 'Identity';

або

SELECT last_insert_id();

2
це дозволяє використовувати умови перегонів, оскільки ви вимагаєте ідентифікатор останнього рядка від сервера. тому що я, ти не хочеш цього безладу.
Джошуа Бернс


1
Хочу зазначити, що ця частина не менш важлива: "Кожен клієнт отримає останній вставлений ідентифікатор за останнє твердження, яке виконав клієнт". Таким чином, ви отримаєте інше значення від Workbench, ніж запустити те саме select last_insert_id()з CLI на машині Linux
простокодування

0

Це може бути лише вимогою PyMySql в Python, але я виявив, що мені потрібно було назвати точну таблицю, для якої я хотів ідентифікатор:

В:

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

Вихід: 5
... або будь-яке правильне значення Batch_ID насправді


@krzys_h Дякуємо, що переглянули цей K, але ваша редакція не вдалася до мого тестування, тому я відхилив вашу редагування. Якщо ви не заперечуєте також створити резервну копію редагування?
Едвард
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.