2009-04-12 18 views
126

Necesito escribir un Insertar, Actualizar desencadenador en la tabla A que eliminará todas las filas de la tabla B cuya columna (por ejemplo, Desc) tiene valores como el valor insertado/actualizado en el columna de la tabla A (digamos Col1). ¿Cómo voy a redactarlo para poder manejar tanto los casos de actualización como de inserción? ¿Cómo puedo determinar si el disparador se ejecuta para una actualización o inserción?Insertar activación de la actualización cómo determinar si insertar o actualizar

Respuesta

136

Si se trata de MS SQL Server ...

causas no tienen especiales INSERTED y DELETED tablas para hacer un seguimiento "antes" y "después" de datos. Entonces puede usar algo como IF EXISTS (SELECT * FROM DELETED) para detectar una actualización. Solo tiene filas en DELETED en la actualización, pero siempre hay filas en INSERTED.

buscar "inserta" en CREATE TRIGGER

Edición 23 Nov 2011

Después del comentario, esta respuesta es sólo para INSERTED y UPDATED desencadenantes.
Obviamente, BORRAR disparadores no pueden tener "siempre filas en INSERTED" como he dicho anteriormente

10

Después de un montón de búsqueda no pude encontrar un ejemplo exacto de un solo disparador de SQL Server que se encarga de todos los (3) tres condiciones de las acciones desencadenantes INSERTAR, ACTUALIZAR y ELIMINAR. Finalmente encontré una línea de texto que hablaba del hecho de que cuando se produce un BORRADO o ACTUALIZACIÓN, la tabla eliminada común contendrá un registro para estas dos acciones. En función de esa información, creé una pequeña rutina de Acción que determina por qué se activó el activador. Este tipo de interfaz a veces se necesita cuando hay una configuración común y una acción específica en un disparador INSERTAR versus ACTUALIZAR. En estos casos, crear un disparador separado para la ACTUALIZACIÓN y el INSERT se convertiría en un problema de mantenimiento. (Es decir, eran los dos gatillos actualizados correctamente para el arreglo algoritmo de datos comunes necesarios?)

Con ese fin, me gustaría dar la siguiente múltiples desencadenantes código de evento fragmento para el manejo de INSERT, UPDATE, DELETE en un disparador para un Microsoft Servidor SQL.

CREATE TRIGGER [dbo].[INSUPDDEL_MyDataTable] 
ON [dbo].[MyDataTable] FOR INSERT, UPDATE, DELETE 
AS 

-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with caller queries SELECT statements. 
-- If an update/insert/delete occurs on the main table, the number of records affected 
-- should only be based on that table and not what records the triggers may/may not 
-- select. 
SET NOCOUNT ON; 

-- 
-- Variables Needed for this Trigger 
-- 
DECLARE @PACKLIST_ID varchar(15) 
DECLARE @LINE_NO smallint 
DECLARE @SHIPPED_QTY decimal(14,4) 
DECLARE @CUST_ORDER_ID varchar(15) 
-- 
-- Determine if this is an INSERT,UPDATE, or DELETE Action 
-- 
DECLARE @Action as char(1) 
DECLARE @Count as int 
SET @Action = 'I' -- Set Action to 'I'nsert by default. 
SELECT @Count = COUNT(*) FROM DELETED 
if @Count > 0 
    BEGIN 
     SET @Action = 'D' -- Set Action to 'D'eleted. 
     SELECT @Count = COUNT(*) FROM INSERTED 
     IF @Count > 0 
      SET @Action = 'U' -- Set Action to 'U'pdated. 
    END 

if @Action = 'D' 
    -- This is a DELETE Record Action 
    -- 
    BEGIN 
     SELECT @PACKLIST_ID =[PACKLIST_ID] 
        ,@LINE_NO = [LINE_NO] 
     FROM DELETED 

     DELETE [dbo].[MyDataTable] 
     WHERE [PACKLIST_ID][email protected]_ID AND [LINE_NO][email protected]_NO 
    END 
