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

时间:2009-10-09 09:52:54

标签: sql sql-server

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

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

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

5 个答案:

答案 0 :(得分:11)

尝试IDENT_CURRENT

Select IDENT_CURRENT('yourtablename')

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

  

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

答案 1 :(得分:11)

编辑:

在花了几个小时比较整个页面转储后,我意识到有一种更简单的方法,我应该留在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)

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

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

哦,还有捷径:

select ident_current('foo') + ident_incr('foo')

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

答案 2 :(得分:3)

您可以使用UNIQUEIDENTIFIER(Guid)列作为唯一行标识符并插入已知值,而不是使用IDENTITY列。

另一个选项(我使用的)是SET IDENTITY_INSERT ON,其中行ID在源控制的单个“文档”中管理。

答案 3 :(得分:3)

这有点奇怪,但它会起作用:

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

SELECT max(id) FROM yourtable

要使其工作,您需要在插入时重置标识:

DECLARE @value INTEGER

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

DBCC CHECKIDENT (yourtable, reseed, @value)

INSERT INTO yourtable ...

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

(这也假设您的进程或第一个和第二个代码块之间的任何其他进程没有对表执行任何操作。)

答案 4 :(得分:1)

您可以非常轻松地确定使用的最后一个值是:

SELECT
    last_value
FROM 
    sys.identity_columns
WHERE
    object_id = OBJECT_ID('yourtablename')

通常,下一个ID将是last_value + 1 - 但不能保证。

马克