你怎么知道下一个标识列将是什么?

时间:2009-02-18 20:01:17

标签: sql-server tsql identity

是否有tsql查询来告诉它期望用于下一行插入的SQL服务器标识列值?

已编辑添加:

我删除并使用

重新创建了一个表
[personID] [int] IDENTITY(1,1) NOT NULL

作为我的CREATE TABLE命令的一部分。我还尝试重新设置标识列,同时删除该表中的所有信息,但这并不总是有效。它让我想知道是否有办法查看SQL预期用于下一个标识列号。

6 个答案:

答案 0 :(得分:15)

您可能希望使用SCOPE_IDENTITY而不是@@ IDENTITY将其限制为当前范围中的标识值。这样可以避免将触发器插入的新标识值放入其他表而不是刚插入的表中。

但是你可以计算下一个身份值是什么

SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable

问题是你无法保证价值。 您必须有一个锁,以便在运行时在表上拒绝其他插入以确保值准确。在用完32位整数后,我也不知道逻辑是什么。我不知道它是否会翻身或失败。

编辑: 我刚测试了这个(参见下面的SQL),当没有数据时它没有返回正确的值。 使用DBCC CHECKIDENT('tablename',RESEED,200)进行重新种子实际上导致下一个值为201而不是200.

CREATE TABLE willtest (myid integer IDENTITY(1,1), myvalue varchar(255))

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')

INSERT INTO willtest (myvalue)
VALUES ('1')
INSERT INTO willtest (myvalue)
VALUES ('2')
INSERT INTO willtest (myvalue)
VALUES ('3')
INSERT INTO willtest (myvalue)
VALUES ('4')
INSERT INTO willtest (myvalue)
VALUES ('5')
INSERT INTO willtest (myvalue)
VALUES ('6')
INSERT INTO willtest (myvalue)
VALUES ('7')
INSERT INTO willtest (myvalue)
VALUES ('8')

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')

DBCC CHECKIDENT ('willtest', RESEED, 200)

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')

INSERT INTO willtest (myvalue)
VALUES ('200')
INSERT INTO willtest (myvalue)
VALUES ('201')
INSERT INTO willtest (myvalue)
VALUES ('202')
INSERT INTO willtest (myvalue)
VALUES ('203')
INSERT INTO willtest (myvalue)
VALUES ('204')
INSERT INTO willtest (myvalue)
VALUES ('205')
INSERT INTO willtest (myvalue)
VALUES ('206')
INSERT INTO willtest (myvalue)
VALUES ('207')

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')

SELECT * FROM willtest

DROP TABLE willtest

答案 1 :(得分:10)

不,没有任何保证方式(虽然您当然可以找到可能的下一个值,但是另一个命令可能会在您可以使用之前使用它任何使用它)。您可以检索的唯一保证值是之前通过SCOPE_IDENTITY()插入的标识值(它将返回上次为当前范围生成的标识值)。

在使用自动递增的种子标识列之前,为什么需要知道该值的目的是值得怀疑的。

如果您之前需要知道该值,那么我建议您自己生成ID。您可以使用在表名上键入的id表来执行此操作,或者,如果您有可伸缩性问题(并且您正在使用事务),则可以为每个需要id的id表创建一个id表,该id将具有要插入的id(然后递增)。

或者,您可以使用GUID,在将其发送到数据库之前,您可以在客户端轻松生成这些GUID。

答案 2 :(得分:4)

这段sql将为您提供下一个标识列值(可能有很多理由不在生产代码中重复此代码段)

declare @nextid int;
declare @previousid int;

begin tran

 insert into dbo.TestTable (Col1) values ('11');
 select @nextid = SCOPE_IDENTITY(); 

rollback tran

 select @previousid = @nextid -1
 DBCC CHECKIDENT('dbo.TestTable', RESEED, @previousid);
 select @nextid

此stackoverflow问题提供了一些额外信息 - sql-identity-autonumber-is-incremented-even-with-a-transaction-rollback

答案 3 :(得分:0)

SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable

答案 4 :(得分:-1)

由于您从1开始播种并递增1(IDENTITY(1,1)),我想知道您是否可以创建一个过程,您可以设置一个变量,如“选择@@ IDENTITY + 1”或类似的东西

答案 5 :(得分:-1)

使用GUID列作为主键。除非您每秒有数十亿条记录和数千条请求,否则您可能不会注意到性能差异。但除非你喜欢花太多时间处理这类愚蠢的问题,否则你会注意到你的压力水平和预期寿命的差异。