基本的T-SQL触发器来填充审核表

时间:2019-09-05 11:09:40

标签: tsql database-trigger audit-tables

已阅读this page,我已经建立了几个表和一个触发器。这个想法是,当在第一个表INSERT上执行UPDATEDELETEMatt时,所操作的数据将被插入第二个审计表{{ 1}}。

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

主表ALTER TRIGGER

Matt

审核表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]

MattAudit

在Matt上触发:

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]

以下insert语句会将行插入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表中什么也没有出现。

MattAudit

触发器中我缺少什么或出错了?

2 个答案:

答案 0 :(得分:2)

我认为问题是因为这样的:

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

将两者结合在一起将始终为INSERTDELETE产生0行,因为进行INSERT时,INSERTED中将有1行或更多行,而{{ 1}}。反之亦然,DELETED语句。

我的建议是将单个触发器分为每种情况(DELETEINSERTUPDATE)的触发器,并在每个新触发器中都有一个查询

一个小警告是DELETE触发器将在AFTER UPDATEINSERTED表中添加行。

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

答案 1 :(得分:0)

我认为您正在执行的错误是在插入和删除的表之间进行内部联接。 2表中的MattId决不能相同。我的意思是,您应该像左或右进行外部联接(或在2个不同的选择中加载变量,而不是执行1个)。试试看,希望您理解我!