170 votes

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

J'utilise Python et psycopg2 pour interfacer avec postgres.

Lorsque 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 puis-je obtenir l'ID de la ligne que je viens d'insérer ? En essayant :

hundred = cursor.fetchall() 

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

renvoie simplement None .

MISE À JOUR : Il en va de même pour currval (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 nous conseiller ?

merci !

312voto

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

Ne construisez pas manuellement des chaînes SQL contenant des valeurs. Vous pouvez (et devriez !) passer les valeurs séparément, ce qui rend l'échappement inutile 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]

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

17voto

Jamie Brown Points 413

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

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

Juste au cas où cela aurait été utile à quelqu'un !

7voto

Mike Graham Points 22480

4voto

danrodz Points 21

L'approche de ThiefMaster a fonctionné pour moi, à la fois pour INSERT y UPDATE commandes.

Si cursor.fetchone() est appelé sur un curseur après avoir exécuté un INSERT / UPDATE mais sans valeur de retour ( RETURNING ), une exception sera levée : ProgrammingError('no results to fetch'))

insert_query = """
    INSERT INTO hundred (id, name, name_slug, status)
        VALUES (DEFAULT, %(name)s, %(name_slug)s, %(status)s)
        RETURNING id;
"""

insert_query_values = { 
    "name": "",
    "name_slug": "",
    "status": ""
}

connection = psycopg2.connect(host="", port="", dbname="", user="", password="")

try:
    with connection:
        with connection.cursor() as cursor:
            cursor.execute(insert_query, insert_query_values)
            num_of_rows_affected = cursor.rowcount
            new_row_id = cursor.fetchone()

except psycopg2.ProgrammingError as ex:
    print("...", ex)
    raise ex

finally:
    connection.commit()
    connection.close()

3voto

Paulo Points 1201

Pour moi, ni la réponse de ThiefMaster ni celle de Jamie Brown n'ont fonctionné. Ce qui a fonctionné pour moi est un mélange des deux, et j'aimerais répondre ici pour que cela puisse aider quelqu'un d'autre.

Ce que je devais faire, c'était.. :

cursor.execute('SELECT LASTVAL()')
id_of_new_row = cursor.fetchone()[0]

La déclaration lastid = cursor.fetchone()['lastval'] n'a pas fonctionné pour moi, même après cursor.execute('SELECT LASTVAL()') . La déclaration id_of_new_row = cursor.fetchone()[0] seule n'a pas fonctionné non plus.

Il y a peut-être quelque chose qui m'échappe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X