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.