我有一个表格,test_table
其中一个字段id
会自动递增.现在我想要的是在运行INSERT
语句后立即获取最后一个插入的id .此时我所有的尝试都会导致None(顺便说一句,我在MySQL中得到了相同的行为,只有在SQLite中一切正常).这是一些重现这种意外行为的代码:
>>> import psycopg2 >>> cnx = psycopg2.connect(host="127.0.0.1", dbname="reestr", user="postgres", password="postgres") >>> cur = cnx.cursor() >>> cur.execute("INSERT INTO test_table (field_1) VALUES ('hello')") >>> cur.execute("INSERT INTO test_table (field_1) VALUES ('hello')") >>> cur.execute("SELECT CURRVAL(pg_get_serial_sequence('test_table','id'))") >>> res = cur.fetchone() >>> res (None,) >>> cur.execute("SELECT id, field_1 FROM test_table") >>> res = cur.fetchall() >>> res [(1, 'hello'), (2, 'hello')]
我们清楚地看到,该id
列自动增量,但由于一些疯狂的原因,SELECT CURRVAL(pg_get_serial_sequence('test_table','id'))
没有返回任何东西.这有什么问题?顺便说一下,我还尝试在一个事务中显式运行这些查询,并得到完全相同的结果.
因为PostgreSQL文档说:
pg_get_serial_sequence(table_name,column_name)| 文字| 获取serial或bigserial列使用的序列的名称
(强调我的)因为你的专栏没有明确宣布为SERIAL或BIGSERIAL,所以pg_get_serial_sequence
什么都不返回.如果您想使用pg_get_serial_sequence
,您必须声明:
CREATE TABLE test_table (id SERIAL, field_1 VARCHAR(128))
无论如何,生成的密钥是PostgreSQL中的常见问题.我在Java中遇到过它,但它在Python中应该是相同的.
PostgreSQL具有特定的扩展名,而不是从游标中访问最后生成的密钥的常用习惯用法RETURNING
.从INSERT的 PostreSQL文档中提取
[ WITH [ RECURSIVE ] with_query [, ...] ] INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
...可选的RETURNING子句使INSERT根据实际插入的每一行计算和返回值.这主要用于获取默认提供的值,例如序列号... RETURNING列表的语法与SELECT的输出列表的语法相同.
所以我的建议是坚持你当前的声明,但是将你的插入代码更改为:
>>> cur.execute("INSERT INTO test_table (field_1) VALUES ('hello') RETURNING id") >>> res = cur.fetchone() >>> last_inserted_id = res[0]