如何获取最后插入的id的SQL标准?如果有的话。
mysql: LAST_INSERT_ID()
postgresql: ... RETURNING f_id
mssql: SCOPE_IDENTITY()
... 更多例子请见这里 ...
我的意思是,所有数据库都对此有不同的实现,难道没有针对这样一个常见任务的标准吗?
如何获取最后插入的id的SQL标准?如果有的话。
mysql: LAST_INSERT_ID()
postgresql: ... RETURNING f_id
mssql: SCOPE_IDENTITY()
... 更多例子请见这里 ...
我的意思是,所有数据库都对此有不同的实现,难道没有针对这样一个常见任务的标准吗?
请参见这个答案:在SQL中检索插入的行ID
简而言之,除了使用MAX(ID)(但这不是一种可保证的结果,并且存在许多很多的缺陷,例如:
与identity/autonumber/auto_increment/sequences相关的ANSI标准首次出现在SQL:2003中,正在等待所有主要RDBMS的实现。它最可能类似于Oracle/PostgreSQL序列。
SQL:2003标准对SQL:1999(也称为SQL3)的所有部分进行了轻微修改,并正式引入了一些新功能,例如:
- 序列生成器,允许标准序列。
SQL:2003中的另一个变化是OUTPUT USING CLAUSE
,但是关于它的信息很少。Sybase和SQL Server对其采取了不同的处理方式,因此目前还不清楚它将如何发展。 SQL Server将其实现为
INSERT INTO TBL(..)
OUTPUT inserted.identity_col
INTO @sometablevar
VALUES(..)
Oracle和PostgreSQL支持RETURNING
子句,并使用称为序列的对象提供自动顺序编号。SQL Server的下一个版本Denali将支持序列,但我还没有看到是否支持RETURNING子句的消息。获取当前序列值的另一种方法是:
Oracle: sequence_name.CURRVAL
PostgreSQL: CURRVAL('sequence_name')
SELECT MAX(auto_increment_column) ...
,因为它不可靠。在Oracle中,读者(SELECT)不会被写入者(INSERT/UPDATE)阻塞,因此无法保证该值的正确性。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
然而,使用读取提交(read committed):
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)不能信任是错误的。
nextval 函数或类似函数。
- 使用该ID插入行。
- 将该ID用于您余下的需求。
nextval
或类似的东西,但我们可以假装它只是一种小型的服务器产品,所以不算数。我想知道的是你的方法实际上应该如何工作。这里有一个场景:插入了一行数据,不久之后又被删除了。此后没有插入更多的行,但即将添加一行。此时MAX(ID)
为某个N
。新行将使用ID = N + 2
插入,因为N + 1
是最近插入和删除的行的ID。使用nextval
能正确解决这种情况吗? - Andriy M
INSERT INTO table (a,b,c) VALUES (A,B,C)
,则可以通过SELECT id FROM table WHERE a = A AND b = B AND c = C
获得ID。当然,如果存在重复值(例如记录A、B、C不是唯一的),则不能依赖此方法。 - jmz