Python / postgres / psycopg2: pobieranie ID właśnie wstawionego wiersza


105

Używam Pythona i psycopg2 do połączenia z postgres.

Kiedy wstawiam wiersz ...

sql_string = "INSERT INTO hundred (name,name_slug,status) VALUES ("
sql_string += hundred_name + ", '" + hundred_slug + "', " + status + ");"
cursor.execute(sql_string)

... jak uzyskać identyfikator właśnie wstawionego wiersza? Próbować:

hundred = cursor.fetchall() 

zwraca błąd podczas używania RETURNING id:

sql_string = "INSERT INTO domes_hundred (name,name_slug,status) VALUES ("
sql_string += hundred_name + ", '" + hundred_slug + "', " + status + ") RETURNING id;"
hundred = cursor.execute(sql_string)

po prostu wraca None.

AKTUALIZACJA: Tak robi currval(nawet jeśli użycie tego polecenia bezpośrednio w postgres działa):

sql_string = "SELECT currval(pg_get_serial_sequence('hundred', 'id'));"
hundred_id = cursor.execute(sql_string)

Czy ktoś może doradzić?

dzięki!

Odpowiedzi:


214
cursor.execute("INSERT INTO .... RETURNING id")
id_of_new_row = cursor.fetchone()[0]

I proszę nie tworzyć ręcznie łańcuchów SQL zawierających wartości. Możesz (i powinieneś!) Przekazywać wartości osobno, dzięki czemu nie ma potrzeby ucieczki i iniekcji SQL:

sql_string = "INSERT INTO domes_hundred (name,name_slug,status) VALUES (%s,%s,%s) RETURNING id;"
cursor.execute(sql_string, (hundred_name, hundred_slug, status))
hundred = cursor.fetchone()[0]

Zobacz dokumentację psycopg po więcej szczegółów: http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries


13
Dla wyjaśnienia, idin RETURNING idpowinno być nazwą pola pola klucza seryjnego / podstawowego.
— joshden,

11
kursor fetchone daje mi „brak wyników do pobrania”.
— Leonid

@Leonid, czy odkryłeś to?
— Alison S

5
@AlisonS @Leonid Miałem ten sam błąd, ale dodanie RETURNING idna końcu INSERTzapytania naprawiło go.
— Banjer,

Może tylko mała uwaga, ale ważna uwaga dla wszystkich: Upewnij się, że używasz tylko kursora .execute (), a nie kursora .mogrify () przed poleceniem execute () , w przeciwnym razie (jak w moim przypadku) kursor.fetchone () nie przyniesie żadnych wyników! Używając tylko kursora .execute () bez "niczego" przed tym poleceniem, otrzymasz identyfikator.
— TheHeroOfTime

14

Skończyło się tutaj, ponieważ miałem podobny problem, ale używamy Postgres-XC, który jeszcze nie obsługuje klauzuli RETURNING ID. W takim przypadku możesz użyć:

kursor.execute ('WSTAW DO ........')
kursor.execute ('SELECT LASTVAL ()')
lastid = kursor.fetchone () ['lastval']

Na wszelki wypadek, gdyby było to przydatne dla każdego!


4
Pamiętaj tylko - zrobienie tego w dwóch takich instrukcjach powoduje (bardzo małe) ryzyko wystąpienia warunków wyścigu, jeśli coś wstawia wiersz do bazy danych bezpośrednio po tobie, ale zanim polecenie lastval () zwraca bieżącą wartość sekwencji.
— Dave Thomas

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.