Python / postgres / psycopg2: obtention de l'ID de la ligne qui vient d'être insérée


99

J'utilise Python et psycopg2 pour m'interfacer avec postgres.

Quand j'insère une ligne ...

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

... comment obtenir l'ID de la ligne que je viens d'insérer? En essayant:

hundred = cursor.fetchall() 

renvoie une erreur, lors de l'utilisation 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)

retourne simplement None.

UPDATE: Il en va de currvalmême (même si l'utilisation de cette commande directement dans postgres fonctionne):

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

Quelqu'un peut-il conseiller?

Merci!

Réponses:


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

Et veuillez ne pas créer manuellement des chaînes SQL contenant des valeurs. Vous pouvez (et devriez!) Transmettre les valeurs séparément, ce qui rend inutile l'échappement et l'injection SQL impossible:

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]

Consultez la documentation psycopg pour plus de détails: http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries


12
Juste pour clarifier, le idin RETURNING iddoit être le nom de champ du champ de clé série / primaire.
joshden

9
le curseur fetchone ne me donne "aucun résultat à récupérer".
Leonid

@Leonid avez-vous compris cela?
Alison S

4
@AlisonS @Leonid J'ai eu la même erreur, mais l'ajout RETURNING idà la fin de la INSERTrequête l'a corrigée pour moi.
Banjer

Peut-être juste une petite note, mais un point important à mentionner pour tout le monde: assurez-vous que vous n'utilisez que le curseur .execute () et non un curseur .mogrify () avant la commande execute () , sinon (comme dans mon cas) cursor.fetchone () n'aura aucun résultat! En utilisant uniquement le curseur .execute () sans "rien" avant cette commande, vous recevrez un identifiant.
TheHeroOfTime

14

Je me suis retrouvé ici parce que j'avais un problème similaire, mais nous utilisons Postgres-XC, qui ne prend pas encore en charge la clause RETURNING ID. Dans ce cas, vous pouvez utiliser:

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

Juste au cas où cela serait utile à n'importe qui!


4
Rappelez-vous simplement que le faire dans deux instructions comme celle-ci présente un (très petit) risque de conditions de concurrence, si quelque chose insère une ligne dans la base de données directement après vous, mais avant que votre commande lastval () ne renvoie la valeur actuelle de la séquence.
Dave Thomas

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.