J'aime les solutions «élégantes en informatique». Ma solution ici frappe les pseudotables [inséré] et [supprimé] une fois chacun pour obtenir leurs statuts et place le résultat dans une variable mappée. Ensuite, chaque combinaison possible de INSERT, UPDATE et DELETE peut facilement être testée tout au long du déclencheur avec des évaluations binaires efficaces (sauf pour la combinaison improbable INSERT ou DELETE).
Il suppose que peu importe ce qu'était l'instruction DML si aucune ligne n'était modifiée (ce qui devrait satisfaire la grande majorité des cas). Ainsi, même si elle n'est pas aussi complète que la solution de Roman Pekar, elle est plus efficace.
Avec cette approche, nous avons la possibilité d'un déclencheur "FOR INSERT, UPDATE, DELETE" par table, ce qui nous donne A) un contrôle complet sur l'ordre des actions et b) une implémentation de code par action multi-action applicable. (Évidemment, chaque modèle de mise en œuvre a ses avantages et ses inconvénients; vous devrez évaluer vos systèmes individuellement pour déterminer ce qui fonctionne vraiment le mieux.)
Notez que les instructions «existe (sélectionnez * à partir de« inséré / supprimé »)» sont très efficaces car il n'y a pas d'accès disque ( https://social.msdn.microsoft.com/Forums/en-US/01744422-23fe-42f6 -9ab0-a255cdf2904a ).
use tempdb
;
create table dbo.TrigAction (asdf int)
;
GO
create trigger dbo.TrigActionTrig
on dbo.TrigAction
for INSERT, UPDATE, DELETE
as
declare @Action tinyint
;
-- Create bit map in @Action using bitwise OR "|"
set @Action = (-- 1: INSERT, 2: DELETE, 3: UPDATE, 0: No Rows Modified
(select case when exists (select * from inserted) then 1 else 0 end)
| (select case when exists (select * from deleted ) then 2 else 0 end))
;
-- 21 <- Binary bit values
-- 00 -> No Rows Modified
-- 01 -> INSERT -- INSERT and UPDATE have the 1 bit set
-- 11 -> UPDATE <
-- 10 -> DELETE -- DELETE and UPDATE have the 2 bit set
raiserror(N'@Action = %d', 10, 1, @Action) with nowait
;
if (@Action = 0) raiserror(N'No Data Modified.', 10, 1) with nowait
;
-- do things for INSERT only
if (@Action = 1) raiserror(N'Only for INSERT.', 10, 1) with nowait
;
-- do things for UPDATE only
if (@Action = 3) raiserror(N'Only for UPDATE.', 10, 1) with nowait
;
-- do things for DELETE only
if (@Action = 2) raiserror(N'Only for DELETE.', 10, 1) with nowait
;
-- do things for INSERT or UPDATE
if (@Action & 1 = 1) raiserror(N'For INSERT or UPDATE.', 10, 1) with nowait
;
-- do things for UPDATE or DELETE
if (@Action & 2 = 2) raiserror(N'For UPDATE or DELETE.', 10, 1) with nowait
;
-- do things for INSERT or DELETE (unlikely)
if (@Action in (1,2)) raiserror(N'For INSERT or DELETE.', 10, 1) with nowait
-- if already "return" on @Action = 0, then use @Action < 3 for INSERT or DELETE
;
GO
set nocount on;
raiserror(N'
INSERT 0...', 10, 1) with nowait;
insert dbo.TrigAction (asdf) select top 0 object_id from sys.objects;
raiserror(N'
INSERT 3...', 10, 1) with nowait;
insert dbo.TrigAction (asdf) select top 3 object_id from sys.objects;
raiserror(N'
UPDATE 0...', 10, 1) with nowait;
update t set asdf = asdf /1 from dbo.TrigAction t where asdf <> asdf;
raiserror(N'
UPDATE 3...', 10, 1) with nowait;
update t set asdf = asdf /1 from dbo.TrigAction t;
raiserror(N'
DELETE 0...', 10, 1) with nowait;
delete t from dbo.TrigAction t where asdf < 0;
raiserror(N'
DELETE 3...', 10, 1) with nowait;
delete t from dbo.TrigAction t;
GO
drop table dbo.TrigAction
;
GO