SQL Server 删除触发器以更新同一表中的多个列
Posted
技术标签:
【中文标题】SQL Server 删除触发器以更新同一表中的多个列【英文标题】:SQL Server Delete Trigger To Update Multiple Columns in Same Table 【发布时间】:2010-06-23 15:52:22 【问题描述】:我有以下触发器:
CREATE TRIGGER Users_Delete
ON Users
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
-- Patients
UPDATE Patients SET ModifiedByID=NULL WHERE ModifiedByID=ID;
UPDATE Patients SET CreatedByID=NULL WHERE CreatedByID=ID;
UPDATE Patients SET DeletedByID=NULL WHERE DeletedByID=ID;
END
我想知道是否有办法将这三个 UPDATE 语句“组合”成如下所示的内容:
UPDATE Patients SET
(ModifiedByID=NULL WHERE ModifiedByID=ID) OR
(CreatedByID=NULL WHERE CreatedByID=ID) OR
(DeletedByID=NULL WHERE DeletedByID=ID);
我真的很想只用一个语句来提高性能。
我之所以在ON DELETE
上为FOREIGN KEY
使用触发器,是因为我收到一个错误,即拥有多个ON DELETE
会导致以下错误:
在表“Patients”上引入 FOREIGN KEY 约束“FK_Patients_Users_Deleted”可能 导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
编辑:在所有 ModifiedByID、CreatedByID、DeletedByID 列上都有索引会更好吗?删除用户当然很少见,那么是否值得为 3 列添加索引?
【问题讨论】:
令我困扰的是,您完全改变了这些数据。停用用户比删除具有关联的子记录的用户要好。现在您将无法分辨谁创建了该记录,这可能具有一定的重要性,尤其是当用户因性能原因被解雇时。 这实际上是一个非常有效的观点。我会考虑到这一点。 【参考方案1】:关于你原来的问题。
不是真的。我想不出比这更好的了
UPDATE Patients
SET ModifiedByID= CASE WHEN ModifiedByID=ID THEN NULL ELSE ModifiedByID END,
CreatedByID= CASE WHEN CreatedByID=ID THEN NULL ELSE CreatedByID END,
DeletedByID= CASE WHEN DeletedByID=ID THEN NULL ELSE DeletedByID END
WHERE
ModifiedByID IN (SELECT ID FROM DELETED)
OR
CreatedByID IN (SELECT ID FROM DELETED)
OR
DeletedByID IN (SELECT ID FROM DELETED)
请注意,这可以正确处理多行删除。从您发布的内容中不清楚您当前的触发器是否有效。
【讨论】:
重要的一点,许多人针对单个记录编写代码并由于多行操作而失败。【参考方案2】:这样的?
UPDATE Patients SET
ModifiedByID = CASE WHEN ModifiedByID=ID THEN Null ELSE ModifiedById END,
CreatedByID = CASE WHEN CreatedByID=ID THEN Null ELSE CreatedById END,
DeletedByID = CASE WHEN DeletedByID=ID THEN Null ELSE DeletedById END
WHERE (ModifiedByID = ID OR CreatedByID = ID OR DeletedByID = ID)
【讨论】:
我猜您会看到性能提升的唯一情况是,Patients 表非常大并且您在 ModifiedByID、CreatedByID 或 DeletedByID 上没有适当的索引。在这种情况下,解决方案是添加索引 那么您认为最好将这 3 个语句与 ModifiedByID/CreatedByID/DeletedByID 上的索引一起使用? 我强烈怀疑它几乎没有区别,所以我会选择更容易理解的那个(即三个语句) 好的,我会去的。您认为在 3 列上有索引很重要吗?更新索引不是很昂贵吗? 一般经验法则:在写入数据时进行打击,以便加快读取数据的速度。优化 SQL 很有趣,因为您可以将读取提高几个数量级。顺便说一句,我会注意到 HLGEM 关于你为什么要这样做的评论(当你可以进行软删除时),以及 Martin Smith 关于多次删除的观点,这很容易被忽视。【参考方案3】:您可以在一个语句中做到这一点,但这并不一定会提高性能。
UPDATE
Patients
SET
ModifiedByID = CASE WHEN ModifiedID = ID THEN NULL ELSE ModifiedID,
CreatedByID = CASE WHEN CreatedByID = ID THEN NULL ELSE CreatedByID,
DeletedByID = CASE WHEN DeletedByID = ID THEN NULL ELSE DeletedByID
我真的怀疑这会表现得更好。
【讨论】:
以上是关于SQL Server 删除触发器以更新同一表中的多个列的主要内容,如果未能解决你的问题,请参考以下文章