7

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

编辑添加:

我删除并重新创建了一个表

[personID] [int] IDENTITY(1,1) NOT NULL

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

4

6 回答 6

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
于 2009-02-18T20:21:33.753 回答
10

不,没有任何保证的方法(尽管您当然可以找出下一个值可能是什么,但另一个命令可能会在您使用它之前先使用它)。您可以检索的唯一保证值是先前插入的标识值SCOPE_IDENTITY()(它将返回为当前范围最后生成的标识值)。

值得怀疑的是,为什么人们需要知道之前的值(当使用自动递增的种子标识列时)。

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

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

于 2009-02-18T20:04:51.437 回答
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

于 2009-02-18T23:02:06.550 回答
0
SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable
于 2013-10-09T06:32:04.087 回答
-1

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

于 2009-02-18T20:20:07.580 回答
-1

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

于 2009-02-18T20:24:06.057 回答