簡體   English   中英

T-SQL EXEC和范圍

[英]T-SQL EXEC and scope

假設我的主體中有一個存儲過程:

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。 :(

嘗試

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

或者更好的,按照

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

根據微軟的T-SQL文檔:

IDENT_CURRENT類似於SQL Server 2000身份函數SCOPE_IDENTITY和@@ IDENTITY。 所有三個函數都返回最后生成的標識值。 但是,在每個函數中定義last的范圍和會話有所不同:

IDENT_CURRENT返回在任何會話和任何范圍內為特定表生成的最后一個標識值。

@@ IDENTITY返回在所有范圍內為當前會話中的任何表生成的最后一個標識值。

SCOPE_IDENTITY返回為當前會話中的任何表和當前范圍生成的最后一個標識值。

所以我想說,不,IDENT_CURRENT 不能保證給你正確的價值。 它可能是在不同會話中插入的最后一個IDENTITY值。

我會確保使用SCOPE_IDENTITY - 這應該可靠地工作。

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;

我認為Scope_Identity()是您正在尋找的,它將為您提供當前范圍內的最新標識。

我想通過使用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

繼續多次運行以了解它是如何工作的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM