次の方法で共有


O2SS0239: ROWID 列にアクセスできません (エラー)

この記事では、SQL Server Migration Assistant (SSMA) for Oracle でテーブルに対してトリガーを含む ROWID 列を定義する必要がある理由について説明します。

背景

Oracle では、変更される一連の行全体ではなく、実行 FOR EACH ROWされるトリガーを作成できます。 SQL Server では、変更された行のセット全体に対してトリガーが常に実行されます。 行レベルの Oracle トリガーが両方の :old :new 特別な変数にアクセスする場合、SSMA では、更新の前後の特定の行の値を識別するために、両方の行セットの行を照合する方法が必要です。 このような "行ごとに" 機能をエミュレートするために、SSMA は、変更された各行を一意に識別する特別な ROWID 列を追加し、それを使用して inserteddeleted の行セット間のリレーションシップを確立します。

この動作は、ROWID 列の生成プロジェクト設定によって制御されます。この設定は、[ツール - プロジェクト設定] - の [一般 - 変換 - ROWID 生成] にあります。 設定が [いいえ] に設定されている場合、ROWID列はテーブルに追加されず、SSMA はそのようなトリガーを変換できません。

次の Oracle トリガーは、テーブルで更新された各行に対して TRIG_TEST 実行されます。

CREATE OR REPLACE TRIGGER TSCHM.TRIG_TEST_AU
AFTER UPDATE OF DATA ON TSCHM.TRIG_TEST
FOR EACH ROW
BEGIN
    IF (:new.DATA = 'ABC') THEN
        INSERT INTO TSCHM.TRIG_TEST(DATA) VALUES ('-' || :old.DATA);
    END IF;
END;

SSMA でこのトリガーを変換しようとすると、[ROWID 列の生成] プロジェクト設定が [いいえ] に設定されている場合、SSMA によって次のエラー メッセージが生成されます。

O2SS0239: ROWID 列にアクセスできません

考えられる対処方法

[ROWID 列生成] プロジェクト設定を、トリガーを持つテーブルの ROWID 列を追加するように変更します。これにより、SSMA は、前の例を変換するときに、SQL Server トリガー内で次の T-SQL を生成できます。

  1. inserted 行セットの上にカーソルを移動し、ROWIDおよび DATA 列を選んで @new$0 および @new$DATA 変数を選びます。

    DECLARE
        ForEachInsertedRowTriggerCursor CURSOR LOCAL FORWARD_ONLY READ_ONLY FOR
        SELECT ROWID, DATA
        FROM inserted
    
    OPEN ForEachInsertedRowTriggerCursor
    
    FETCH ForEachInsertedRowTriggerCursor
        INTO @new$0, @new$DATA
    
  2. 挿入 ROWID された (変数に @old$0 格納されている) に基づいて、行セットと @old$DATA 変数から deleted 一致する行を @new$0 選びます。

    SELECT @old$0 = ROWID, @old$DATA = DATA
    FROM deleted
    WHERE ROWID = @new$0
    
  3. 変数を使用してトリガー アクションを @old$DATA/@new$DATA 実行します。

    IF (@new$DATA = 'ABC')
        INSERT SSMAADMIN.TRIG_TEST(DATA)
        VALUES (('-' + ISNULL(@old$DATA, '')))