2011-05-20 60 views
1

我有一张桌子和一个触发器如何使用OUTPUT获取身份列的值 - SQL服务器

create table test(id int not null identity(1,1) primary key, data int); 
create trigger insteadTestInsert ON test INSTEAD OF INSERT 
AS 
BEGIN 
    INSERT INTO test(data) select data FROM inserted; 
END; 

启用触发,下面的查询

declare @tmp_table table(id int, int_val int); 
insert into test(data) 
output inserted.* into @tmp_table 
values (10); 
select * from @tmp_table; 

返回ID = 0, int_val = 10。
如果我禁用(或丢弃)触发器,查询将返回适当的值id

如何让OUTPUT在表格变量中插入正确的结果?

回答

1

这一个实际工作。

declare @tmp_table table(seq int identity, id int, int_val int); 
insert into test(data) 
output inserted.data into @tmp_table(int_val) 
values (11),(12),(13); 

update @tmp_table set id = seq + @@identity - @@rowcount 
select * from @tmp_table; 
select top 2 * from test order by id desc; 

的限制是,你不能对表test那会“破坏” @@ IDENTITY变量任何其他触发器。

+0

非常感谢。非常好。 – a1ex07 2011-05-20 02:30:02

+0

@ a1ex07 - 准备好看到微妙的错误:) – 2011-05-20 02:37:13

+0

@ a1ex07 - 不能保证插入临时表的数据与从“插入”返回的数据的顺序相同。 – 2011-05-20 02:42:25

2

MSDN

列从OUTPUT返回反映 的数据,因为它是INSERT,UPDATE 后,或DELETE语句 完成但 触发器执行之前的。

所以问题是,在你的触发器执行之前插入没有id设置。

即使这样

create trigger insteadTestInsert on test instead of insert 
as 
begin 
    return; 
end 

触发删除内容,你会看到inserted仍填充虽然没有什么是inserted到表中。基本上insertedoutput声明匹配inserted里面的触发器。

+0

是的,我读过这个,但可能不够仔细。无论记录是否被插入,我预计身份栏填充;这对于检查哪些行实际插入是有用的。感谢您的解释。 – a1ex07 2011-05-20 01:51:56

1

这是一个黑客,但它的工作原理:

declare @tmp_table table(id int, int_val int); 
insert into test(data) 
output @@IDENTITY + 1, inserted.data into @tmp_table 
values (10); 
select * from @tmp_table; 

http://msdn.microsoft.com/en-us/library/ms190315.aspx的具体使用@@ IDENTITY。

+1

嗯... @@ IDENTITY - 非常糟糕。 :)。如果插入多行,也会显得有趣,对吗? – 2011-05-20 01:53:59

+0

谢谢,这是一个不错的选择,但不幸的是它只有插入1行才有效。 – a1ex07 2011-05-20 01:54:38

+0

你们是对的。它只会在插入一行时起作用。我不确定用例是什么,所以我仍然发布。 – 2011-05-20 02:11:53

相关问题