2015-02-06 87 views
0

我知道,當我將一行插入到具有標識列的表中時,我可以使用SELECT @@IDENTITY來檢索剛插入的行的標識。SQL Server是否具有返回多個值的@@ IDENTITY?

如果我做了一個插入10行到同一個表的插入語句,是否有一種實用的方法來獲得所有10行的ID?

+0

也許是觸發器? – 2015-02-06 22:12:19

+3

好的,如果你只有一條記錄,那麼你可以永遠不要使用@@ identity ieven。如果有人將觸發器插入帶有標識的另一個表中,則可能返回錯誤的值。 – HLGEM 2015-02-06 22:12:24

+0

'OUTPUT'子句可以與'INSERT','UPDATE','DELETE'和'MERGE'一起使用,並在'UPDATE'的情況下提供對值和值之前的訪問。 – HABO 2015-02-07 01:18:11

回答

3

是的,使用OUTPUT子句。無論如何,你應該使用它作爲第一選擇。

更好的是,您可以使用OUTPUT返回多個字段。所以你可以使用代理鍵和自然鍵來擴充一個表變量。

0

帶有INSERT的OUTPUT子句缺少:在插入源表中爲每個行分配Id後無法說出。

declare @Persistent table (Id int not null identity primary key, Value varchar(10)); 
declare @Temporary table (Id int not null primary key, Value varchar(10)); 

insert into @Temporary values (11, 'AAA'), (22, 'AAA'), (33, 'CCC'); 

insert into @Persistent (Value) 
output inserted.Id 
select Value from @Temporary; 

在上面的例子中,我們將得到@Persistent表實際ID列表,但我們不能在@Temporary表的ID映射到IDS,因爲OUPTUT在INSERT不允許獲得源表中的字段 - 它只獲取INSERTED表格字段。

與INSERT相反,MERGE中的OUPTUT子句允許從源表中獲取字段。因此,使用與合併輸出解決了這個問題:

merge into @Persistent as target 
    using @Temporary as source on source.Id = target.Id   
when matched then 
    update set Value = source.Value  
when not matched then 
    insert (Value) values (Value)  
output 
    inserted.Id, source.Id; 

以下是使用MERGE命令插入,更新,刪除父子表中的行例。從MERGE OUTPUT收集目標源映射非常有用:

-- definition of persistent tables 

declare @Parents table (Id int not null identity primary key, Name varchar(10)); 
declare @Children table (Id int not null identity primary key, ParentId int, Name varchar(10)); 

-- imagine that persistent tables contain some data 

insert into @Parents (Name) select 'Alfa'; 
insert into @Children (ParentId, Name) select 1, 'Delta'; 

-- definition of temporary tables 

declare @TempParents table (Id int not null primary key, Name varchar(10)); 
declare @TempChildren table (Id int not null primary key, ParentId int, Name varchar(10)); 

-- data to insert (with negative Ids) and update (with real positive Ids) 

insert into @TempParents values 
    (1, 'Alpha'), (-2, 'Bravo'), (-1, 'Charlie'); 

insert into @TempChildren values 
    (-9, 1, 'Alpha-1'), (-8, 1, 'Alpha-2'), (-7, 1, 'Alpha-2'), 
    (-6, -2, 'Bravo-1'), (-5, -2, 'Bravo-2'), (-4, -2, 'Bravo-3'), 
    (-3, -1, 'Charlie-1'), (-2, -1, 'Charlie-2'), (-1, -1, 'Charlie-3'); 

-- table to collect mapping Ids from @TempParents to @Parents 

declare @ParentIdMaps table (ParentId int, TempParentId int) 

-- merge data into @Parents table and collection of mapping Ids 

merge into @Parents as target 
using @TempParents as source on source.Id = target.Id  
when matched then 
    update set Name = source.Name 
when not matched then 
    insert (Name) values (Name) 
output 
    inserted.Id, source.Id 
into @ParentIdMaps 
    (ParentId, TempParentId); 

-- merge data into @Children table and use of mapping Ids 

merge into @Children as target 
using 
    (
     select 
      Id, 
      ParentId = m.ParentId, 
      Name 
     from 
      @TempChildren tc 
      inner join @ParentIdMaps m on m.TempParentId = tc.ParentId  
    ) 
    as source on source.Id = target.Id  
when matched then 
    update set ParentId = source.ParentId, Name = source.Name 
when not matched then 
    insert (ParentId, Name) values (ParentId, Name) 
when not matched by source and target.ParentId in (select Id from @TempParents) then 
    delete; 

-- checking the result 
-- see that 'Alfa' was renamed to 'Alpha' 
-- and 'Delta' was deleted because it was not mentioned in @TempChildren 

select 
    p.*, 
    c.* 
from  
    @Parents p 
    inner join @Children c on c.ParentId = p.Id 
order by 
    p.Id, 
    c.Id;