2011-02-03 64 views
14

也许是一个愚蠢的问题!插入触发后调用存储过程

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

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

     EXEC createAuditSproc 'I NEED VALUES HERE!' 

我没有任何标识列担心 - 我只是想使用一些“刚插入”的值传入我的存储过程。

编辑:澄清 - 我需要这个调用一个存储过程,而不是直接插入到表中,因为存储过程不止一件事。我正在处理一些遗留表格,我目前无法修改以适当地处理这些问题(时间/资源/遗留代码),所以我必须使用我所拥有的东西:(

回答

22

您可以到新“改变”数据使用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的评论,注意插入/ de可以包含多行,这使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或更低时,你可能需要使用游标来遍历插入行传递到你的存储过程,东西太多horr能够思考。

作为一个侧面说明,如果你有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; 
+4

+1还记得那些`Inserted`和`Deleted`表可能包含几行 - 不只是一个!永远不要假设只有一行正在触发器中进行处理! – 2011-02-03 15:20:53