挿入されたテーブルと削除されたテーブルを使用する際の 1 つの注意点は、両方とも空になる可能性があることです。他に知っておくべきキャッチャーはありますか?たとえば、挿入されたテーブルには、新しいレコードと更新されたレコードを含めることができますか?
トリガー内のアクションを検出するために、このロジックに依存しています。
IF EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted) SET @operation = 'U'
IF EXISTS(SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted) SET @operation = 'I'
IF NOT EXISTS(SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted) SET @operation = 'D'
IF NOT EXISTS(SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted) SET @operation = 'X'
編集:
これが、監査証跡の問題に対する私の解決策です。挿入、偽の更新、実際の更新、および削除を行う 1 つの MERGE ステートメントでテストされています。
ALTER TRIGGER [dbo].[LogInsertEditDelete]
ON [dbo].[<TableToAudit>]
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--You will need to change @table to match the table to be audited
DECLARE @table VARCHAR(50)
SELECT @table = '<TableToAudit>'
-- date and user
DECLARE @updatedBy VARCHAR(50),
@timestamp DateTime
SELECT @updatedBy = SYSTEM_USER,
@timestamp = GETDATE()
-- Action, U = update, I = insert, D = delete
DECLARE @insertedCount int,
@deletedCount int
SET @insertedCount = (SELECT COUNT(*) FROM inserted)
SET @deletedCount = (SELECT COUNT(*) FROM deleted)
-- handle no action
IF @insertedCount = 0 AND @deletedCount = 0 RETURN
-- handle update
IF @insertedCount <> 0 AND @deletedCount <> 0
BEGIN
INSERT Audit (Type, TableName, UpdateDate, UpdatedBy, PK1)
SELECT
'U',
@table,
@timestamp,
@updatedBy,
CONVERT(VARCHAR(255), i.Id)
FROM
(SELECT Id, BINARY_CHECKSUM(*) Version FROM inserted) i
INNER JOIN
(SELECT Id, BINARY_CHECKSUM(*) Version FROM deleted) d
ON i.Id = d.Id
WHERE
i.Version <> d.Version
RETURN
END
-- handle deletes and inserts
INSERT Audit (Type, TableName, UpdateDate, UpdatedBy, PK1)
SELECT
CASE
WHEN i.Id IS NOT NULL AND d.Id IS NULL THEN 'I'
WHEN i.Id IS NULL AND d.Id IS NOT NULL THEN 'D'
END,
@table,
@timestamp,
@updatedBy,
CONVERT(VARCHAR(255), COALESCE(i.Id, d.Id))
FROM inserted i
FULL OUTER JOIN
deleted d
ON i.Id = d.Id
WHERE i.Id IS NULL OR
d.Id IS NULL
END
テーブルごとに主キーを指定する必要があるため、このソリューションは一般的なものではありません。