删除后触发触发器
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_NUMBER
或 CTE
s 那么你也许可以伪造那些,但实际上,从这些机器升级已经超出了时间)。
1例如在您的示例delete from TEST1_TEST2 where NSId=13 and Id=1
中,您的触发器将尝试更新所有ListOrder
大于1
的行。您被告知的实际冲突(或至少其中一个)是针对当前键 (2,2,2) 的行,它也受您的更新语句影响,但是 (2 ,2,1) 不是被删除的行,所以这是重复的键值。
【讨论】:
ohhhhhh 非常感谢你,你是一个救生员。也感谢您的多行删除正确,这太好了。 @omarbezzanou - 我确实希望您花时间考虑并从这种情况中学习。我建议您误诊了这种情况,但您似乎坚持认为您了解情况并且只需要“真正删除”行的帮助,而实际上不存在这种情况。在进行故障排除时,挑战所有您的假设,并且不一定要排除其他人的疑虑。以上是关于删除后触发触发器的主要内容,如果未能解决你的问题,请参考以下文章