删除后触发触发器

Posted

技术标签:

【中文标题】删除后触发触发器【英文标题】:fire the trigger after the delete 【发布时间】:2018-04-24 13:13:39 【问题描述】:

我正在使用after delete 触发器,触发器的作用是在删除另一个行时更新一行;但问题是,我更新行的方式与已删除行获得相同的键:但由于after delete 触发器保留了假定的已删除行,并且由于键违规,我无法更新另一行,是有什么方法可以明确删除该行并然后触发触发器(我不需要回滚)

所以这是我的触发器:

CREATE TRIGGER REORDONNE
AFTER DELETE  ON TEST1_TEST2
AS
BEGIN

DECLARE @oldOrder int

SELECT @oldOrder = ListOrder FROM deleted

UPDATE TEST1_TEST2
SET ListOrder=ListOrder-1
WHERE ListOrder > @oldOrder
END;

我的表 TEST1_TEST2 是这样的:

我的表的KEY是(LONSId,LOId,ListOrder)

然后我执行这个请求:

从 TEST1_TEST2 中删除 其中 NSId=13 和 Id=1

问题是当我尝试删除第 4 行时,触发器将尝试更新第 5 行并将 ListOrder 的值更改为 1,但我收到 KEY 错误,因为这 2 行将具有相同的键说:

Msg 2627,Niveau 14,État 1,Procédure REORDONNE,Ligne 19

违反约束唯一键“IX_TEST1_TEST2”。 Impossible d'insérer une clé en double dans l'objet 'dbo.TEST1_TEST2'。

我希望这足够清楚

【问题讨论】:

请向我们展示您的查询 你的问题好像少了点什么,你能猜到是什么吗? 您可能还想重新考虑您的声明的措辞。一个很长的句子只会让人感到困惑和难以阅读。 分享表结构、样本数据、预期结果和你目前的工作。 我做了,希望它更清楚 【参考方案1】:

问题是您尝试重新编号 所有 行,其 ListOrder 列值高于已删除行之一 - 而不仅仅是共享相同 LONSId 和 @987654323 的行@值1。所以我们需要收紧UPDATE 以更好地定位它。

虽然我们这样做了,但我们不妨也让触发器多行删除正确:

CREATE TRIGGER REORDONNE
AFTER DELETE  ON TEST1_TEST2
AS
BEGIN
;With Ranges as (
    select
        LONSId,
        LOId,
        ListOrder,
        COUNT(*) OVER (PARTITION BY LONSId,LOId ORDER BY ListOrder) as Cnt,
        LAG(ListOrder) OVER (PARTITION BY LONSId,LOId ORDER BY ListOrder desc)
                  as NextListOrder
    from
        deleted
)
update t
set ListOrder= t.ListOrder- Cnt
from
    TEST1_TEST2 t
        inner join
    Ranges r
        on
            t.LONSId = r.LONSId and
            t.LOId = r.LOId and
            t.ListOrder > r.ListOrder and
            (r.NextListOrder is null or r.NextListOrder > t.ListOrder)
END;

希望这里的逻辑很清楚。我们计算出表中仍然存在的哪些行应该受到来自deleted 的每一行的影响,并确保我们只针对这些行,考虑到 entire 键。

(如果您的 SQL Server 版本不支持 LAG,那么简单搜索 SO 应该会找到大量在旧版本上伪造它的示例。如果它不支持 ROW_NUMBERCTEs 那么你也许可以伪造那些,但实际上,从这些机器升级已经超出了时间)。


1例如在您的示例delete from TEST1_TEST2 where NSId=13 and Id=1 中,您的触发器将尝试更新所有ListOrder 大于1 的行。您被告知的实际冲突(或至少其中一个)是针对当前键 (2,2,2) 的行,它受您的更新语句影响,但是 (2 ,2,1) 不是被删除的行,所以这是重复的键值。

【讨论】:

ohhhhhh 非常感谢你,你是一个救生员。也感谢您的多行删除正确,这太好了。 @omarbezzanou - 我确实希望您花时间考虑并从这种情况中学习。我建议您误诊了这种情况,但您似乎坚持认为您了解情况并且只需要“真正删除”行的帮助,而实际上不存在这种情况。在进行故障排除时,挑战所有您的假设,并且不一定要排除其他人的疑虑。

以上是关于删除后触发触发器的主要内容,如果未能解决你的问题,请参考以下文章

如何创建删除后触发器

发送嵌入后删除触发器 |不和谐.js

删除触发器后无法删除的回收站对象

插入或删除后的 Oracle 触发器

更新/插入/删除表中的行后触发的触发器有问题

PostgresQL 中超出堆栈深度限制(删除触发器后)