SQL Server:在未更改数据时捕获插入更新和删除的触发器?

SHR*_*SHR 6 trigger sql-server

我已将一个简单的表添加到名为: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)
Run Code Online (Sandbox Code Playgroud)

id 列仅用于保持顺序的方式。

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
Run Code Online (Sandbox Code Playgroud)

没有其他人更新aaa_log表,只是这些触发器,但是当我检查 aaa_log表时,我看到一些op为 NULL 的行。

我能想到的唯一选择是插入和更新都是空的,那么触发器是如何被激活的?

有什么解释吗?

Aar*_*and 8

您依赖于其中一个inserteddeleted(或两者)中行的存在。当没有行受到影响时会发生什么?触发器仍然会触发。

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
Run Code Online (Sandbox Code Playgroud)

为了避免这种事情,人们通常会从以下内容开始触发:

IF     NOT EXISTS (SELECT 1 FROM inserted) 
   AND NOT EXISTS (SELECT 1 FROM deleted)
BEGIN
  RETURN;
END
Run Code Online (Sandbox Code Playgroud)

检查@@ROWCOUNT也很流行,但我发现它要脆弱得多。

  • 正确的。每当针对表发生覆盖的 DML 操作时,触发器都会触发,无论受影响的行数如何,即使受影响的行数为零。 (4认同)