Python / postgres / psycopg2: mendapatkan ID dari baris yang baru saja dimasukkan

101

Saya menggunakan Python dan psycopg2 untuk berinteraksi dengan postgres.

Ketika saya menyisipkan baris ...

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

... bagaimana cara mendapatkan ID dari baris yang baru saja saya sisipkan? Mencoba:

hundred = cursor.fetchall() 

mengembalikan kesalahan, saat menggunakan 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)

hanya kembali None.

UPDATE: Begitu pula currval(meskipun menggunakan perintah ini langsung ke postgres berfungsi):

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

Adakah yang bisa memberi saran?

Terima kasih!

AP257
sumber

Jawaban:

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

Dan tolong jangan membangun string SQL yang berisi nilai secara manual. Anda dapat (dan harus!) Meneruskan nilai secara terpisah, membuatnya tidak perlu melarikan diri dan injeksi SQL tidak mungkin:

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]

Lihat dokumen psycopg untuk detail selengkapnya: http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries

ThiefMaster
sumber
12
Hanya untuk memperjelas, idin RETURNING idharus berupa nama field dari field serial / primary key.
joshden
10
cursor fetchone memberi saya "tidak ada hasil untuk diambil".
Leonid
@ Leonid, apakah Anda mengetahui hal ini?
Alison S
4
@AlisonS @Leonid Saya mengalami kesalahan yang sama, tetapi menambahkan RETURNING iddi akhir INSERTkueri memperbaikinya untuk saya.
Banjer
Mungkin hanya sedikit catatan, tetapi poin penting untuk disebutkan untuk semua orang: Pastikan Anda hanya menggunakan kursor .execute () dan bukan kursor .mogrify () sebelum perintah eksekusi () , jika tidak (seperti dalam kasus saya) cursor.fetchone () tidak akan memberikan hasil apa pun! Dengan hanya menggunakan kursor .execute () tanpa "apa pun" sebelum perintah itu Anda akan menerima sebuah id.
TheHeroOfTime
14

Saya berakhir di sini karena saya memiliki masalah yang sama, tetapi kami menggunakan Postgres-XC, yang belum mendukung klausul RETURNING ID. Jika demikian, Anda dapat menggunakan:

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

Kalau-kalau itu berguna bagi siapa saja!

Jamie Brown
sumber
4
Ingat saja - melakukannya dalam dua pernyataan seperti itu menjalankan risiko (sangat kecil) kondisi balapan, jika sesuatu menyisipkan baris ke dalam database langsung setelah Anda, tetapi sebelum perintah lastval () mengembalikan nilai urutan saat ini.
Dave Thomas