Postgres/PHP - 如何标准地检索已插入行的ID?

3
我在Google上搜索并阅读了几篇关于不同人如何解决此问题的文章,但我想知道解决它的标准方法是什么,同时,哪种方法对我的情况最有效。
我有一个创建新问题的AJAX页面,我需要知道如何在同一php文件中从插入查询中检索ID,在下一行中使用它。
它看起来像这样:
$r = pg_query("INSERT INTO questions (audit_id, type_id, order) VALUES (1,1,1)");
// Fetch ID from $r here...

我见过 MySQL 中的 mysql_insert_id() 函数,并听说 PostgreSQL 的类似函数是 pg_last_oid(),但文档中声称该函数已过时并将被删除。我还看到了使用 CURRVAL('my_sequence_table.id') 的方法,但我不确定这是否适用于 AJAX,因为这可能会引发竞态条件。
请问有人能告诉我解决这个问题的 PHP/PostgreSQL 标准方法吗?任何评论将不胜感激。
P.S. 我想念 Ruby on Rails!

哦,顺便说一下,pg_last_oid绝对不是一个好主意。默认情况下,表不再具有OID。 - alvherre
@alvherre - 是的,我在阅读中也注意到了。OID 中的 O 到底代表什么呢? - Topher Fangio
1
"对象"。请注意,OID仍然用于标识系统对象(即表、模式、数据库等)。 - alvherre
@alvherre - 谢谢。很有趣的了解。 - Topher Fangio
3个回答

5
也许你最好使用INSERT INTO questions ... VALUES (1,1,1) RETURNING audit_id,因为它将给你正确的值,无论是手动插入值还是通过序列插入。
请注意,如果你在同一会话中使用currval()技巧,它肯定会起作用 -- currval()保证返回与序列提供给您的会话相同的值,而不管其他并发会话正在做什么。只有当你有一个连接池程序以某种方式为第一个查询和第二个查询使用不同的连接时,它才可能导致问题,但如果它这样做了,那么它会非常糟糕。我不知道有哪个连接池器会这样做。 更新:请参见pg_get_serial_sequence()函数,该函数接受表名和列名,并返回相关的序列名称。使用它比在代码中硬编码序列名称更实用。

感谢您对RETURNINGcurrval()的意见。看到其他人的做法很好。 - Topher Fangio

2

MySQL有自增字段的概念,而PostgreSQL有序列(sequences)的概念。PostgreSQL序列是一个命名的数据库对象,它的值可以被增加。请参阅FAQ


谢谢提供链接。经过更多阅读,我认为我会使用RETURNING id选项。 - Topher Fangio

0
我建议使用CURRVAL('my_sequence_table.id')选项。
这不会导致竞争条件,因为它将返回当前会话的最新值,并且这些将是同一会话中的两个连续语句。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接