Jak uzyskać „id” po INSERT w bazie danych MySQL za pomocą Pythona?

183

Wykonuję instrukcję INSERT INTO

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

i chcę zdobyć klucz podstawowy.

Moja tabela ma 2 kolumny:

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

Jak uzyskać „identyfikator” po tym, jak właśnie go wstawiłem?

TIMEX
źródło

Odpowiedzi:

243

Użyj, cursor.lastrowidaby wstawić identyfikator ostatniego wiersza do obiektu kursora lub connection.insert_id()aby uzyskać identyfikator z ostatniej wstawki w tym połączeniu.

Bursztyn
źródło
3
Co jeśli dwa procesy wstawiają wiersz w tym samym czasie, używając tego samego połączenia. Który identyfikator insert_idpowróci?
xiaohan2012
27
@ xiaohan2012 W jaki sposób 2 procesy używają tego samego połączenia?
hienbt88
5
Czy jest lastrowiddostępny tylko po zatwierdzeniu bieżącej transakcji?
John Wang,
4
@ hienbt88 Prawdopodobnie miał na myśli wątki, zrobiłem to i może to powodować problemy, chyba że właściwie użyjesz wątków. Osobiście zdecydowałem się na utworzenie nowego połączenia dla każdego wątku, co jest uroczym obejściem, ponieważ z jakiegoś powodu zatwierdzanie (właściwie automatyczne przydzielanie) nie działało dla mnie, mam poważne przeplatanie z powodu wielu współbieżnych wątków, z których wszystkie wysyłają kilka zapytań na sekundę.
Milan Velebit,
Nie działa ze zduplikowanymi rekordami przy użyciu wstawiania, wybierania i gdzie.
e-info128
114

Ponadto cursor.lastrowid(rozszerzenie dbapi / PEP249 obsługiwane przez 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.lastrowidjest nieco tańszy connection.insert_id()i znacznie tańszy niż kolejna podróż w obie strony do MySQL.

Andrzej
źródło
4
Dlaczego jest cursor.lastrowidtańszy niż connection.insert_id()?
Martin Thoma,
3
Tylko dlatego, że kursor.strowid jest automatycznie ustawiany na obiekcie kursora jako część kursora.execute () i jest jedynie wyszukiwaniem atrybutów. connection.insert_id () to dodatkowe niepotrzebne wywołanie funkcji - które zostało już wywołane i którego wynik jest dostępny dla atrybutu lastrowid.
Andrew
5
Właśnie miałem problem, w którym cursor.lastrowidzwróciło coś innego niż connection.insert_id(). cursor.lastrowidzwrócił ostatni identyfikator wstawki, connection.insert_id()zwrócił 0. Jak to możliwe?
Martin Thoma,
1
@ moose, być może równoległe procesy wykonują równoległe wstawianie bazy danych przy użyciu tego samego połączenia.
xiaohan2012
1
@FlyingAtom, ponieważ został on uruchomiony na python2 zamiast python3.
Andrew
35

Specyfikacja DBAPI w języku Python definiuje również atrybut „lastrowid” dla obiektu kursora, więc ...

id = cursor.lastrowid

... powinien również działać, i oczywiście jest oparty na połączeniu.

Htechno
źródło
7
SELECT @@IDENTITY AS 'Identity';

lub

SELECT last_insert_id();
Keith
źródło
2
pozwala to na warunki wyścigu, ponieważ żądasz od serwera ostatniego identyfikatora wiersza. ponieważ ja nie chcesz tego bałaganu.
Joshua Burns
1
Chcę podkreślić, że ta część jest równie ważna: „Każdy klient otrzyma ostatni wstawiony identyfikator ostatniego polecenia wykonanego przez klienta”. select last_insert_id()
Otrzymasz
0

Może to być tylko wymóg PyMySql w Pythonie, ale okazało się, że muszę podać dokładną tabelę, dla której chciałbym mieć identyfikator:

W:

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
... lub cokolwiek to jest poprawna wartość Batch_ID

Edward
źródło
@krzys_h Dziękuję za obejrzenie tego K, ale edycja nie powiodła się w moich testach, więc odrzuciłem ją. Jeśli nie miałbyś nic przeciwko wycofaniu edycji?
Edward