web-dev-qa-db-ja.com

SQL Server:データが変更されていないときに挿入更新と削除のトリガーがキャッチされましたか?

次の名前のシンプルなテーブルをdbに追加しました:aaa_logという列:(idnameop))

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であるため、トリガーはどのようにアクティブ化されたのですか?

何か説明は?

6
SHR

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も人気ですが、私ははるかに壊れやすいと思います。

8
Aaron Bertrand

質問:変更が加えられていない場合、データベースに対して何らかのアクションを実行する必要がありますか?これはアプリケーションを不必要に遅くするようで、ベストプラクティスではありません。

ここでは、可能な限り、不要なデータベーストランザクションを削除することをお勧めします。

このトリガーが何らかの方法で監査することを意図している場合(それはそうであるように見えます)、@ Aaron Bertrandの回答は監査テーブルへの更新をログに記録しません。

2
Devon Di Vito