次の名前のシンプルなテーブルをdbに追加しました:aaa_logという列:(id
、name
、op
))
CREATE TABLE aaa_log (
[id] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[name] [varchar](50) NOT NULL,
[op] [varchar](50) NULL)
id
列は、順序を維持するために使用されます。
次のスクリプトを使用して、db内の他のすべてのテーブルにトリガー(for insert, update, delete
)を追加しました。
declare @cmd varchar(max)
declare trigger_create cursor for
select 'Create trigger ['+TABLE_SCHEMA+'].[xxtr_'+TABLE_NAME+'_auto]
on ['+TABLE_SCHEMA+'].['+TABLE_NAME+'] fro insert,update,delete as
BEGIN
declare @op varchar(20)
if exists(SELECT * from inserted) and exists(SELECT * from deleted)
begin
set @op = ''update''
end
if exists(SELECT * from inserted) and not exists(SELECT * from deleted)
begin
set @op = ''insert''
end
if not exists(SELECT * from inserted) and exists(SELECT * from deleted)
begin
set @op = ''delete''
end
insert into aaa_log([name],[op]) values('+TABLE_SCHEMA+'.'+TABLE_NAME+', @op)
END
'
from information_schema.tables
where table_type='BASE TABLE' AND table_name <> 'aaa_log'
open trigger_create
fetch next from trigger_create into @sql
while @@FETCH_STATUS =0
BEGIN
exec(@sql)
fetch next from trigger_create into @sql
END
close trigger_create
deallocate trigger_create
他の誰もaaa_log
テーブルを更新せず、これらのトリガーのみを更新しますが、aaa_log
テーブルを確認すると、op
がNULLである行がいくつかあります。
私が考えることができる唯一のオプションは、挿入と更新の両方がnullであるため、トリガーはどのようにアクティブ化されたのですか?
何か説明は?
inserted
またはdeleted
(またはその両方)の行の存在に依存しています。影響を受ける行がない場合はどうなりますか?トリガーはまだ作動します。
CREATE TABLE dbo.floob(a int);
INSERT dbo.floob(a) VALUES(1);
GO
CREATE TRIGGER dbo.TRfloob
ON dbo.floob
FOR INSERT, UPDATE, DELETE
AS
BEGIN
IF NOT EXISTS (SELECT 1 FROM inserted)
AND NOT EXISTS (SELECT 1 FROM deleted)
BEGIN
PRINT 'Strange, unknown operation!';
END
END
GO
UPDATE dbo.floob SET a = 2 WHERE a = 2;
GO
この種のことを避けるために、通常、人々は次のようなものからトリガーを開始します:
IF NOT EXISTS (SELECT 1 FROM inserted)
AND NOT EXISTS (SELECT 1 FROM deleted)
BEGIN
RETURN;
END
チェック@@ROWCOUNT
も人気ですが、私ははるかに壊れやすいと思います。
質問:変更が加えられていない場合、データベースに対して何らかのアクションを実行する必要がありますか?これはアプリケーションを不必要に遅くするようで、ベストプラクティスではありません。
ここでは、可能な限り、不要なデータベーストランザクションを削除することをお勧めします。
このトリガーが何らかの方法で監査することを意図している場合(それはそうであるように見えます)、@ Aaron Bertrandの回答は監査テーブルへの更新をログに記録しません。