J'ai ajouté une table simple à une base de données appelée: aaa_log avec des colonnes: (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
colonne utilisée juste pour conserver l'ordre.
J'ai ajouté un déclencheur (for insert, update, delete
) à toutes les autres tables d'une base de données à l'aide du script suivant:
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
Personne d'autre ne met à jour le aaa_log
table, juste ces déclencheurs, mais quand je vérifie le aaa_log
table Je vois quelques lignes où op
est NULL.
La seule option à laquelle je peux penser est qu'inséré et mis à jour est nul, alors comment le déclencheur a-t-il été activé?
Une explication?
Vous comptez sur la présence de lignes dans inserted
ou deleted
(ou les deux). Que se passe-t-il lorsqu'aucune ligne n'est affectée? La détente se déclenche toujours.
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
Pour éviter ce genre de chose, les gens démarrent généralement leur déclencheur avec quelque chose comme:
IF NOT EXISTS (SELECT 1 FROM inserted)
AND NOT EXISTS (SELECT 1 FROM deleted)
BEGIN
RETURN;
END
Vérification @@ROWCOUNT
est populaire aussi, mais je le trouve beaucoup plus fragile.
Question: Devriez-vous prendre des mesures contre la base de données si aucune modification n'est apportée? Cela semble ralentir inutilement votre application et ce n'est pas la meilleure pratique.
Je dirais ici qu'une meilleure solution serait de supprimer les transactions de base de données inutiles, si possible.
Si ce déclencheur est destiné à auditer de quelque manière que ce soit (ce à quoi il ressemble), la réponse de @Aaron Bertrand n'enregistrera aucune mise à jour de la table d'audit.