用于填充审核的基本 T-SQL 触发器 table

Basic T-SQL trigger to populate an audit table

阅读 this page 我已经构建了几个 table 和一个触发器。这个想法是,当在第一个 table Matt 上执行 INSERTUPDATEDELETE 时,操作的数据将被插入到第二个审计中, table MattAudit.

触发器一定是失败了,我不知道为什么;证据是在审计 table 中没有输入任何条目,尽管 CREATE TRIGGER 和随后的 ALTER TRIGGER 语句成功完成。

主要tableMatt:

CREATE TABLE [dbo].[Matt](
    [MattID] [int] IDENTITY(1,1) NOT NULL,
    [Text] [nchar](10) NULL,
 CONSTRAINT [PK_Matt] PRIMARY KEY CLUSTERED 
(
    [MattID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

审计tableMattAudit:

CREATE TABLE [dbo].[MattAudit](
    [MattAuditID] [int] IDENTITY(1,1) NOT NULL,
    [MattID] [int] NOT NULL,
    [Text] [nchar](10) NULL,
    [Action] [int] NOT NULL,
    [InsertedDate] [datetime] NOT NULL,
 CONSTRAINT [PK_MattAudit] PRIMARY KEY CLUSTERED 
(
    [MattAuditID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

对马特的触发:

ALTER TRIGGER TrgMattAudit ON Matt
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;

    INSERT INTO [dbo].[MattAudit]
        ( MattID, [Text], [Action], InsertedDate )
    SELECT
        ISNULL(i.MattID, d.MattID) as MattID,
        ISNULL(i.Text, d.Text) as Text,
        CASE ISNULL(i.MattID,0) WHEN 0 THEN 0 ELSE 1 END
        +
        CASE ISNULL(d.MattID,0) WHEN 0 THEN 0 ELSE -1 END
        as [Action],
        GETDATE() as InsertedDate
    FROM
        inserted i
        INNER JOIN deleted d ON i.MattID = d.MattID;

END

下面的插入语句将插入行到 Matt table 但没有出现在 MattAudit table.

INSERT INTO Matt ([Text]) VALUES ('Test4')

我在触发器中遗漏或弄错了什么?

我认为问题是因为:

FROM
    inserted i
    INNER JOIN deleted d ON i.MattID = d.MattID;
  • 插入时您只有 INSERTED.
  • 中的记录
  • 当您删除记录时,您只有 DELETED.
  • 中的记录
  • 当您更新记录时,您将同时拥有 INSERTED(新值)和 DELETED(旧值)的记录。

合并两者将始终导致 INSERTDELETE 的 0 行,因为在执行 INSERT 时,您将在 INSERTED 中有 1 行或更多行,但在DELETEDDELETE 语句反之亦然。

我要提出的一个建议是将单个触发器拆分为针对每种情况的触发器(INSERTUPDATEDELETE),并在您的每种情况下都有一个查询新触发器。

一个小警告是 AFTER UPDATE 触发器将在 INSERTEDDELETED table 中添加行。

INSERTED 中的值将是放置的值,DELETED 中的值将是 UPDATE 查询之前的旧值 运行。

我认为你在那里做的错误是在插入表和删除表之间进行内部连接。两个表中的 MattId 永远不应该相同。我的意思是,你应该像左或右那样做外连接(或者在 2 个不同的选择中加载变量而不是做 1 个)。试试看,希望你能理解我!