从插入触发器后调用存储过程

时间:2011-02-03 15:10:27

标签: tsql stored-procedures triggers

也许是一个愚蠢的问题!

如果我从After Insert触发器(T-SQL)调用存储过程 - 那么如何获取“刚插入”数据的值? e.g。

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

       EXEC createAuditSproc 'I NEED VALUES HERE!' 

我没有任何标识列需要担心 - 我只想使用一些“刚插入”的值传递给我的sproc。

编辑:为了澄清 - 我需要这个来调用一个sproc而不是直接插入到表中,因为sproc不止一件事。我正在处理一些我目前无法正确修改的遗留表(时间/资源/遗留代码),所以我必须使用我所拥有的:(

1 个答案:

答案 0 :(得分:23)

您可以使用INSERTED and DELETED伪表来获取新的“已更改”数据:

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

给出示例表

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

编辑:道歉,我没有解决有关调用存储过程的问题。根据marc_s的注释,请注意插入/删除的行可能包含多行,这使得SPROC的问题变得复杂。就个人而言,我会将触发器直接插入审计表而不需要封装SPROC。但是,如果您有SQL 2008,则可以使用表值参数,如下所示:

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  

然后你的触发器会被改变,如下所示:

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

然后,您可以测试这适用于单个和多个插入

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

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

但是,如果您使用的是SQL 2005或更低版本,则可能需要使用游标将插入的传递行循环到您的SPROC,这太难以考虑了。

作为旁注,如果您有SQL 2008,可以查看Change Data Capture

编辑#2 :因为您需要调用proc,并且如果您确定只插入一行...

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;