5

假设我的主体中有一个存储过程:

EXEC 'INSERT INTO ' + quotename(@table) ' blah...'
SELECT IDENT_CURRENT('' + @table + '')

IDENT_CURRENT() 是否保证在 EXEC 中获得插入该行的标识?IDENT_CURRENT() “返回在任何会话和任何范围内为特定表生成的最后一个标识值”,但 EXEC 中的范围与存储过程不同,对吧?

我想确保如果一次多次调用存储过程,则选择正确的标识。

编辑:或者我是否需要在 EXEC 中同时执行 INSERT 和 SELECT,如下所示:

declare @insert nvarchar
set @insert = 
    'INSERT INTO ' + quotename(@table) ' blah...' +
    'SELECT IDENT_CURRENT(''' + @table + ''')'
EXEC @insert

如果是这种情况,如果我想继续使用 T-SQL 中的更多代码,我该如何选择 EXEC 的结果?像这样(虽然它显然是不正确的):

declare @insert nvarchar
set @insert = 
    'INSERT INTO ' + quotename(@table) ' blah...' +
    'SELECT IDENT_CURRENT(''' + @table + ''')'

declare @ident int
set @ident = EXEC @insert

-- more code
SELECT * FROM blah

更新:在第一个片段中,如果我选择 SCOPE_IDENTITY() 而不是使用 IDENT_CURRENT(),则 SELECT 将返回 NULL。:(

4

5 回答 5

6

尝试

EXEC 'INSERT INTO ' + quotename(@table) ' blah...; SELECT @@IDENTITY'

或者更好,根据这个

EXEC 'INSERT INTO ' + quotename(@table) ' blah...; SELECT SCOPE_IDENTITY()'
于 2009-04-08T21:04:30.697 回答
4

根据微软的 T-SQL 文档:

IDENT_CURRENT 类似于 SQL Server 2000 标识函数 SCOPE_IDENTITY 和 @@IDENTITY。所有三个函数都返回最后生成的标识值。但是,在每个函数中定义 last 的范围和会话不同:

IDENT_CURRENT 返回为任何会话和任何范围内的特定表生成的最后一个标识值。

@@IDENTITY 返回为当前会话中的任何表在所有范围内生成的最后一个标识值。

SCOPE_IDENTITY 返回为当前会话和当前范围中的任何表生成的最后一个标识值。

所以我想说,不,IDENT_CURRENT不能保证给你正确的价值。它可能是在不同会话中插入的最后一个 IDENTITY 值。

我会确保改用 SCOPE_IDENTITY - 这应该可以可靠地工作。

马克

于 2009-04-08T21:07:34.340 回答
2

http://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor-parallel-plan-and-solution/

SCOPE_IDENTITY() 中有一个错误 我已将存储过程切换到用于从插入中检索默认值的方法:

 declare @TheNewIds table (Id bigint, Guid uniqueidentifier)
 insert [dbo].[TestTable] output inserted.Id, inserted.Guid into @TheNewIds
 values (default);
 select @Id = [Id], @Guid = [Guid] from @TheNewIds;
于 2009-04-08T21:16:31.417 回答
1

我认为 Scope_Identity() 是您正在寻找的,它将为您提供当前范围内的最新标识。

于 2009-04-08T21:06:48.757 回答
0

我想通过使用 OUTPUT 关键字加入我最喜欢的解决方案。由于 INSERT 一次可以支持多行,我们想知道插入的身份。开始:

 
-- source table
if object_id('Source') is not null drop table Source
create table Source
(
    Value datetime
)
-- populate source
insert Source select getdate()
waitfor delay '00:00.1'
insert Source select getdate()
waitfor delay '00:00.1'
insert Source select getdate()
select * from Source -- test
-- destination table
if object_id('Destination') is null
create table Destination
(
    Id int identity(1, 1),
    Value datetime
)
-- tracking table to keep all generated Id by insertion of table Destination
if object_id('tempdb..#Track') is null
create table #Track 
(
    Id int  
)
else delete #Track
-- copy source into destination, track the Id using OUTPUT
insert Destination output inserted.Id into #Track select Value from Source
select Id from #Track -- list out all generated Ids

继续运行它多次以感受它是如何工作的。

于 2009-04-21T09:52:40.690 回答