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

Blu*_*ppy 16 t-sql triggers stored-procedures

也许是一个愚蠢的问题!

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

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

       EXEC createAuditSproc 'I NEED VALUES HERE!' 
Run Code Online (Sandbox Code Playgroud)

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

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

Stu*_*tLC 25

您可以使用INSERTED和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
Run Code Online (Sandbox Code Playgroud)

给出示例表

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
Run Code Online (Sandbox Code Playgroud)

编辑:道歉,我没有解决有关调用存储过程的问题.根据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  
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

insert into dbo.MyTable 
    select 'double'
union
    select 'insert';
Run Code Online (Sandbox Code Playgroud)

但是,如果您使用的是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;
Run Code Online (Sandbox Code Playgroud)

  • +1并且还记得那些`Inserted`和`Deleted`表可能包含几行 - 而不仅仅是一行!永远不要假设在触发器中只处理一行! (4认同)