为什么 FOR/AFTER DELETE 触发器中删除的 table 不包含已删除记录的数据?
Why doesn't the deleted table in a FOR/AFTER DELETE Trigger contain data of the Deleted Record?
鉴于以下审核table:
CREATE TABLE Auditing.[Record Deletion Times]
(
ID BIGINT IDENTITY NOT NULL,
[Schema] NVARCHAR(128) NOT NULL,
[Table] NVARCHAR(256) NOT NULL,
[Record ID] INT NOT NULL,
[Date-Time] DATETIME2 NOT NULL,
[Record Information] NVARCHAR(1024) NULL,
CONSTRAINT [Record Deleted Times Primary Key] PRIMARY KEY CLUSTERED
(
ID ASC
),
CONSTRAINT [Record Deleted Modified Times Unique Key] UNIQUE NONCLUSTERED
(
[Schema] ASC,
[Table] ASC,
[Record ID] ASC,
[Date-Time] ASC
)
)
和以下数据table:
CREATE TABLE [dbo].[Items]
(
[ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[Key] [varchar](50) NOT NULL,
[Value] [varchar](255) NOT NULL
)
我想要一个触发器,当它从 Items
中删除时,它将记录信息到 Record Deletion Times
。我发现我可以使用 INSTEAD OF
触发器来做到这一点(我记录数据然后手动删除触发器中的记录)但想知道为什么 FOR
或 AFTER
触发器不需要我自己执行删除就不会做同样的事情。我的猜测是 deleted
不包含有关删除记录后删除的任何数据(调试触发器的最佳方法是什么?)。
这是我希望使用的触发器,它未能在 Record Deletion Times
中记录任何内容:
CREATE TRIGGER [Items Deleted]
ON Items
FOR DELETE
AS
INSERT INTO Auditing.[Record Deletion Times]
SELECT
'dbo',
'Items',
deleted.ID,
GETUTCDATE(),
CONCAT
(
'Key: ''',
Items.Key,
''' Value: ''',
Items.Value,
''''
)
FROM Items
JOIN deleted ON deleted.ID = Items.ID
这是我最终使用的触发器:
CREATE TRIGGER [Items Deleted]
ON Items
INSTEAD OF DELETE
AS
BEGIN
INSERT INTO Auditing.[Record Deletion Times]
SELECT
'dbo',
'Items',
deleted.ID,
GETUTCDATE(),
CONCAT
(
'Key: ''',
Items.Key,
''' Value: ''',
Items.Value,
''''
)
FROM Items
JOIN deleted ON deleted.ID = Items.ID
DELETE Items
FROM Items
JOIN deleted ON deleted.ID = Items.ID
END
你不应该 selecting 来自 你的 Items
table 因为你想要的行现在已被删除。
刚刚 select 来自 Deleted
即
INSERT INTO RecordDeletionTimes
SELECT
'dbo',
'Items',
ID,
GETUTCDATE(),
CONCAT
(
'Key: ''',
[Key],
''' Value: ''',
Value,
''''
)
FROM deleted ;
调试触发器的最佳方法是 select * from deleted
并使用 begin tran/rollback.
在 SSMS 中进行测试
鉴于以下审核table:
CREATE TABLE Auditing.[Record Deletion Times]
(
ID BIGINT IDENTITY NOT NULL,
[Schema] NVARCHAR(128) NOT NULL,
[Table] NVARCHAR(256) NOT NULL,
[Record ID] INT NOT NULL,
[Date-Time] DATETIME2 NOT NULL,
[Record Information] NVARCHAR(1024) NULL,
CONSTRAINT [Record Deleted Times Primary Key] PRIMARY KEY CLUSTERED
(
ID ASC
),
CONSTRAINT [Record Deleted Modified Times Unique Key] UNIQUE NONCLUSTERED
(
[Schema] ASC,
[Table] ASC,
[Record ID] ASC,
[Date-Time] ASC
)
)
和以下数据table:
CREATE TABLE [dbo].[Items]
(
[ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[Key] [varchar](50) NOT NULL,
[Value] [varchar](255) NOT NULL
)
我想要一个触发器,当它从 Items
中删除时,它将记录信息到 Record Deletion Times
。我发现我可以使用 INSTEAD OF
触发器来做到这一点(我记录数据然后手动删除触发器中的记录)但想知道为什么 FOR
或 AFTER
触发器不需要我自己执行删除就不会做同样的事情。我的猜测是 deleted
不包含有关删除记录后删除的任何数据(调试触发器的最佳方法是什么?)。
这是我希望使用的触发器,它未能在 Record Deletion Times
中记录任何内容:
CREATE TRIGGER [Items Deleted]
ON Items
FOR DELETE
AS
INSERT INTO Auditing.[Record Deletion Times]
SELECT
'dbo',
'Items',
deleted.ID,
GETUTCDATE(),
CONCAT
(
'Key: ''',
Items.Key,
''' Value: ''',
Items.Value,
''''
)
FROM Items
JOIN deleted ON deleted.ID = Items.ID
这是我最终使用的触发器:
CREATE TRIGGER [Items Deleted]
ON Items
INSTEAD OF DELETE
AS
BEGIN
INSERT INTO Auditing.[Record Deletion Times]
SELECT
'dbo',
'Items',
deleted.ID,
GETUTCDATE(),
CONCAT
(
'Key: ''',
Items.Key,
''' Value: ''',
Items.Value,
''''
)
FROM Items
JOIN deleted ON deleted.ID = Items.ID
DELETE Items
FROM Items
JOIN deleted ON deleted.ID = Items.ID
END
你不应该 selecting 来自 你的 Items
table 因为你想要的行现在已被删除。
刚刚 select 来自 Deleted
即
INSERT INTO RecordDeletionTimes
SELECT
'dbo',
'Items',
ID,
GETUTCDATE(),
CONCAT
(
'Key: ''',
[Key],
''' Value: ''',
Value,
''''
)
FROM deleted ;
调试触发器的最佳方法是 select * from deleted
并使用 begin tran/rollback.