在响应INSERT而触发触发器时使用@@ identity,并且触发器执行另一个INSERT语句

时间:2011-09-14 12:19:50

标签: sql-server sql-server-2000 identity

我有以下表格:

tbl_workshop
id  int  identity
Name nvarchar(10)
Address nvarchar(40)


tbl_workshop_temp
id int identity
code int
InsUpkey  smallint

我有以下陈述

insert into tbl_workshop
    (Name,Address)
     values('x','y')
select @@identity  -- My problem is here

我也有以下触发器插入:

create trigger InsertedWorkshop
on tbl_workshop
for insert
as
  insert into tbl_workshop_temp
     (code,InsUpKey)
    select id,1
        from inserted

select @@identity语句运行时,我在id中插入tbl_workshop_temp而不是id中插入的tbl_workshop

我知道我必须使用scope_identity,但我无法更改代码。我只能改变我的触发器。 我现在应该怎么做?请帮帮我。

3 个答案:

答案 0 :(得分:4)

你不能欺骗@@identity返回一些不同的值。您可以做的是从IDENTITY中删除tbl_workshop_temp属性,并且该列中没有递增值(只使用与tbl_workshop相同的ID),完全删除列,或者以这种方式在触发器中填充它(这意味着它只适用于一行):

DECLARE @id INT;

SELECT @id = MAX(id) + 1
   FROM dbo.tbl_workshop_temp WITH (UPDLOCK, HOLDLOCK); -- important

insert into dbo.tbl_workshop_temp
     (id,code,InsUpKey)
    select @id,id,1
        from inserted;

使用SQL Server 2005及更高版本,您可以更加聪明 - 您可以更改上面的内容,以便使用ROW_NUMBER()来处理多行,或者您可以使用INSTEAD OF TRIGGER代替(不需要双关语)并简单地更改插入语句的顺序。但是对于SQL Server 2000,您的选择确实有限......

答案 1 :(得分:1)

有关每个身份选择的工作原理,请参阅this question。您将不得不更改初始INSERT的代码以修复此问题。 @@identity始终从会话中获取最后一个ID,并且由于触发器是同一会话的一部分,因此您必须更改在应用程序中拾取ID的方式。

答案 2 :(得分:0)

您可以在插入的行中选择where where子句,如此

SELECT ID_FIRST_TABLE FROM TRIGGERED_TABLE WHERE TRIGGERED_ID = @@Identity