以下は、SQL データベースのテーブル用に作成したトリガーです (SQL Server 2008 を実行しています)。更新、挿入、および削除を一括で行うため、このトリガーと「ストレージ」テーブル (TransactionLog) を作成して、すべてのアクティビティをキャプチャします。これまでのところ、このトリガーは挿入と更新に対して完全に機能します。すべてのレコードは、すべての適切な値とともに「ストレージ」テーブルに配置されます。
ただし、複数のレコードを削除しようとすると問題が発生します。このトリガーがキャプチャして「ストレージ」テーブルに送信する唯一のレコードは、最後に削除されたレコードです。他のすべては失われます。
CREATE TRIGGER [dbo].[trg_Agent_ALL]
ON [dbo].[Agent]
FOR INSERT, UPDATE, DELETE
AS
BEGIN
--TransactionLog variables
DECLARE @tableName char(25) = 'Agent'
DECLARE @transDate datetime
DECLARE @lastChangeOperator char(6)
DECLARE @tableString char(255)
DECLARE @action char(1) = 'I'
DECLARE @userId char(25)
--Trigger table variables
DECLARE @sNumber char(10)
DECLARE @controlId char(3)
DECLARE @entityType char(1)
DECLARE @firstName nvarchar(50)
DECLARE @lastName nvarchar(50)
DECLARE @suffix nvarchar(10)
DECLARE @corpName nvarchar(100)
IF EXISTS (SELECT * FROM deleted)
BEGIN
SET @action =
CASE
WHEN EXISTS (SELECT * FROM inserted) THEN 'U'
ELSE 'D'
END
END
IF @action = 'D'
BEGIN
SELECT @sNumber = sNumber, @lastChangeOperator = LastChangeOperator, @transDate = LastChangeDate, @entityType = EntityType,
@firstName = FirstName, @lastName = LastName, @suffix = NameSuffix, @corpName = CorporateName, @controlId = ControlId
FROM deleted
IF @firstName IS NULL SET @firstName = 'NULL'
IF @lastName IS NULL SET @lastName = 'NULL'
IF @suffix IS NULL SET @suffix = 'NULL'
IF @corpName IS NULL SET @corpName = 'NULL'
IF @controlId IS NULL SET @controlId = 'NULL'
SET @tableString = 'sNum:' + @sNumber + ' ' + 'EntType:' + @entityType + ' ' + 'Fname:' + @firstName + ' ' + 'Lname:' + @lastname + ' ' + 'suf:' + @suffix +
' ' + 'crpName:' + @corpName + ' ' + 'crlId:' + @controlId
END
ELSE
BEGIN
SELECT @sNumber = SymetraNumber, @lastChangeOperator = LastChangeOperator, @transDate = LastChangeDate, @entityType = EntityType,
@firstName = FirstName, @lastName = LastName, @suffix = NameSuffix, @corpName = CorporateName, @controlId = ControlId
FROM inserted
IF @firstName IS NULL SET @firstName = 'NULL'
IF @lastName IS NULL SET @lastName = 'NULL'
IF @suffix IS NULL SET @suffix = 'NULL'
IF @corpName IS NULL SET @corpName = 'NULL'
IF @controlId IS NULL SET @controlId = 'NULL'
SET @tableString = 'sNum:' + @sNumber + ' ' + 'EntType:' + @entityType + ' ' + 'Fname:' + @firstName + ' ' + 'Lname:' + @lastname + ' ' + 'suf:' + @suffix +
' ' + 'crpName:' + @corpName + 'crlId:' + @controlId
END
INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
VALUES (@transDate, 'Op', @tableName, @action, @tableString, @lastChangeOperator)
END
以下のコメントに基づいて、削除セクションの SQL コードを変更しました。ハードコーディングされた値は機能しているように見えますが、それらを表示するためだけにそれらを配置した主な理由は、それらの特定の列に必要な値です。上記のコードでこれらの値を設定した変数があります (DECLARE ステートメントを参照してください)。ただし、これにより、次のエラーメッセージが表示されます。
Conversion failed when converting the varchar value 'P' to data type int.
このエラーは、内部の SELECT ステートメントの EntityType 属性から発生しています。私を混乱させるのは、この列のデータ型が char(1) に設定されており、TableString 列 (連結された値の宛先) のデータ型が nvarchar(255) であることです。「int」がどこから来ているのかわかりません...
IF @action = 'D'
BEGIN
INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
SELECT LastChangeDate, 'Op', 'Agent', 'D',
(SELECT CAST(CAST(sNumber as nvarchar) + ' ' + EntityType + ' ' + ISNULL(FirstName, ' ') + ' ' + ISNULL(LastName, ' ') + ' ' + ISNULL(NameSuffix, ' ') + ' ' +
ISNULL(CorporateName, ' ' ) + ' ' + ISNULL(CAST(ControlId as nvarchar), ' ') AS nvarchar) as TableString
FROM deleted), LastChangeOperator
FROM deleted
END
ELSE
編集
sNumber フィールドと controlId フィールドを nvarchar にキャストすることで、以前のエラー メッセージを回避することができました。ただし、現在、以下に投稿された別のエラー メッセージが表示されます。
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
最終編集
このようにサブクエリを変更すると、一度に 1 つのレコードしか要求していなかったので、削除された複数のレコードを Audit テーブルに返すことができました。
IF @action = 'D'
BEGIN
INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
SELECT LastChangeDate, 'Op', 'Agent', 'D',
CAST('SymNum:' + CAST(SymetraNumber as nvarchar(30)) + ' entType:' + EntityType + ' Fname:' + ISNULL(FirstName, 'NULL') + ' Lname:' + ISNULL(LastName, 'NULL') +
' suff:' + ISNULL(NameSuffix, 'NULL') + ' corpName:' + ISNULL(CorporateName, 'NULL' ) + ' ctrlId:' + ISNULL(CAST(ControlId as nvarchar(30)), 'NULL') AS nvarchar(30)) as TableString
, LastChangeOperator
FROM deleted
END
ELSE