2017-07-17 7 views
0

私は2つのテーブルを持っています。 最初の表には、多くの教室 (名前、年齢、教室)plsqlカーソルが異なるスキーマに挿入されます

別の表に、各classromのためのスキーマが含まれています(教室、SCHEMA_NAME)

(したがって、各classrom foがあります異なるスキーマ)

の生徒が含まれています

だから私は各クラスのための異なるスキーマを持っています。私は生徒のテーブルからすべてのデータを取得し、それらを正しいスキーマのターゲットテーブルにコピーする必要があります。 (私は管理者としてログインしています、私はすべてのスキーマへのアクセス権を持っている)

ここでは私の文は次のとおりです。

DECLARE 
    CURSOR all_pupils 
    IS 
     SELECT NAME, AGE, CLASSROOM FROM TABLE_1 
BEGIN 
    FOR pupil_rec 
    IN all_pupils 
    LOOP 
     EXECUTE IMMEDIATE 'INSERT INTO ' 
      || (Select schema_name FROM TABLE_2 sn WHERE sn.classroom=pupil_rec.CLASSROOM) ||'.TARGET_TABLE ' 
     ||'(name, age) VALUES (pupil_rec.name, pupil_rec.age'; 
    END LOOP; 
END; 
/

私はこのエラーを取得しています:

PLS-00103: Encountered the symbol "END" when expecting one of the following: 

私はちょうどPLSQLおよびIを学び始めました私はカーソルでそれをしなければならないと言われました。これが正しいアプローチであるかどうか誰かが私に助けてくれますか?私の構造は正しくないようです。これらのエラーを回避するには

+0

あなたはちょうどあなたが好きなラインの途中に ''(選択を...)ドロップすることはできません。カーソルを拡張して、必要な値を含める必要があります。 –

答えて

0

EXECUTE IMMEDIATEは静的な文字列でのみ動作します。そのため、まずスキーマ名を変数に問い合せ、その変数をステートメントに組み込む必要があります。

また、カーソルの内容は実行された文字列の範囲には含まれません。だから、値をプレースホルダーに渡す必要があります。

また
DECLARE 
    CURSOR all_pupils 
    IS 
     SELECT NAME, AGE, CLASSROOM FROM TABLE_1; 
    l_schema_name varchar2(30); 
BEGIN 
    FOR pupil_rec 
    IN all_pupils 
    LOOP 
     Select schema_name 
     into l_schema_name 
     FROM TABLE_2 sn 
     WHERE sn.classroom=pupil_rec.CLASSROOM: 
     EXECUTE IMMEDIATE 'INSERT INTO ' 
      || l_schema_name ||'.TARGET_TABLE ' 
      ||'(name, age) VALUES (:1, :2)' 
      using pupil_rec.name, pupil_rec.age; 
    END LOOP; 
END; 
/

、駆動カーソルに参加を使用して...

DECLARE 
    CURSOR all_pupils 
    IS 
     SELECT t1.NAME, t1.AGE, sn.schema_name 
     FROM TABLE_1 t1 
      join TABLE_2 sn 
      on sn.classroom = T1.CLASSROOM 
     where t1.col_copied != 1 
     for update of t1.col_copied ; 
BEGIN 
    FOR pupil_rec 
    IN all_pupils 
    LOOP 
     EXECUTE IMMEDIATE 'INSERT INTO ' 
      || pupil_rec.schema_name ||'.TARGET_TABLE ' 
      ||'(name, age) VALUES (:1, :2)' 
      using pupil_rec.name, pupil_rec.age; 

     update TABLE_1 t1 
     set t1.col_copied = 1 
     where current of all_pupils; 

    END LOOP; 
END; 
/
+0

私の追加の要件(今すぐ見つけたsry)。私のTable_1は追加の列(COL_COPIED)を持っています。行が選択され、正しいスキーマでコピーされるときに1に設定する必要があります。 (つまり、TABLE_1は常に新しいデータを取得する)行を選択するだけです。更新を行うaddit文のように、forループ内で実行することはできますか?または、より良い解決策があります – Norbert94

+0

thx、ちょうど質問(あなたの声明を理解しようとしています) あなたの最初の結合は、最初の解法(結合なし)のように、table_1からすべてのデータを選択します。ループ内のschema_nameを参照するためには? – Norbert94

+0

はい。一般に、2つのテーブルを結合することは、ループ内のルックアップよりも優れています。これは、集合演算が行ごとの処理より効率的であるためです。おそらくあなたの状況に大きな違いはありませんが、良い習慣を身につけるのが早すぎることはありません。 – APC

-1

スキーマ名の保存には新しい変数が必要です。 Execute Immediate内には、文字列として提供されていない限り、他の文字の連結はできません。SELECT

DECLARE 

    CURSOR all_pupils 
    IS 

     SELECT NAME, 
      AGE, 
      CLASSROOM 
     FROM TABLE_1; 

    v_chr_schema TABLE_2.schema_name%TYPE; 
BEGIN 

    FOR pupil_rec IN all_pupils 
    LOOP 

     SELECT schema_name 
     INTO v_chr_schema 
     FROM TABLE_2 
     WHERE sn.classroom=pupil_rec.CLASSROOM; 

     EXECUTE IMMEDIATE 'INSERT INTO ' || v_chr_schema ||'.TARGET_TABLE ' || 
     '(name, age) VALUES (' || pupil_rec.name || ',' || pupil_rec.age || ')'; 

    END LOOP; 

END; 
/
+0

thx非常に多く、私はあなたの入力に応じて私の声明を変更しましたが、私はエラーが表示されます:00984. 00000 - "ここでは列が許可されていません – Norbert94

+0

@ Norbert94 - カーソルの値は文字列の外にあったはずです。 –

関連する問題