【问题标题】:How to get a table identity inserted by instead of insert trigger?如何获取插入的表标识而不是插入触发器?
【发布时间】:2015-05-14 19:09:22
【问题描述】:

我有一个问题描述如下:我有一个表,而不是插入触发器:

create table TMessage (ID int identity(1,1), dscp varchar(50))
GO
Alter trigger tr_tmessage on tmessage
instead of insert
as

--Set NoCount On

  insert into tmessage
  select dscp from inserted
GO
Alter proc P1
As

--Set NoCount On

insert into tmessage
(dscp)
values('some data')

Select SCOPE_IDENTITY()

GO

当我执行 P1 时,它为 SCOPE_IDENTITY() 返回 Null 而不是表的标识。我什至在proc的插入语句中尝试了Output子句。但在这种情况下,从插入到输出子句中填充的输出表标识字段再次为 0。

任何帮助将不胜感激。

【问题讨论】:

  • 您需要向我们展示触发器!
  • 你试过@@IDENTITY而不是scope_identity()吗?
  • 尝试使用IDENT_CURRENT(‘tablename’) 而不是scope_identity()。 read this article to learn the differences.
  • @ZoharPeled 我需要在会话中创建相同的身份,因为可能有其他会话同时插入到表中。
  • @Sahand,不,这是数据库设计中的错误

标签: sql-server triggers


【解决方案1】:

嗯,你已经把自己弄得一团糟。
一方面,您需要表上的instead of insert 触发器,但另一方面,您希望将此触发器生成的标识返回给激活它的存储过程。

由于无法向触发器发送参数或从触发器发送参数,因此您必须做以下三件事之一:

  1. 找到一些方法来消除对它的需要,而不是触发。
    这是我最好的建议。

  2. 将您的存储过程分成两部分:一部分将执行所有操作,直到 insert into 语句(包括它),从而激活 instead of insert 触发器,另一部分将执行之后所需的所有操作扳机。这样您就可以在instead of insert 触发器中使用scope_identity() 并将其返回值作为参数发送到第二个存储过程。
    注意:这种设计意味着您必须插入一条记录一个。如果您尝试插入多于一条记录,scope_identity() 将仅返回触发器插入的最后一行的标识。

  3. 找到某种方式在存储过程和instead of 触发器之间传递数据。由于触发器不能排除或返回参数,因此您将不得不使用临时表或常规表。这个建议的解决方案仅作为最后的手段提出,因为它会使您的代码复杂化并且可能还会导致一些性能问题。此外,您必须找到一种方法来保持存储过程的执行,直到代替触发器完成它的工作。我可以给你一些关于如何在过程和触发器之间共享数据的建议,但我真的建议不要选择这种解决方案。

【讨论】:

  • 感谢您的 cmets。对于解决方案 1。我们必须使用触发器,因为该表的另一个触发器中有很多业务代码。我们添加了此触发器以在插入之前验证数据。如果我们将逻辑放入第一个触发器,那么在数据无效事件上,我们必须回滚触发器,这将导致整个过程的回滚。但是这样,第二个触发器仅在数据有效时才插入表中,否则不会插入任何内容并继续该过程。对于没有 3,我已经使用 proc 和 trigger 中的临时表解决了问题。
  • 但正如你所说,由于潜在的性能问题,我对此并不满意。您能否详细解释一下解决方案 2。在这种情况下,我们仍然需要将范围标识返回给第一个 proc,然后将其传递给另一个。那怎么办呢?
  • 解决方案2的要点是您不需要将身份重新运行到第一个过程,只需在插入后使用第二个执行您在原始过程中所做的任何事情。
  • 顺便说一句,如果此答案为您的问题提供了解决方案,您应该接受它,以便其他人知道问题已解决。如果您找到了不同的解决方案,请将其作为答案发布并接受。
  • 对不起,我仍然不明白解决方案 2。我重复我的问题。我们运行 scope_IDENTITY 而不是 insert。我们甚至无法将 id 传递给调用 proc。你是如何解决这个问题的?我在这里错过了什么吗?
【解决方案2】:

SCOPE_IDENTITY() 返回当前作用域的值,即存储过程之外的存储过程,它将为空。使用@@identity 获取最后插入的标识。

【讨论】:

  • 投反对票原因:请在建议答案之前阅读 cmets。此外,@@identity 将返回空洞数据库中 any 身份的最后一个值。在这种情况下不是很有用。
  • 对。无法使用触发器类型和范围身份来获取身份列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 2019-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多