Else 
    BEGIN 
      -- 
      -- Table INSERTED is common to both the INSERT, UPDATE trigger 
      -- 
      SELECT @PACKLIST_ID =[PACKLIST_ID] 
       ,@LINE_NO = [LINE_NO] 
       ,@SHIPPED_QTY =[SHIPPED_QTY] 
       ,@CUST_ORDER_ID = [CUST_ORDER_ID] 
      FROM INSERTED 

     if @Action = 'I' 
      -- This is an Insert Record Action 
      -- 
      BEGIN 
       INSERT INTO [MyChildTable] 
        (([PACKLIST_ID] 
        ,[LINE_NO] 
        ,[STATUS] 
       VALUES 
        (@PACKLIST_ID 
        ,@LINE_NO 
        ,'New Record' 
        ) 
      END 
     else 
      -- This is an Update Record Action 
      -- 
      BEGIN 
       UPDATE [MyChildTable] 
        SET [PACKLIST_ID] = @PACKLIST_ID 
          ,[LINE_NO] = @LINE_NO 
          ,[STATUS]='Update Record' 
       WHERE [PACKLIST_ID][email protected]_ID AND [LINE_NO][email protected]_NO 
      END 
    END 
99
CREATE TRIGGER dbo.TableName_IUD 
ON dbo.TableName 
AFTER INSERT, UPDATE, DELETE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    -- 
    -- Check if this is an INSERT, UPDATE or DELETE Action. 
    -- 
    DECLARE @action as char(1); 

    SET @action = 'I'; -- Set Action to Insert by default. 
    IF EXISTS(SELECT * FROM DELETED) 
    BEGIN 
     SET @action = 
      CASE 
       WHEN EXISTS(SELECT * FROM INSERTED) THEN 'U' -- Set Action to Updated. 
       ELSE 'D' -- Set Action to Deleted.  
      END 
    END 
    ELSE 
     IF NOT EXISTS(SELECT * FROM INSERTED) RETURN; -- Nothing updated or inserted. 

    ... 

    END 
+0

+1 Esto es más eficiente que 'COUNT' –

+0

La manera más eficiente sería hacer" Seleccionar 1 de Insertado "... – ganders

+0

Me gusta escribir SELECCIONAR 1 DE INSERTADO también, ya que creo que señaliza la intención más claramente, pero los programadores de MSSQL me decepcionarían si esto ocurriera. hace alguna diferencia en este contexto ... –

2

Esto podría ser una manera más rápida:

DECLARE @action char(1) 

IF COLUMNS_UPDATED() > 0 -- insert or update 
BEGIN 
    IF EXISTS (SELECT * FROM DELETED) -- update 
     SET @action = 'U' 
    ELSE 
     SET @action = 'I' 
    END 
ELSE -- delete 
    SET @action = 'D' 
+3

De esta manera no funciona para tablas con un gran número de columnas, ya que columns_updated() devuelve un varbinary que es enorme. Por lo tanto, el "> 0" falla porque el valor predeterminado 0 es un número almacenado internamente mucho más pequeño que el valor devuelto por columns_updated() – Graham

3

Un problema potencial con las dos soluciones que ofrece es que, dependiendo de la forma en que se escriben, una consulta de actualización puede actualizar cero registros y una consulta de inserción puede insertar cero registros. En estos casos, los conjuntos de registros insertados y eliminados estarán vacíos. En muchos casos, si los conjuntos de registros insertados y eliminados están vacíos, es posible que desee salir del activador sin hacer nada.

2

me pareció que un pequeño error en Graham solución fría de otro modo:

Debe ser SI COLUMNS_UPDATED() <> 0 - insertar o actualizar
en lugar de> 0 probablemente porque la parte superior poco consigue interpretarse como signo FIRMADO, bit de signo entero ... (?). Así que en total:

DECLARE @action CHAR(8) 
IF COLUMNS_UPDATED() <> 0 -- delete or update? 
BEGIN  
    IF EXISTS (SELECT * FROM deleted) -- updated cols + old rows means action=update  
    SET @action = 'UPDATE'  
    ELSE 
    SET @action = 'INSERT' -- updated columns and nothing deleted means action=insert 
END 
ELSE -- delete  
BEGIN 
    SET @action = 'DELETE' 
END 
62

Muchas de estas sugerencias no tienen en cuenta si se ejecuta una instrucción de eliminación que elimina nada.
Digamos que intentas eliminar donde una ID es igual a algún valor que no existe en la tabla.
Todavía se llama su activador, pero no hay nada en las tablas Eliminado o Insertado.

uso que esto sea segura:

--Determine if this is an INSERT,UPDATE, or DELETE Action or a "failed delete". 
DECLARE @Action as char(1); 
    SET @Action = (CASE WHEN EXISTS(SELECT * FROM INSERTED) 
         AND EXISTS(SELECT * FROM DELETED) 
         THEN 'U' -- Set Action to Updated. 
         WHEN EXISTS(SELECT * FROM INSERTED) 
         THEN 'I' -- Set Action to Insert. 
         WHEN EXISTS(SELECT * FROM DELETED) 
         THEN 'D' -- Set Action to Deleted. 
         ELSE NULL -- Skip. It may have been a "failed delete". 
        END) 

agradecimiento especial a @KenDog y @Net_Prog para sus respuestas.
Lo construí a partir de sus scripts.

+1

Este es el premio, se elimina el manejo que no existe. ¡Buen trabajo! –

+2

Es posible que también tengamos una ACTUALIZACIÓN que no afectó a ninguna fila (ni siquiera a INSERT). –

0

En primer escenario que se supone que la tabla tiene la columna IDENTIDAD

CREATE TRIGGER [dbo].[insupddel_yourTable] ON [yourTable] 
FOR INSERT, UPDATE, DELETE 
AS 
IF @@ROWCOUNT = 0 return 
SET NOCOUNT ON; 
DECLARE @action nvarchar(10) 
SELECT @action = CASE WHEN COUNT(i.Id) > COUNT(d.Id) THEN 'inserted' 
         WHEN COUNT(i.Id) < COUNT(d.Id) THEN 'deleted' ELSE 'updated' END 
FROM inserted i FULL JOIN deleted d ON i.Id = d.Id 

En segundo escenario no es necesario utilizar la columna IDENTITTY

CREATE TRIGGER [dbo].[insupddel_yourTable] ON [yourTable] 
FOR INSERT, UPDATE, DELETE 
AS 
IF @@ROWCOUNT = 0 return 
SET NOCOUNT ON; 
DECLARE @action nvarchar(10), 
     @insCount int = (SELECT COUNT(*) FROM inserted), 
     @delCount int = (SELECT COUNT(*) FROM deleted) 
SELECT @action = CASE WHEN @insCount > @delCount THEN 'inserted' 
         WHEN @insCount < @delCount THEN 'deleted' ELSE 'updated' END 
+0

Tengo el mismo problema, alguien me puede ayudar. Consulte el siguiente enlace http://stackoverflow.com/questions/26043106/how-to-determine-if-insert-or-update/26043654#26043654 – Prathyush

0

solución rápida MySQL

Por el camino: estoy usando MySQL PDO.

(1) En una tabla de incremento automático acaba de obtener el valor más alto (mi nombre de la columna = id) de la columna incrementa una vez cada ejecución de script primero:

$select = " 
    SELECT MAX(id) AS maxid 
    FROM [tablename] 
    LIMIT 1 
"; 

(2) Ejecutar la consulta MySQL como usted normaly lo haría, y emitir el resultado a un entero, por ejemplo:

$iMaxId = (int) $result[0]->maxid; 

(3) Después de que el "insertar en ... eN ACTUALIZACIÓN una llave duplicada" consulta obtener el último ID insertado el modo preferido, por ejemplo:

$iLastInsertId = (int) $db->lastInsertId(); 

(4) Compare y reaccione: Si el lastInsertId es más alto que el más alto en la tabla, es probable que sea un INSERT, ¿verdad? Y viceversa.

if ($iLastInsertId > $iMaxObjektId) { 
    // IT'S AN INSERT 
} 
else { 
    // IT'S AN UPDATE 
} 

Sé que es rápido y tal vez sucio. Y es una publicación anterior. Pero, oye, estaba buscando una solución por mucho tiempo, y tal vez alguien encuentre mi camino algo útil de todos modos. ¡Todo lo mejor!

1

Esto hace el truco para mí:

declare @action_type int; 
select @action_type = case 
         when i.id is not null and d.id is  null then 1 -- insert 
         when i.id is not null and d.id is not null then 2 -- update 
         when i.id is  null and d.id is not null then 3 -- delete 
        end 
    from  inserted i 
    full join deleted d on d.id = i.id 

Dado que no todas las columnas se pueden actualizar a la vez se puede comprobar si una columna en particular está siendo actualizado por algo como esto:

IF UPDATE([column_name]) 
+0

Un desafío con esta solución es que debe conocer el nombre de una columna. Algunos de los otros están diseñados de manera que solo puede copiar pegar desde una biblioteca de fragmentos. Pequeño punto, pero considerando todo, una solución genérica es mejor que una solución específica de caso. EN MI HUMILDE OPINIÓN. – greg

0

acaba de forma sencilla

CREATE TRIGGER [dbo].[WO_EXECUTION_TRIU_RECORD] ON [dbo].[WO_EXECUTION] 
WITH EXECUTE AS CALLER 
FOR INSERT, UPDATE 
AS 
BEGIN 

    select @vars = [column] from inserted 
    IF UPDATE([column]) BEGIN 
    -- do update action base on @vars 
    END ELSE BEGIN 
    -- do insert action base on @vars 
    END 

END 
+0

Según mi SSMS IDE, su sintaxis no es correcta con la forma en que está ajustando su lógica en IF BEGIN - END ELSE BEGIN - END blocks. – Erutan409

0
DECLARE @INSERTEDCOUNT INT, 
     @DELETEDCOUNT INT 

SELECT @INSERTEDCOUNT = COUNT([YourColumnName]) FROM inserted 

SELECT @DELETEDCOUNT = COUNT([YourColumnName]) FROM deleted 

SI su updation

@INSERTEDCOUNT = 1 
@DELETEDCOUNT = 1 

si su inserción

@INSERTEDCOUNT = 1 
@DELETEDCOUNT = 0 
1
declare @insCount int 
declare @delCount int 
declare @action char(1) 

select @insCount = count(*) from INSERTED 
select @delCount = count(*) from DELETED 

    if(@insCount > 0 or @delCount > 0)--if something was actually affected, otherwise do nothing 
    Begin 
     if(@insCount = @delCount) 
      set @action = 'U'--is update 
     else if(@insCount > 0) 
      set @action = 'I' --is insert 
     else 
      set @action = 'D' --is delete 

     --do stuff here 
    End 
+1

No usaría COUNT (*) por razones de rendimiento; necesita escanear toda la tabla. En su lugar, establecería un indicador utilizando IF EXISTS (SELECT * FROM INSERTED), lo mismo para el DELETED. Normalmente sé que hay solo dos filas afectadas, pero ¿por qué desacelerar el sistema? – Endrju

+0

Estaba a punto de publicar algo muy similar como solución. Es un poco prolijo, pero muy legible. Equilibrio justo. También me gusta la solución Grahms anterior. – greg

15

estoy usando el siguiente, sino que también detecta correctamente eliminar declaraciones que eliminan nada:

CREATE TRIGGER dbo.TR_TableName_TriggerName 
    ON dbo.TableName 
    AFTER INSERT, UPDATE, DELETE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    IF NOT EXISTS(SELECT * FROM INSERTED) 
     -- DELETE 
     PRINT 'DELETE'; 
    ELSE 
    BEGIN 
     IF NOT EXISTS(SELECT * FROM DELETED) 
      -- INSERT 
      PRINT 'INSERT'; 
     ELSE 
      -- UPDATE 
      PRINT 'UPDATE'; 
    END 
END; 
+3

, este detecta incorrectamente declaraciones que no insertan nada ni actualizan nada, sin embargo. –

0

I He usado esas consultas exists (select * from inserted/deleted) durante mucho tiempo, pero todavía no es suficiente para operaciones CRUD vacías (cuando no hay registros en las tablas inserted y deleted). Así que después de la investigación de este tema un poco he encontrado la solución más precisa:

declare 
    @columns_count int = ?? -- number of columns in the table, 
    @columns_updated_count int = 0 

-- this is kind of long way to get number of actually updated columns 
-- from columns_updated() mask, it's better to create helper table 
-- or at least function in the real system 
with cte_columns as (
    select @columns_count as n 
    union all 
    select n - 1 from cte_columns where n > 1 
), cte_bitmasks as (
    select 
     n, 
     (n - 1)/8 + 1 as byte_number, 
     power(2, (n - 1) % 8) as bit_mask 
    from cte_columns 
) 
select 
    @columns_updated_count = count(*) 
from cte_bitmasks as c 
where 
    convert(varbinary(1), substring(@columns_updated_mask, c.byte_number, 1)) & c.bit_mask > 0 

-- actual check 
if exists (select * from inserted) 
    if exists (select * from deleted) 
     select @operation = 'U' 
    else 
     select @operation = 'I' 
else if exists (select * from deleted) 
    select @operation = 'D' 
else if @columns_updated_count = @columns_count 
    select @operation = 'I' 
else if @columns_updated_count > 0 
    select @operation = 'U' 
else 
    select @operation = 'D' 

También es posible el uso de columns_updated() & power(2, column_id - 1) > 0 para ver si se ha actualizado la columna, pero no es seguro para las tablas con gran número de columnas. Utilicé una forma de cálculo un tanto compleja (ver el útil artículo a continuación).

Además, este enfoque aún clasificará incorrectamente algunas actualizaciones como inserciones (si cada columna de la tabla se ve afectada por la actualización), y probablemente clasifique las inserciones donde solo se insertan valores predeterminados como eliminaciones, pero esas son las principales operaciones raras (en alquiler en mi sistema lo son). Además de eso, no sé cómo mejorar esta solución en este momento.

1

me gustan las soluciones que son "la informática elegante." Mi solución aquí golpea los pseudotables [insertados] y [eliminados] una vez para obtener sus estados y pone el resultado en una variable asignada de bits. Entonces, cada posible combinación de INSERTAR, ACTUALIZAR y ELIMINAR se puede probar fácilmente a través del activador con evaluaciones binarias eficientes (a excepción de la improbable combinación INSERTAR o ELIMINAR).

Supone que no importa cuál era la declaración DML si no se modificaban las filas (lo que debería satisfacer la gran mayoría de los casos). Entonces, aunque no es tan completo como la solución de Roman Pekar, es más eficiente.

Con este enfoque, tenemos la posibilidad de un disparador "FOR INSERT, UPDATE, DELETE" por tabla, 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 saber qué es lo que realmente funciona mejor.)

Tenga en cuenta que las instrucciones "exists (select * from" inserted/deleted »)" 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 
+0

