在不插入行的情况下获取下一个ID

iWe*_*sel 13 sql sql-server

是否有可能在SQL(SQL Server)中从表中的标识列检索下一个ID(整数),而实际上没有插入行?如果最近的行被删除,则不一定是最高ID加1.

我问这个是因为我们偶尔需要用新行更新实时数据库.行的ID在我们的代码中使用(例如Switch(ID){Case ID:}并且必须相同.如果我们的开发DB和实时DB不同步,那么提前预测行ID会很不错在部署之前.

我当然可以设置IDENTITY OFF SET INSERT_IDENTITY ON或运行一个事务(这会回滚ID吗?)等但是想知道是否有一个函数返回了下一个ID(没有增加它).

And*_*rew 12

编辑:

在花了几个小时比较整个页面转储后,我意识到有一种更简单的方法,我应该留在DMV上.

该值在备份/恢复后仍然存在,这清楚地表明它已存储 - 我将所有页面转储到数据库中,并且无法找到添加记录时的位置/更改.比较200k行的页面转储并不好玩.

我曾经使用过专用的管理控制台,我把每一个内部表的转储暴露出来,插入一行,然后进一步转储系统表.两个转储都是相同的,这表明虽然它存活了,因此必须存储,但即使在那个级别也不会暴露.

所以经过一圈之后,我意识到DMV确实有答案.

create table foo (MyID int identity not null, MyField char(10))
insert into foo values ('test')
go 10

-- Inserted 10 rows
select Convert(varchar(8),increment_value) as IncrementValue,
   Convert(varchar(8),last_value) as LastValue
from sys.identity_columns where name ='myid'


-- insert another row
insert into foo values ('test')

-- check the values again
select Convert(varchar(8),increment_value) as IncrementValue,
   Convert(varchar(8),last_value) as LastValue
from sys.identity_columns where name ='myid'

-- delete the rows
delete from foo


-- check the DMV again
select Convert(varchar(8),increment_value) as IncrementValue,
   Convert(varchar(8),last_value) as LastValue
from sys.identity_columns where name ='myid'

-- value is currently 11 and increment is 1, so the next insert gets 12
insert into foo values ('test')
select * from foo

Result:
MyID        MyField
----------- ----------
12          test      

(1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)

只是因为删除了行,最后一个值没有重置,所以最后一个值+增量应该是正确的答案.

还要在我的博客上写下这集.

哦,还有所有的捷径:

select ident_current('foo') + ident_incr('foo')
Run Code Online (Sandbox Code Playgroud)

事实证明这很简单 - 但是这一切都假设没有其他人在你拿回你的身份时使用了你的身份证.很好的调查,但我不想在代码中使用它.


Him*_*dri 11

尝试IDENT_CURRENT:

Select IDENT_CURRENT('yourtablename')
Run Code Online (Sandbox Code Playgroud)

即使您尚未在当前会话中插入任何行,这仍然有效:

返回为指定表或视图生成的最后一个标识值.生成的最后一个标识值可以用于任何会话和任何范围.

  • 真好 这将获取使用的最新值,并且MSDN页面会警告“请谨慎使用IDENT_CURRENT来预测下一个生成的标识值。由于其他会话执行的插入操作,实际生成的值可能不同于IDENT_CURRENT加上IDENTITY_SEED。” (2认同)

Jef*_*nby 5

这有点奇怪,但可以使用:

如果您想知道下一个值,请先获得最大的值加一个:

SELECT max(id) FROM yourtable
Run Code Online (Sandbox Code Playgroud)

要使此工作有效,您需要在插入时重置身份:

DECLARE @value INTEGER

SELECT @value = max(id) + 1 FROM yourtable

DBCC CHECKIDENT (yourtable, reseed, @value)

INSERT INTO yourtable ...
Run Code Online (Sandbox Code Playgroud)

这不是一个优雅的解决方案,但我还没有喝咖啡;-)

(这还假定您的过程或第一和第二代码块之间的任何其他过程均未对表进行任何操作)。