【问题标题】:how to use conditional trigger in sql server for update如何在sql server中使用条件触发器进行更新
【发布时间】:2017-07-07 10:23:00
【问题描述】:

我有一张这样的桌子:

---------------table1--------------------------------------------
    id    |   name  | lname   |   displayStatus   | delStatus
    1         a         b               1              0
    2         aa        bb              0              0
    3         aaa       bbb             1              0
    4         aaaa      bbbb            0              1

---------------tbl_LOG--------------------------------------------
    id    |   rowData| actType

我有这个更新触发器:

alter trigger tgr_delete
on table1
after update
as
begin
    declare @rowData nvarchar(max), @username nvarchar(50)

    if update(delStatus)
    begin
        if((select delStatus from inserted) = 1)
        begin
            set @rowData = (select CAST((CAST(id as nvarchar(12)) + ' | ' + name) as nvarchar(max)) from inserted)

            exec sp_insert_LOG 'table1', @rowData, 2
        end
        else if((select delStatus from inserted) = 0)
        begin
            set @rowData = (select CAST((CAST(id as nvarchar(12)) + ' | ' + name) as nvarchar(max)) from inserted)

            exec sp_insert_LOG 'table1', @rowData, 3
        end
    end
    else if update(displayStatus)
    begin
        if((delStatus = 0 or delStatus is null) and (select displayStatus from inserted) = 0)
        begin
            set @rowData = (select CAST((CAST(id as nvarchar(12)) + ' | ' + name) as nvarchar(max)) from inserted)

            exec sp_insert_LOG 'table1', @rowData, 4
        end
        else if((delStatus = 0 or delStatus is null) and (select displayStatus from inserted) = 1)
        begin
            set @rowData = (select CAST((CAST(id as nvarchar(12)) + ' | ' + name) as nvarchar(max)) from inserted)

            exec sp_insert_LOG 'table1', @rowData, 5
        end
    end
end

我有 3 个存储过程

  • 首先是更新delStatus
  • 第二个是更新显示状态
  • 第三个是更新所有列

现在我应该怎么做才能避免干扰前两个条件。

【问题讨论】:

  • 只是检查我是否理解这个问题 - 您希望触发器仅在 delStatusdisplayStatus 更改时才起作用,但如果它们一起更改或任何其他列也更改则不会?
  • 是的。我想要这个。
  • sql 中的触发器按语句工作,而不是按行工作。如果您曾经在 table1 上运行多行更新语句,它将失败。可以通过使用主键上的内部连接比较删除和插入之间的值来检查哪些列已更改(在这种情况下假设为 id)。

标签: sql sql-server triggers sql-server-2016


【解决方案1】:

这不是一个完整的答案,因为我不知道 sp_insert_LOG 做了什么,但它应该能让你朝着正确的方向开始:

CREATE TRIGGER trg_Table1_Update ON Table1
FOR UPDATE
AS


DECLARE @LogData AS TABLE
(
    TableName sysname,
    RowData nvarchar(max),
    ActionType int
)

INSERT INTO @LogData (TableName, RowData, ActionType)
SELECT 'Table1', 
       CAST((CAST(id as nvarchar(12)) + ' | ' + name) as nvarchar(max)),
       CASE WHEN i.delStatus = 1 THEN 2
            WHEN i.delStatus = 0 THEN 3
            WHEN ISNULL(i.delStatus, 0) = 0 AND i.displayStatus = 0 THEN 4
            WHEN ISNULL(i.delStatus, 0) = 0 AND i.displayStatus = 1 THEN 5
       END
FROM INSERTED i 
INNER JOIN Deleted d ON i.Id = d.Id
WHERE (i.name = d.name OR i.name IS NULL and d.name IS NULL)
AND (i.lname = d.lname OR i.lname IS NULL and d.lname IS NULL)
AND
(
(
    ISNULL(i.delStatus, 0) <> ISNULL(d.delStatus, 0)
    AND ISNULL(i.displayStatus, 0) = ISNULL(d.displayStatus, 0)
)
OR 
(
    ISNULL(i.delStatus, 0) = ISNULL(d.delStatus, 0)
    AND ISNULL(i.displayStatus, 0) <> ISNULL(d.displayStatus, 0)
)
)

此时,@LogData 表包含您要发送到sp_insert_LOG 的任何数据。我建议创建一个新的存储过程,例如sp_insert_log,它将接受一个表值参数并处理这些数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    相关资源
    最近更新 更多