1

レコードをコピーしてそれ自体に戻す必要があるテーブルがあります。その一環として、OUTPUT 句を使用してテーブル変数に新しい行をキャプチャし、同じプロセスで行に対して他の操作を実行できるようにしたいと考えています。各行に新しいキーとコピー元のキーを含めたい。これは不自然な例です:

INSERT 
    MyTable (myText1, myText2) -- myId is an IDENTITY column
OUTPUT  
    Inserted.myId, 
    Inserted.myText1, 
    Inserted.myText2 
INTO
    -- How do I get previousId into this table variable AND the newly inserted ID? 
    @MyTable    
SELECT 
    -- MyTable.myId AS previousId,
    MyTable.myText1,
    MyTable.myText2
FROM
    MyTable
WHERE
    ...

INSERT の列数が SELECT ステートメントの列数と一致しない場合、SQL Server は吠えます。そのため、列を MyTable に追加した場合にこれがどのように機能するかはわかりますが、それはオプションではありません。以前は、これはパフォーマンスのボトルネックを引き起こしているカーソルで実装されていました。意図的にそれを回避しようとしています。

可能な限り最高のパフォーマンスを達成する方法でコピーされた行のキーを保持しながら、これらのレコードをコピーするにはどうすればよいですか?

4

1 に答える 1

1

コンテキストについては少しわかりません。これはAFTERINSERTトリガーの場合です。

とにかく、私はこれを1回の呼び出しで行う方法を見つけることができません。OUTPUT句では、挿入した行のみを返すことができます。私がお勧めするのは次のとおりです。

DECLARE @MyTable (
    myID INT, 
    previousID INT, 
    myText1 VARCHAR(20), 
    myText2 VARCHAR(20)
)

INSERT @MyTable (previousID, myText1, myText2) 
SELECT myID, myText1, myText2 FROM inserted

INSERT MyTable (myText1, myText2) 
SELECT myText1, myText2 FROM inserted

-- @@IDENTITY now points to the last identity value inserted, so...
UPDATE m SET myID = i.newID
FROM @myTable m, (SELECT @@IDENTITY - ROW_NUMBER() OVER(ORDER BY myID DESC) + 1 AS newID, myID FROM inserted) i
WHERE m.previousID = i.myID

...

もちろん、これをAFTER INSERTトリガーに入れることはありません。再帰呼び出しが行われるためですが、INSTEADOFINSERTトリガーで行うことはできます。再帰的な問題については間違っているかもしれません。私は常に再帰呼び出しを避けてきたので、実際に見つけたことはありません。ただし、@@ IDENTITYとROW_NUMBER()を使用することは、私が過去に数回使用して同様のことを行うためのトリックです。

于 2012-03-05T17:19:33.400 に答える