【发布时间】:2009-01-02 20:25:13
【问题描述】:
我幼儿园的 SQL Server 告诉我,在插入和删除的伪表中可能会触发多行触发器。我在编写触发代码时大多考虑到这一点,通常会导致一些基于光标的混乱。现在我真的只能测试它们一次发射一行。如何生成多行触发器,SQL Server 是否真的会发送多行触发器?我可以设置一个标志,让 SQL Server 只触发单行触发器吗?
【问题讨论】:
标签: sql-server database
我幼儿园的 SQL Server 告诉我,在插入和删除的伪表中可能会触发多行触发器。我在编写触发代码时大多考虑到这一点,通常会导致一些基于光标的混乱。现在我真的只能测试它们一次发射一行。如何生成多行触发器,SQL Server 是否真的会发送多行触发器?我可以设置一个标志,让 SQL Server 只触发单行触发器吗?
【问题讨论】:
标签: sql-server database
触发器定义应始终处理多行。
取自SQLTeam:
-- BAD Trigger code following:
CREATE TRIGGER trg_Table1
ON Table1
For UPDATE
AS
DECLARE @var1 int, @var2 varchar(50)
SELECT @var1 = Table1_ID, @var2 = Column2
FROM inserted
UPDATE Table2
SET SomeColumn = @var2
WHERE Table1_ID = @var1
上述触发器只对插入表的最后一行起作用。
这就是你应该如何实现它:
CREATE TRIGGER trg_Table1
ON Table1
FOR UPDATE
AS
UPDATE t2
SET SomeColumn = i.SomeColumn
FROM Table2 t2
INNER JOIN inserted i
ON t2.Table1_ID = i.Table1_ID
【讨论】:
SET SomeColumn = t1.SomeColumn 好像写错了,别名t1 定义在哪里?尽管如此 +1,因为现在我明白为什么我的触发器只针对最后插入的行触发。
是的,如果一条语句影响多行,它应该由单个触发器调用处理,因为您可能希望恢复整个事务。不可能在逻辑上将其拆分为单独的触发器调用,我认为 SQL Server 不提供这样的标志。您可以通过发出影响多行的 UPDATE 或 DELETE 语句来使 SQL Server 调用具有多行的触发器。
【讨论】:
首先让我担心的是,您正在使用游标使触发器处理多行。不要那样做!使用基于集合的语句来代替插入或删除的伪表。在我来这里工作之前,有人将其中一个基于光标的触发器放在我们的数据库中。处理 400,00 条记录插入需要 40 多分钟(而且我经常需要为一个客户在此表中插入超过 100,000 条记录)。将其更改为基于集合的解决方案将时间更改为不到一分钟。虽然所有触发器都必须能够处理多行,但您绝不能通过制造性能噩梦来做到这一点。
如果您可以为 cusor 编写 select 语句,则可以基于相同的基于 set 的 select 语句编写插入、更新或删除。
【讨论】:
我一直编写触发器来处理多行,我的理解是,如果一个查询插入/更新/删除多行,那么只有一个触发器会触发,因此您必须使用游标来移动一个一个的记录。
【讨论】:
一个 SQL 语句总是调用一个触发器执行 - 这是触发器定义的一部分。 (这也是一种情况,似乎每个编写触发器的人都至少有一次绊倒。)我相信您可以通过检查 @@ROWCOUNT 发现有多少记录受到影响。
【讨论】: