【问题标题】:using @@identity when a trigger is fired in response to an INSERT, and the trigger executes another INSERT statement在触发触发器以响应 INSERT 并且触发器执行另一个 INSERT 语句时使用 @@identity
【发布时间】:2011-09-14 12:19:50
【问题描述】:

我有以下表格:

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 语句运行时,我得到tbl_workshop_temp 中插入行的id,而不是id 中插入tbl_workshop

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

【问题讨论】:

  • 我能想到一个可行的办法,但你真的应该改变你的代码。为什么无法更改它以调用正确的函数?
  • 因为代码是别人用VB6写的。我可以只更改数据库。
  • 此 SQL 语句在您无权访问的编译代码中是什么?确实,您需要对此进行更改,但假设您正在寻找短期解决方案,我将发布我的(可怕的)想法。
  • @Raymond 下次不要让“其他人”将糟糕的临时 SQL 放入他们的应用程序 - 鼓励/坚持存储过程!
  • 是的,你是对的。我会做的。

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


【解决方案1】:

你不能欺骗@@identity 返回一些不同的值。您可以做的是从tbl_workshop_temp 中删除IDENTITY 属性,并且在该列中没有递增值(只需使用与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 如果没有显示任何额外的代码来执行多行插入,这将失败,但是id 可能在tbl_workshop_temp 中是唯一的
  • @Martin,是的,这是一个重要的免责声明......我将把它添加到答案中......谢谢。
  • @Aaron Bertan 我更改了您的代码并使用了此触发器。我做得对吗? create trigger InsertedWorkshop on tbl_workshop for insert as declare @id int select @id=id from inserted insert into tbl_workshop_temp (id,code,insupkey) select @id,id,1 from inserted 我只想在我的id 字段中有一个唯一的键,所以我使用了tbl_workshopid。两个用户同时插入两条记录不会有问题吗?
  • 如果表为空COALESCE(MAX(id),0) + 1更好;否则你会得到 NULL 的 id。
  • @JustAMartin 是的,这里的答案很简单,因为我们可以假设在大多数情况下,像这样的表格不会突然从有行变成完全空的。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    你可以像这样使用 where 子句在插入的行中选择

    SELECT ID_FIRST_TABLE FROM TRIGGERED_TABLE WHERE TRIGGERED_ID = @@Identity
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 2013-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-04
      相关资源
      最近更新 更多