允许通过触发器更新列,但阻止直接更新同一列

时间:2018-06-10 21:07:33

标签: sql-server sql-server-2016

我有两个共享一些列的表:

Table1:
+----+----+----+
| A  | B  | C  |
+----+----+----+
| a1 | b1 | c1 |
| a2 | b2 | c2 |
| a3 | b3 | c3 |
+----+----+----+

Table2:
+----+----+----+----+
| E  | F  | A  | C  |
+----+----+----+----+
| e1 | f1 | a1 | c1 |
| e2 | f2 | a2 | c2 |
| e3 | f3 | a3 | c3 |
+----+----+----+----+

Table1上我有一个触发器,在A中更新Table2后更新Table1中的列Table2。但是我在A上有一个触发器会阻止直接更新Table2中的列Table2。只应在第一次触发时允许更新。我面临的问题是,即使我通过第一个触发器更新AFTER UPDATE AS IF UPDATE (IMEPREZIME) BEGIN SET NOCOUNT ON; UPDATE t2 SET A = i.A FROM DBO.Table2 t2 INNER JOIN inserted i on t2.C = i.C END ,第二个触发器也会触发。 有没有办法防止第二次触发器在第一次触发后完成更新后发生火灾?

触发器1:

AFTER UPDATE
AS 
IF UPDATE (A)
BEGIN
    SET NOCOUNT ON;
    IF UPDATE (A) and NOT EXISTS(SELECT A 
                from dbo.Table1 t1 
                where exists(select A 
                                from inserted i 
                                where t1.C= i.C ))
    BEGIN
        RAISERROR('DIRECT UPDATE OF COLUMN "A" IS FORBIDDEN', 16, -1)
        ROLLBACK TRAN
    END
END

触发2:

php artisan config:clear

1 个答案:

答案 0 :(得分:1)

在SQL Server 2016及更高版本中,您可以设置SESSION_CONTEXT值以使第二个触发器短路。

AFTER UPDATE AS 
   IF UPDATE (IMEPREZIME)
BEGIN
    SET NOCOUNT ON;
    EXEC sp_set_session_context @key = N'FiredFromTrigger1', @value = 1;
    UPDATE t2
    SET A = i.A
    FROM DBO.Table2 t2
    INNER JOIN inserted i on t2.C = i.C;
    EXEC sp_set_session_context @key = N'FiredFromTrigger1', @value = NULL;
END;


AFTER UPDATE
AS 
IF UPDATE (A)
BEGIN
    SET NOCOUNT ON;
    IF NOT CAST(SESSION_CONTEXT(N'FiredFromTrigger1') AS bit) = 1 AND UPDATE (A) and NOT EXISTS(SELECT A 
                from dbo.Table1 t1 
                where exists(select A 
                                from inserted i 
                                where t1.C= i.C ))
    BEGIN
        RAISERROR('DIRECT UPDATE OF COLUMN "A" IS FORBIDDEN', 16, -1);
        ROLLBACK TRAN;
    END;
END;