获取最后一个插入ID的sql标准是什么?如果有这样的事情。
mysql:LAST_INSERT_ID()
postgresql:...返回f_id
mssql:SCOPE_IDENTITY()
......这里有更多例子......
我的意思是,所有数据库都有不同的实现,这种常见任务没有标准吗?
答案 0 :(得分:9)
请参阅此回答Retrieve inserted row ID in SQL
简而言之,除了MAX(ID)之外,没有跨数据库的方法来做到这一点 - 但这不是一个保证的结果,并且有很多陷阱,例如。
与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支持sequences和RETURNING 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>
nextval
功能或类似功能。