BEFORE
トリガーをトリガーに置き換えることができる場合もありAFTER
ますが、挿入が行われる前に明らかに値を提供する必要があるため、これはあなたの状況には当てはまらないようです。そのため、@marc_s がコメントで示唆しているように、最も近い機能はINSTEAD OF
トリガー機能のようです。
BEFORE
ただし、これら 2 つのトリガー タイプの名前が示すように、トリガーとトリガーには根本的な違いがあることに注意してくださいINSTEAD OF
。どちらの場合も、トリガーを呼び出したステートメントによって決定されるアクションが発生していないときにトリガーが実行されますが、トリガーの場合INSTEAD OF
、アクションはまったく発生しないはずです。実行する必要がある実際のアクションは、トリガー自体によって実行する必要があります。BEFORE
これは、明示的にロールバックしない限り、ステートメントが常に実行されるトリガー機能とは大きく異なります。
しかし、実際に取り組むべき問題がもう 1 つあります。Oracle スクリプトが明らかにしているように、変換する必要があるトリガーは、SQL Server でサポートされていない別の機能を使用していますFOR EACH ROW
。SQL Server にも行ごとのトリガーはなく、ステートメントごとのトリガーのみです。つまり、挿入されたデータは単一の行ではなく、行セットであることに常に留意する必要があります。これにより複雑さが増しますが、説明する必要があるもののリストはおそらくこれで終わりです。
したがって、実際に解決すべきことは次の 2 つです。
機能を置き換えBEFORE
ます。
機能を置き換えFOR EACH ROW
ます。
これらを解決するための私の試みは以下のとおりです。
CREATE TRIGGER sub_trg
ON sub1
INSTEAD OF INSERT
AS
BEGIN
DECLARE @new_super TABLE (
super_id int
);
INSERT INTO super (subtype_discriminator)
OUTPUT INSERTED.super_id INTO @new_super (super_id)
SELECT 'SUB1' FROM INSERTED;
INSERT INTO sub (super_id)
SELECT super_id FROM @new_super;
END;
上記の仕組みは次のとおりです。
に挿入されるのと同じ数の行sub1
が最初に に追加されsuper
ます。生成super_id
された値は、一時ストレージ ( と呼ばれるテーブル変数@new_super
) に格納されます。
新しく挿入されたsuper_id
が に挿入されsub1
ます。
それほど難しいことはありませんが、上記はsub1
、質問で指定した列以外に列がない場合にのみ機能します。他の列がある場合、上記のトリガーはもう少し複雑にする必要があります。
super_id
問題は、挿入されたすべての行に個別に新しい s を割り当てることです。マッピングを実装する 1 つの方法は、次のようになります。
CREATE TRIGGER sub_trg
ON sub1
INSTEAD OF INSERT
AS
BEGIN
DECLARE @new_super TABLE (
rownum int IDENTITY (1, 1),
super_id int
);
INSERT INTO super (subtype_discriminator)
OUTPUT INSERTED.super_id INTO @new_super (super_id)
SELECT 'SUB1' FROM INSERTED;
WITH enumerated AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rownum
FROM inserted
)
INSERT INTO sub1 (super_id, other columns)
SELECT n.super_id, i.other columns
FROM enumerated AS i
INNER JOIN @new_super AS n
ON i.rownum = n.rownum;
END;
ご覧のとおり、IDENTIY(1,1)
列が に追加される@new_user
ため、一時的に挿入されたsuper_id
値が 1 から追加で列挙されます。新しいsuper_id
と新しいデータ行の間のマッピングを提供するために、ROW_NUMBER
関数を使用してINSERTED
行も列挙します。その結果、INSERTED
セット内のすべての行を 1 つの行にリンクできるようになりsuper_id
、完全なデータ行を補完して に挿入できるようになりましたsub1
。
新しいsuper_id
が挿入される順序は、割り当てられる順序と一致しない場合があることに注意してください。私はそれを問題にしないと考えました。生成されたすべての新しいsuper
行は、ID を除いて同一です。したがって、ここで必要なのは、新しい行super_id
ごとに新しいものを 1 つ取得することだけです。sub1
ただし、挿入のロジックsuper
がより複雑で、何らかの理由で、どの新しい行super_id
に対してどの新しい行が生成されたかを正確に覚えておく必要があるsub
場合は、このスタック オーバーフローの質問で説明されているマッピング方法を検討することをお勧めします。