用于填充审核的基本 T-SQL 触发器 table
Basic T-SQL trigger to populate an audit table
阅读 this page 我已经构建了几个 table 和一个触发器。这个想法是,当在第一个 table Matt
上执行 INSERT
、UPDATE
或 DELETE
时,操作的数据将被插入到第二个审计中, 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
(旧值)的记录。
合并两者将始终导致 INSERT
或 DELETE
的 0 行,因为在执行 INSERT 时,您将在 INSERTED
中有 1 行或更多行,但在DELETED
。 DELETE
语句反之亦然。
我要提出的一个建议是将单个触发器拆分为针对每种情况的触发器(INSERT
、UPDATE
和 DELETE
),并在您的每种情况下都有一个查询新触发器。
一个小警告是 AFTER UPDATE
触发器将在 INSERTED
和 DELETED
table 中添加行。
INSERTED
中的值将是放置的值,DELETED
中的值将是 UPDATE 查询之前的旧值 运行。
我认为你在那里做的错误是在插入表和删除表之间进行内部连接。两个表中的 MattId 永远不应该相同。我的意思是,你应该像左或右那样做外连接(或者在 2 个不同的选择中加载变量而不是做 1 个)。试试看,希望你能理解我!
阅读 this page 我已经构建了几个 table 和一个触发器。这个想法是,当在第一个 table Matt
上执行 INSERT
、UPDATE
或 DELETE
时,操作的数据将被插入到第二个审计中, 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
(旧值)的记录。
合并两者将始终导致 INSERT
或 DELETE
的 0 行,因为在执行 INSERT 时,您将在 INSERTED
中有 1 行或更多行,但在DELETED
。 DELETE
语句反之亦然。
我要提出的一个建议是将单个触发器拆分为针对每种情况的触发器(INSERT
、UPDATE
和 DELETE
),并在您的每种情况下都有一个查询新触发器。
一个小警告是 AFTER UPDATE
触发器将在 INSERTED
和 DELETED
table 中添加行。
INSERTED
中的值将是放置的值,DELETED
中的值将是 UPDATE 查询之前的旧值 运行。
我认为你在那里做的错误是在插入表和删除表之间进行内部连接。两个表中的 MattId 永远不应该相同。我的意思是,你应该像左或右那样做外连接(或者在 2 个不同的选择中加载变量而不是做 1 个)。试试看,希望你能理解我!