web-dev-qa-db-ja.com

挿入トリガーの後からストアドプロシージャを呼び出す

おそらく愚かな質問です!

挿入後トリガー(T-SQL)からストアドプロシージャを呼び出す場合、「挿入されたばかりの」データの値を取得するにはどうすればよいですか?例えば.

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

       EXEC createAuditSproc 'I NEED VALUES HERE!' 

心配するID列はありません。「挿入したばかりの」値のいくつかを使用してsprocに渡したいだけです。

編集:明確にするために-sprocは複数のことを行うため、これはsprocを呼び出し、テーブルに直接挿入しないために必要です。私は現在、物事を「適切に」行うために修正できないいくつかのレガシーテーブル(時間/リソース/レガシーコード)を使用しているので、私が持っているものを使用する必要があります:(

16
BlueChippy

INSERTED and DELETED pseudo-tablesを使用して、新しく「変更された」データにアクセスします。

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

Edit:申し訳ありませんが、ストアドプロシージャの呼び出しについては少し触れませんでした。 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を使用している場合は、 データキャプチャの変更 を参照してください。

編集#2:procを呼び出す必要があるため、1行しか挿入しないことが確実な場合...

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;
25
StuartLC