T-SQL EXEC和范围

时间:2009-04-08 21:02:19

标签: sql tsql scope identity

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

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

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

5 个答案:

答案 0 :(得分:6)

尝试

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

或更好,根据this

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

答案 1 :(得分:4)

根据微软的T-SQL文档:

  

IDENT_CURRENT类似于SQL   Server 2000身份功能   SCOPE_IDENTITY和@@ IDENTITY。所有   三个函数返回最后生成的   身份价值观。但是,范围   以及定义最后一个的会话   在每个功能中都有所不同:

     

IDENT_CURRENT返回最后一个   为a生成的身份值   任何会话和任何会议中的特定表   范围。

     

@@ IDENTITY返回最后一个身份   为...中的任何表生成的值   当前会议,涵盖所有范围。

     

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

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

我确保使用SCOPE_IDENTITY - 这应该可靠。

马克

答案 2 :(得分: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;

答案 3 :(得分:1)

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

答案 4 :(得分: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

继续多次运行以了解其工作原理。