Gracias por esta solución que feets en mi contexto. ¿Recomendaría una forma de actualizar la columna LastUpdated de la fila actualizada/insertada? ¿También recomendaría una forma de almacenar en otra mesa el ID de la fila eliminada (puede ser una clave compuesta)? –

7

creo anidada pasaría si un poco confuso y:

plana es mejor que anidado [El Zen de Python]

;)

DROP TRIGGER IF EXISTS AFTER_MYTABLE 

GO 

CREATE TRIGGER dbo.AFTER_MYTABLE ON dbo.MYTABLE AFTER INSERT, UPDATE, DELETE 

AS BEGIN 

    --- FILL THE BEGIN/END SECTION FOR YOUR NEEDS. 

    SET NOCOUNT ON; 

    IF EXISTS(SELECT * FROM INSERTED) AND EXISTS(SELECT * FROM DELETED) 
     BEGIN PRINT 'UPDATE' END 
    ELSE IF EXISTS(SELECT * FROM INSERTED) AND NOT EXISTS(SELECT * FROM DELETED) 
     BEGIN PRINT 'INSERT' END 
    ELSE IF EXISTS(SELECT * FROM DELETED) AND NOT EXISTS(SELECT * FROM INSERTED) 
     BEGIN PRINT 'DELETED' END 
    ELSE BEGIN PRINT 'NOTHING CHANGED'; RETURN; END -- NOTHING 

