Me gustan las soluciones que son "elegantes en informática". Mi solución aquí golpea los pseudotables [insertado] y [eliminado] una vez cada uno para obtener sus estados y coloca el resultado en una variable mapeada de bits. Luego, cada combinación posible de INSERTAR, ACTUALIZAR y ELIMINAR se puede probar fácilmente a lo largo del disparador con evaluaciones binarias eficientes (excepto la improbable combinación INSERTAR o ELIMINAR).
Asume que no importa cuál sea la instrucción DML si no se modificaron las filas (lo que debería satisfacer la gran mayoría de los casos). Entonces, aunque no es tan completa como la solución de Roman Pekar, es más eficiente.
Con este enfoque, tenemos la posibilidad de un disparador "PARA INSERTAR, ACTUALIZAR, BORRAR" por tabla, lo que nos da A) control completo sobre el orden de acción yb) una implementación de código por acción aplicable a múltiples acciones. (Obviamente, cada modelo de implementación tiene sus pros y sus contras; deberá evaluar sus sistemas individualmente para determinar qué es lo que realmente funciona mejor).
Tenga en cuenta que las declaraciones "existe (seleccione * de« insertado / eliminado »)" son muy eficientes ya que no hay acceso al disco ( 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