Python / postgres / psycopg2: отримання ідентифікатора щойно вставленого рядка


99

Я використовую Python та psycopg2 для інтерфейсу до postgres.

Коли я вставляю рядок ...

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

... як отримати ідентифікатор рядка, який я щойно вставив? Спроба:

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)

Хтось може порадити?

Дякую!

Відповіді:


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

І, будь ласка, не створюйте рядки SQL, що містять значення вручну. Ви можете (і повинні!) Передавати значення окремо, унеможливлюючи втечу та ін'єкцію 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


12
Просто для уточнення, idв полі RETURNING idмає бути назва поля серійного / первинного ключа.
joshden

9
fetchone курсора дає мені "ніяких результатів для отримання".
Леонід

@ Леонід ти це зрозумів?
Alison S

4
@AlisonS @Leonid У мене була та ж помилка, але додавання RETURNING idв кінці INSERTзапиту це виправило для мене.
Banjer

Можливо, лише невелика примітка, але важливий момент, який слід згадати для всіх: Переконайтесь, що ви використовуєте лише курсор .execute (), а не курсор .mogrify () перед командою execute () , інакше (як у моєму випадку) cursor.fetchone () не матиме результатів! Використовуючи лише курсор .execute () без "нічого" перед цією командою, ви отримаєте ідентифікатор.
TheHeroOfTime

14

Я опинився тут, тому що у мене виникли подібні проблеми, але ми використовуємо Postgres-XC, який ще не підтримує застереження про ПОВЕРНЕННЯ. У цьому випадку ви можете використовувати:

cursor.execute ('ВСТАВИТИ В ........')
cursor.execute ('SELECT LASTVAL ()')
lastid = cursor.fetchone () ['lastval']

Про всяк випадок це було корисно для когось!


4
Пам'ятайте лише, що це робиться в двох висловлюваннях, таких як, що створює (дуже малий) ризик перегонових умов, якщо щось вставляє рядок у базу даних безпосередньо після вас, але перед тим, як ваша команда lastval () повертає поточне значення послідовності.
Dave Thomas

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.