【问题标题】:Call stored proc from after insert trigger从插入触发器后调用存储过程
【发布时间】:2011-06-20 17:56:21
【问题描述】:

也许是个愚蠢的问题!

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

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

       EXEC createAuditSproc 'I NEED VALUES HERE!' 

我不需要担心任何标识列 - 我只想使用一些“刚刚插入”的值传递到我的存储过程中。

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

【问题讨论】:

    标签: tsql stored-procedures triggers


    【解决方案1】:

    您可以使用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;
    

    【讨论】:

    • +1 并记住那些InsertedDeleted 表可能包含多行——而不仅仅是一行!永远不要假设触发器中只处理了一行!
    • 如何获取这些值作为存储的过程参数?我是否需要全部声明它们然后'select @param1 = val1,@param2 = val2'然后将它们传递进去?
    • @param1 = val1 是一种方法,但由于您可以处理多行,我建议您实现 table 参数或使用游标为插入的每一行数据调用一次存储的过程。
    猜你喜欢
    • 2013-01-21
    • 1970-01-01
    • 2015-02-05
    • 2011-09-30
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 2017-10-14
    相关资源
    最近更新 更多