Python / postgres / psycopg2: รับ ID ของแถวที่เพิ่งแทรก


109

ฉันใช้ Python และ psycopg2 เพื่อเชื่อมต่อกับ postgres

เมื่อฉันแทรกแถว ...

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

... ฉันจะรับ ID ของแถวที่เพิ่งใส่ได้อย่างไร? พยายาม:

hundred = cursor.fetchall() 

ส่งกลับข้อผิดพลาดขณะใช้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)

Noneเพียงแค่ผลตอบแทน

อัปเดต: ก็เช่นกันcurrval(แม้ว่าจะใช้คำสั่งนี้โดยตรงกับ postgres ก็ใช้ได้):

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

ใครสามารถให้คำแนะนำ?

ขอบคุณ!

คำตอบ:


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

และโปรดอย่าสร้างสตริง SQL ที่มีค่าด้วยตนเอง คุณสามารถ (และควร!) ส่งผ่านค่าแยกกันทำให้ไม่จำเป็นต้อง Escape และการแทรก 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]

ดูเอกสาร Psycopg สำหรับรายละเอียดเพิ่มเติม: http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries


13
เพื่อชี้แจงว่าidin RETURNING idควรเป็นชื่อฟิลด์ของฟิลด์ซีเรียล / คีย์หลัก
joshden

11
cursor fetchone ทำให้ฉัน "ไม่มีผลลัพธ์ที่จะดึง"
Leonid

@ Leonid คุณคิดออกหรือไม่?
Alison S

6
@AlisonS @Leonid ฉันมีข้อผิดพลาดเดียวกัน แต่การเพิ่มRETURNING idที่ส่วนท้ายของINSERTแบบสอบถามแก้ไขให้ฉัน
บรรเจิด

อาจเป็นเพียงบันทึกเล็กน้อย แต่เป็นประเด็นสำคัญที่ต้องพูดถึงสำหรับทุกคน: ตรวจสอบให้แน่ใจว่าคุณใช้เคอร์เซอร์. execute () เท่านั้นไม่ใช่เคอร์เซอร์. mogrify ()ก่อนคำสั่ง execute ()มิฉะนั้น (เช่นในกรณีของฉัน) cursor.fetchone () จะไม่มีผลลัพธ์ใด ๆ ! โดยใช้เคอร์เซอร์เท่านั้นexecute ()โดยไม่มี "อะไร" ก่อนคำสั่งนั้นคุณจะได้รับ id
TheHeroOfTime

14

ฉันลงเอยที่นี่เพราะฉันมีปัญหาคล้ายกัน แต่เราใช้ Postgres-XC ซึ่งยังไม่รองรับประโยค RETURNING ID ในกรณีนี้คุณสามารถใช้:

cursor.execute ('INSERT INTO ........ ')
cursor.execute ('เลือก LASTVAL ()')
lastid = cursor.fetchone () ['lastval']

เผื่อว่าจะเป็นประโยชน์สำหรับทุกคน!


5
เพียงจำไว้ว่าการทำในสองคำสั่งเช่นนี้จะทำให้เกิดความเสี่ยง (น้อยมาก) ของเงื่อนไขการแข่งขันหากมีบางสิ่งแทรกแถวลงในฐานข้อมูลโดยตรงหลังจากคุณ แต่ก่อนคำสั่ง lastval () ของคุณจะส่งคืนค่าปัจจุบันของลำดับ
Dave Thomas

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.