PostgreSQL的mysql_insert_id替代方法

24

是否有适用于 PostgreSQL 的mysql_insert_id() PHP 函数的替代方案?大多数框架通过查找ID所使用的序列的当前值来部分解决该问题。但是,有时主键不是序列列...

4个回答

44

从 PostgreSQL 的角度看,以伪代码表示:

 * $insert_id = INSERT...RETURNING foo_id;-- only works for PostgreSQL >= 8.2. 

 * INSERT...; $insert_id = SELECT lastval(); -- works for PostgreSQL >= 8.1

 * $insert_id = SELECT nextval('foo_seq'); INSERT INTO table (foo...) values ($insert_id...) for older PostgreSQL (and newer PostgreSQL)

pg_last_oid()只在存在OID时才有效。自从PostgreSQL 8.1版本以来,OID默认已关闭。

因此,根据您使用的PostgreSQL版本,您应该选择上述方法之一。当然,在理想情况下,请使用一个抽象数据库库来封装上述操作。否则,在低级代码中,它看起来像:

方法一:INSERT... RETURNING

// yes, we're not using pg_insert()
$result = pg_query($db, "INSERT INTO foo (bar) VALUES (123) RETURNING foo_id");
$insert_row = pg_fetch_row($result);
$insert_id = $insert_row[0];

方法二:INSERT;lastval()

$result = pg_execute($db, "INSERT INTO foo (bar) values (123);");
$insert_query = pg_query("SELECT lastval();");
$insert_row = pg_fetch_row($insert_query);
$insert_id = $insert_row[0];

方法三:nextval();插入

$insert_query = pg_query($db, "SELECT nextval('foo_seq');");
$insert_row = pg_fetch_row($insert_query);
$insert_id = $insert_row[0];
$result = pg_execute($db, "INSERT INTO foo (foo_id, bar) VALUES ($insert_id, 123);");

最安全的选择是第三种方法,但它不太方便。最干净的是第一种方法,但您需要运行最近的PostgreSQL。大多数数据库抽象库还没有使用第一种方法。


很好的答案,出于速度原因我已经从第三种方法切换到了第一种。我正在使用Python和Psycopg2,并且仅执行一个语句来进行大量数据插入是更快的方式。想知道第三种方法是否真的比第一种更安全?我认为第一种和第三种方法同样安全,而第二种方法存在竞争条件。 - Ross

5

你还可以使用以下方法:

$result = pg_query($db, "INSERT INTO foo (bar) VALUES (123) RETURNING foo_id");
$insert_row = pg_fetch_result($result, 0, 'foo_id');

在使用pg_fetch_result时,您需要指定要查找的行数和字段名称,这是一种更精确获取所需数据的方法,但我不知道是否会对查询的性能产生影响。请记住,此方法适用于PostgreSQL 8.2及以上版本。


是的,在@angch的答案中已经提到了。请注意,这对于其他SQL方言(如SQL Server、MySQL等)是不可用的。 - Jeffrey04

4
请查看INSERT语句的可选项CLAUSE RETURNING。(链接指向官方PostgreSQL文档) 但是,基本上,您需要:
INSERT INTO table (col1, col2) VALUES (1, 2) RETURNING pkey_col

INSERT语句本身会返回受影响行的id(或您指定的任何表达式)。


4

来自php.net:

$res=pg_query("SELECT nextval('foo_key_seq') as key");
$row=pg_fetch_array($res, 0);
$key=$row['key'];
// now we have the serial value in $key, let's do the insert
pg_query("INSERT INTO foo (key, foo) VALUES ($key, 'blah blah')");

这应该始终提供唯一的键,因为从数据库检索到的键将永远不会被再次检索。


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