2010-12-08 13 views
8

Si un usuario cambia la tabla HelloWorlds, entonces quiero 'acción que hicieron', la hora en que lo hicieron y una copia de la fila original insertada en HelloWorldsHistory.Cómo copiar una fila insertada, actualizada y eliminada en un disparador de SQL Server

Preferiría evitar un desencadenante separado para insertar, actualizar y eliminar acciones debido a las longitudes de columna.

He intentado esto:

create trigger [HelloWorlds_After_IUD] on [HelloWorlds] 
FOR insert, update, delete 
as 
if @@rowcount = 0 
return 
if exists (select 1 from inserted) and not exists (select 1 from deleted) 
begin 
insert into HelloWorldHistory (hwh_action, ..long column list..) 
select 'INSERT', helloWorld.id, helloWorld.text ... and more from inserted 
end 
else 
    if exists (select 1 from inserted) and exists (select 1 from deleted) 
    begin 
insert into HelloWorldHistory (hwh_action, ..long column list..) 
select 'UPDATE', helloWorld.id, helloWorld.text ... and more from deleted 
    end 
    else 
    begin 
insert into HelloWorldHistory (hwh_action, ..long column list..) 
select 'DELETE', helloWorld.id, helloWorld.text ... and more from deleted 
    end 
end 

nunca he visto aparecer una inserción, pero he visto actualizaciones. Voy a probar 3 disparadores por separado, aunque mantener las listas de columnas no será divertido.

+0

no utilice DELETED como fuente de datos para las ACTUALIZACIONES, solo estará registrando el valor anterior que ya estaba registrado. Su fila de registro será de tipo "Actualizar" pero los datos podrían haber sido de una inserción. Véame comentar en mi respuesta. –

Respuesta

19

intentar algo como esto:

CREATE TRIGGER YourTrigger ON YourTable 
    AFTER INSERT,UPDATE,DELETE 
AS 

DECLARE @HistoryType char(1) --"I"=insert, "U"=update, "D"=delete 

SET @HistoryType=NULL 

IF EXISTS (SELECT * FROM INSERTED) 
BEGIN 
    IF EXISTS (SELECT * FROM DELETED) 
    BEGIN 
     --UPDATE 
     SET @HistoryType='U' 
    END 
    ELSE 
    BEGIN 
     --INSERT 
     SET @HistoryType='I' 
    END 
    --handle insert or update data 
    INSERT INTO YourLog 
      (ActionType,ActionDate,.....) 
     SELECT 
      @HistoryType,GETDATE(),..... 
      FROM INSERTED 

END 
ELSE IF EXISTS(SELECT * FROM DELETED) 
BEGIN 
    --DELETE 
    SET @HistoryType='D' 

    --handle delete data, insert into both the history and the log tables 
    INSERT INTO YourLog 
      (ActionType,ActionDate,.....) 
     SELECT 
      @HistoryType,GETDATE(),..... 
      FROM DELETED 

END 
--ELSE 
--BEGIN 
-- both INSERTED and DELETED are empty, no rows affected 
--END 
+0

funciona muy bien. Estar cerca me hizo sentir mucho mejor sobre cómo desenterrar mis polvorientas habilidades MS SQL después de estar en Oracle durante los últimos años. – DefyGravity

+0

Mi solución final será esta "arquitectura", con las columnas pk de bob verificando entre la tabla de origen y las tablas de activación de transacciones temporales. Además, extraeré los datos de 'ACTUALIZACIÓN' de la tabla eliminada, en lugar de insertarlos. – DefyGravity

+4

Recomiendo encarecidamente que registre la ACTUALIZACIÓN de la tabla INSERTADA. Aquí hay un ejemplo: inserte los datos de la fila = AAA (INSERTED = AAA va a registrar), actualice la misma fila a BBB (INSERTED = BBB, DELETED = AAA, digo send BBB to log, y no AAA, que ya estaba registrado). Además, cuando se usa 'IF EXISTS ', todas las" verificaciones de teclas "no son necesarias y solo están sobrecargadas. Un disparador solo puede disparar por 1 comando a la vez, un INSERT o un UPDATE o un DELETE, por lo que no hay necesidad de hacer coincidir las teclas para determinar la operación. Nunca tendrá datos de ACTUALIZACIONES mezclados con datos de INSERT dentro de un desencadenador. –

6

es necesario asociar (partido) de las filas de las columnas insertadas y eliminadas. Algo así debería funcionar mejor.

create trigger [HelloWorlds_After_IUD] on [HelloWorlds] 
FOR insert, update, delete 
as 

insert into HeloWorldsHistory 
select 'INSERT', helloWorld.id, helloWorld.text ... and more 
from inserted 
where myKeyColumn not in (select myKeyColumn from deleted) 

insert into HeloWorldsHistory 
select 'DELETE', helloWorld.id, helloWorld.text ... and more 
from deleted 
where myKeyColumn not in (select myKeyColumn from inserted) 

insert into HeloWorldsHistory 
select 'UPDATE', helloWorld.id, helloWorld.text ... and more 
from inserted 
where myKeyColumn in (select myKeyColumn from deleted) 
+0

¡Definitivamente voy a hacer coincidir en el pk! gracias por esa captura! – DefyGravity

+1

vea el comentario de KM sobre la comprobación de PK en esta situación – DefyGravity

Cuestiones relacionadas