2011-02-03 10 views
14

¡Quizás una pregunta estúpida!Llamar al proceso almacenado después de insertar el desencadenador

Si llamo a un proceso almacenado desde un desencadenante After Insert (T-SQL) - entonces, ¿cómo obtengo los valores de los datos "recién insertados"? p.

CREATE TRIGGER dbo.MyTrigger 
    ON dbo.MyTable 
    AFTER INSERT 
    AS 
    BEGIN 

     EXEC createAuditSproc 'I NEED VALUES HERE!' 

que no tienen ninguna columna de identidad de las que preocuparse - sólo quiero utilizar algunos de los valores "acaba de insertar" a pasar a mi sproc.

Editar: Para aclarar - Necesito esto para llamar a un sproc y no hacer una inserción directa a la mesa, ya que el sproc hace más de una cosa. Estoy trabajando con algunas tablas heredadas que actualmente no puedo modificar para hacer las cosas "correctamente" (tiempo/recursos/código heredado), así que tengo que trabajar con lo que tengo :(

Respuesta

22

Llegas al nuevo ' 'datos cambiados mediante el uso de la INSERTED and DELETED seudo-mesas:

CREATE TRIGGER dbo.MyTrigger  
    ON dbo.MyTable  
    AFTER INSERT  
AS  
    BEGIN   
     INSERT INTO myTableAudit(ID, Name) 
     SELECT i.ID, i.Name 
      FROM inserted i; 
    END 

Teniendo en cuenta las tablas de ejemplo

create table myTable 
(
    ID INT identity(1,1), 
    Name varchar(10) 
) 
GO 

create table myTableAudit 
(
    ID INT, 
    Name varchar(10), 
    TimeChanged datetime default CURRENT_TIMESTAMP 
) 
GO 

Editar: Disculpas, no se refirió a lo de llamar a un procedimiento almacenado de acuerdo. Comentario de marc_s, nota que insertado/de puede contener múltiples filas, lo que complica las cosas con un SPROC. Personalmente, dejaría el desencadenante insertándose directamente en la tabla de auditoría sin la encapsulación de un SPROC. Sin embargo, si usted tiene SQL 2008, puede utilizar parámetros con valores de tabla, así:

CREATE TYPE MyTableType AS TABLE 
(
    ID INT, 
    Name varchar(10) 
); 
GO 

CREATE PROC dbo.MyAuditProc @MyTableTypeTVP MyTableType READONLY 
AS 
    BEGIN 
     SET NOCOUNT ON; 

     INSERT INTO myTableAudit(ID, Name) 
     SELECT mtt.ID, mtt.Name 
      FROM @MyTableTypeTVP mtt; 
    END 
GO 

Y entonces su disparador se modifican, de este modo:

ALTER TRIGGER dbo.MyTrigger 
    ON dbo.MyTable  
    AFTER INSERT  
AS  
    BEGIN   
     SET NOCOUNT ON; 

     DECLARE @MyTableTypeTVP AS MyTableType; 

     INSERT INTO @MyTableTypeTVP(ID, Name) 
     SELECT i.ID, i.Name 
      FROM inserted i; 

     EXEC dbo.MyAuditProc @MyTableTypeTVP; 
    END 

a continuación, puede comprobar que funcione tanto para un solo y múltiples inserciones

insert into dbo.MyTable values ('single'); 

insert into dbo.MyTable 
    select 'double' 
union 
    select 'insert'; 

Sin embargo, si está utilizando SQL 2005 o inferior, es probable que tenga que utilizar un cursor para recorrer insertada pasando filas a su sproc, algo también Horr ible a contemplar.

Como nota al margen, si usted tiene SQL 2008, lo podría hacer en Change Data Capture

Edición # 2: Ya que se necesita para llamar al proc, y si está seguro de que sólo se inserte una fila. ..

ALTER TRIGGER dbo.MyTrigger 
    ON dbo.MyTable  
    AFTER INSERT  
AS  
    BEGIN   
     SET NOCOUNT ON; 

     DECLARE @SomeInt INT; 
     DECLARE @SomeName VARCHAR(10); 

     SELECT TOP 1 @SomeInt = i.ID, @SomeName = i.Name 
     FROM INSERTED i; 

     EXEC dbo.MyAuditProc @SomeInt, @SomeName; 
    END; 
+4

+1 y también recuerde que esas tablas "Insertado" y "Eliminado" contendrán potencialmente varias filas, ¡no solo una sola! ¡Nunca asuma que solo una fila está siendo procesada en un disparador! –

+0

¿Cómo obtengo esos valores como parámetros de proc almacenados? ¿Debo declararlos todos y luego 'seleccionar @ param1 = val1, @ param2 = val2' y luego pasarlos? – BlueChippy

+0

@ param1 = val1 es de una manera, pero como podría trabajar con varias filas, recomiendo implementar el argumento de tabla o usar un cursor para llamar al proceso almacenado una vez para cada fila de datos insertados. – Armand

Cuestiones relacionadas