END 
4

probar este ..

ALTER TRIGGER ImportacionesGS ON dbo.Compra 
    AFTER INSERT, UPDATE, DELETE 
AS 
BEGIN 
    -- idCompra is PK 
    DECLARE @vIdCompra_Ins INT,@vIdCompra_Del INT 
    SELECT @vIdCompra_Ins=Inserted.idCompra FROM Inserted 
    SELECT @vIdCompra_Del=Deleted.idCompra FROM Deleted 
    IF (@vIdCompra_Ins IS NOT NULL AND @vIdCompra_Del IS NULL) 
    Begin 
    -- Todo Insert 
    End 
    IF (@vIdCompra_Ins IS NOT NULL AND @vIdCompra_Del IS NOT NULL) 
    Begin 
    -- Todo Update 
    End 
    IF (@vIdCompra_Ins IS NULL AND @vIdCompra_Del IS NOT NULL) 
    Begin 
    -- Todo Delete 
    End 
END 
4
Declare @Type varchar(50)=''; 
IF EXISTS (SELECT * FROM inserted) and EXISTS (SELECT * FROM deleted) 
BEGIN 
    SELECT @Type = 'UPDATE' 
END 
ELSE IF EXISTS(SELECT * FROM inserted) 
BEGIN 
    SELECT @Type = 'INSERT' 
END 
ElSE IF EXISTS(SELECT * FROM deleted) 
BEGIN 
    SELECT @Type = 'DELETE' 
END 
0

mientras lo hago también como la respuesta Publicado por @Alex, ofrezco esta variación a @ solución de Graham por encima de

este utiliza exclusivamente existencia registro en el insertada y tablas actualizadas, en lugar de utilizar COLUMNS_UPDATED de la primera prueba. También proporciona alivio programador paranoide sabiendo que el último caso se ha considerado ...

declare @action varchar(4) 
    IF EXISTS (SELECT * FROM INSERTED) 
    BEGIN 
     IF EXISTS (SELECT * FROM DELETED) 
      SET @action = 'U' -- update 
     ELSE 
      SET @action = 'I' --insert 
     END 
    ELSE IF EXISTS (SELECT * FROM DELETED) 
     SET @action = 'D' -- delete 
    else 
     set @action = 'noop' --no records affected 
--print @action 

obtendrá NOOP con una declaración como la siguiente:

update tbl1 set col1='cat' where 1=2 
Cuestiones relacionadas