获取最后一个插入ID的标准方法是什么?

时间:2011-02-19 03:12:14

标签: sql mysql sql-server postgresql standards

获取最后一个插入ID的sql标准是什么?如果有这样的事情。

mysql:LAST_INSERT_ID()
postgresql:...返回f_id
mssql:SCOPE_IDENTITY()
......这里有更多例子......

我的意思是,所有数据库都有不同的实现,这种常见任务没有标准吗?

4 个答案:

答案 0 :(得分:9)

请参阅此回答Retrieve inserted row ID in SQL

简而言之,除了MAX(ID)之外,没有跨数据库的方法来做到这一点 - 但这不是一个保证的结果,并且有很多陷阱,例如。

  • 其他插入可以介于最后一次插入和最大查询之间
  • 不能与高事务表一起使用(max会发出读锁定,rdbms特定的方法不会从任何表中读取)

与identity / autonumber / auto_increment / sequences相关的ANSI标准首先出现在所有主要RDBMS等待实现的SQL:2003中。它很可能类似于Oracle / PostgreSQL序列。

  

SQL:2003标准对SQL的所有部分(也称为SQL3)进行了少量修改,并正式引入了一些新功能,例如:

- 序列生成器,它允许标准化序列

SQL:2003中的另一个变化是OUTPUT USING CLAUSE,但关于它的信息非常少。 Sybase和SQL Server已经做了不同的事情,所以还不清楚它将如何发展。 SQL Server将其实现为

INSERT INTO TBL(..)
OUTPUT inserted.identity_col
INTO @sometablevar
VALUES(..)

答案 1 :(得分:3)

Oracle和PostgreSQL支持RETURNING子句,并使用称为序列的对象来提供自动序列编号。 SQL Server的下一个版本denali被设置为支持序列,但是如果Denali支持RETURNING子句,我还没有看到。获取当前序列值的另一种方法是:

Oracle: sequence_name.CURRVAL 
PostgreSQL: CURRVAL('sequence_name')

DB2支持sequencesRETURNING INTO子句。

SELECT MAX(auto_increment_column) ...不是推荐的做法,因为它不可靠。在Oracle中,读取器(SELECT)不会被编写器阻塞(INSERT / UPDATE),因此无法保证该值的正确性。

结论

我不知道ANSI SQL:2003 standard包括使用序列进行自动编号,但此时没有实现检索值的一致方法。

答案 2 :(得分:0)

这是对一些评论的澄清,而不是一个真正的新答案,但它在这里更合适。只要客户端处于可序列化的事务中,select max(id)就可以正常工作。在pgsql中,您可以自己证明。打开两个psql会话,然后运行它,首先是默认的read committed,然后是serializable:

p1: create table test (id serial);
p1 and p2: begin;
p1 and p2: set transaction isolation level serializable;
p1: insert into test values (DEFAULT);
p2: insert into test values (DEFAULT);
p1: select max(id) from test;
 1
p2: select max(id) from test;
 2
p2: commit;
p1: select max(id) from test;
 2

但是,读取已提交:

p1: create table test (id serial);
p1 and p2: begin;
p1 and p2: set transaction isolation level read committed;
p1: insert into test values (DEFAULT);
p2: insert into test values (DEFAULT);
p1: select max(id) from test;
 1
p2: select max(id) from test;
 2
p2: commit;
p1: select max(id) from test;
 1

性能方面的可序列化事务可能会产生负面影响或导致失败的事务,必须回滚并再次尝试等。

返回或currval()是更好的想法。但是,如果执行它的事务是可序列化的,那么说max(id)就是不可信任是错误的。

答案 3 :(得分:0)

这种技术可能适用于所有数据库,并且在序列不是简单的递增数字的情况下(例如,存在具有高ID的预先存在的行,因此您不能使用MAX),是:< / p>

  1. 确定下一个ID是什么,例如使用nextval功能或类似功能。
  2. 使用该ID插入行。
  3. 将id用于满足您的其他需求。