如何使用 SQL Server 更新触发器中的原始值更改第二条记录

Posted

技术标签:

【中文标题】如何使用 SQL Server 更新触发器中的原始值更改第二条记录【英文标题】:How to use the original value in a SQL Server update trigger to change a second record 【发布时间】:2018-02-01 18:23:47 【问题描述】:

我有一个 SQL Server 表,其中包含学生、同类群组、课程、毕业日期和状态。一些学生的记录是专门绑定在一起的——如果某一行的队列发生变化,则状态为 2 的另一行的队列也需要更改。在大多数情况下,我以编程方式捕捉到这一点,但有很多方法可以改变学生的队列,所以我们错过了一些。

基本上如果有人运行第一行更新语句,第二行也需要运行

UPDATE StudentPrograms
SET Cohort = 201610
WHERE Student = 'A1234' AND Program = 'MBA' AND Cohort = 201510

UPDATE StudentPrograms
SET Cohort = 201610
WHERE Student = 'A1234' AND Cohort = 201510 AND Status = 2

我想在表上放置一个更新触发器以更改两个同类群组,但问题是我无法弄清楚如何同时捕获标识需要更改的记录的起始同类群组和它将要更改的同类群组需要更改为。一旦更新运行并触发触发器,我所拥有的就是更新的队列,所以我不知道要更改哪条记录。

CREATE TRIGGER [dbo].[tr_SP_Cohort]
ON [dbo].StudentPrograms
AFTER UPDATE
AS     
     DECLARE @student VARCHAR(10);
     DECLARE @cohort INT;

     SELECT @student = i.student FROM inserted i
     SELECT @cohort = i.cohort FROM inserted i

    SET NOCOUNT ON;

    IF UPDATE(Cohort)
        UPDATE dbo.StudentPrograms
        SET Cohort = @cohort
        WHERE Student = @student AND Status = 2 AND Cohort = ???

不幸的是,由于很多原因,记录必须在此表中,而不是子表中。记录偶尔也会被删除/重新插入,所以如果我通过添加另一个带键的字段将它们绑定在一起,我会遇到同样的问题 - 如果该记录被删除/更新/重新插入,我仍然需要捕获信息,记录它,然后记录变化。

感谢您的即时帮助!这就是我最终得到的结果,稍作更改,因此它适用于批量更新。

ALTER TRIGGER [dbo].[tr_SP_Cohort]
ON [dbo].StudentPrograms
AFTER UPDATE
AS     
    SET NOCOUNT ON;

    IF UPDATE(Cohort)
        UPDATE a
        SET Cohort = i.Cohort
        FROM dbo.StudentPrograms AS a
        INNER JOIN inserted AS i ON a.Student = i.Student 
        INNER JOIN deleted AS d ON a.Cohort = d.Cohort 
         AND a.Student = d.Student 
        WHERE a.Status = 2

【问题讨论】:

尝试从已删除查询。更新时,原始记录被移动到删除中,新值存储在插入中。 完美!谢谢! 不客气。 另一个关于批量更新和触发器的堆栈溢出帖子 (***.com/questions/32324871/…) 【参考方案1】:

创建触发器时,可以使用已删除的表访问旧值

WHERE Student = @student AND Status = 2 AND Cohort = (SELECT TOP 1 Cohort from deleted)

【讨论】:

我已经很好地回答了你的问题,请将其标记为已回答,以便其他人知道它已解决。 SELECT Cohort from deleted LIMIT 1 是有效的 T-SQL 吗? OP 说它有效,但我认为你需要在 Sql Server 中使用SELECT TOP 1 Cohort from deleted【参考方案2】:

理想情况下,您应该在存储过程中处理此问题,但作为临时修复,您可以使用以下代码。

它们是您在代码中处理更新的方式,如果更新了不止一行,它将永远无法工作。

针对受该操作影响的所有行的触发操作(更新、删除、插入)触发一次触发器,而不是针对受触发操作影响的每一行。

记住这一切,您的临时解决方案应该类似于...

CREATE TRIGGER [dbo].[tr_SP_Cohort]
   ON [dbo].StudentPrograms
   AFTER UPDATE
AS     
BEGIN
   SET NOCOUNT ON;

    UPDATE s
    SET s.Cohort = i.Cohort
    FROM deleted d
    INNER JOIN dbo.StudentPrograms s  ON d.Student = s.Student
                                      AND d.Cohort = s.Cohort
    INNER JOIN inserted i             ON i.Student = s.Student
    WHERE s.[Status] = 2;

END

【讨论】:

以上是关于如何使用 SQL Server 更新触发器中的原始值更改第二条记录的主要内容,如果未能解决你的问题,请参考以下文章

如何:使用 SQL Server 2008 为自动更新修改日期创建触发器

当 SQL Server 表中的列“createdDate”从现在起经过 90 天后,如何更新其具有数百万行的列?我们可以使用触发器吗?

sql 检测更新触发器中修改的字段(sql server 2005)?

插入后使用 SQL Server 触发器更新另一个表中的列

更新触发器 SQL Server 2008

如何在 SQL Server 2008 上创建插入更新触发器