Python / postgres / psycopg2: ottenere l'ID della riga appena inserita


99

Sto usando Python e psycopg2 per interfacciarmi con postgres.

Quando inserisco una riga ...

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

... come ottengo l'ID della riga che ho appena inserito? Provando:

hundred = cursor.fetchall() 

restituisce un errore, durante l'utilizzo 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)

semplicemente ritorna None.

AGGIORNAMENTO: Così fa currval(anche se l'uso di questo comando direttamente in postgres funziona):

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

Qualcuno può consigliare?

Grazie!

Risposte:


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

Inoltre, non creare manualmente stringhe SQL contenenti valori. Puoi (e dovresti!) Passare i valori separatamente, rendendo inutile l'escape e l'iniezione SQL impossibile:

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]

Vedere la documentazione di psycopg per maggiori dettagli: http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries


12
Giusto per chiarire, idin RETURNING iddovrebbe essere il nome del campo della chiave seriale / primaria.
joshden

9
il cursore fetchone mi dà "nessun risultato da recuperare".
Leonid

@ Leonid hai capito questo?
Alison S

4
@AlisonS @Leonid Ho avuto lo stesso errore, ma l'aggiunta RETURNING idalla fine della INSERTquery lo ha risolto per me.
Banjer

Forse solo una piccola nota, ma punto importante da menzionare per tutti: assicurati di utilizzare solo il cursore .execute () e non un cursore .mogrify () prima del comando execute () , altrimenti (come nel mio caso) cursor.fetchone () non avrà alcun risultato! Usando solo il cursore .execute () senza "nulla" prima di quel comando riceverai un id.
TheHeroOfTime

14

Sono finito qui perché ho avuto un problema simile, ma stiamo usando Postgres-XC, che non supporta ancora la clausola RETURNING ID. In tal caso puoi utilizzare:

cursor.execute ('INSERT INTO ........')
cursor.execute ('SELECT LASTVAL ()')
lastid = cursor.fetchone () ['lastval']

Nel caso fosse utile per chiunque!


4
Ricorda: farlo in due istruzioni del genere comporta un (molto piccolo) rischio di condizioni di competizione, se qualcosa inserisce una riga nel database direttamente dopo di te, ma prima che il tuo comando lastval () restituisca il valore corrente della sequenza.
Dave Thomas

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.