2017-07-17 67 views
0

我有2個表。 第一個表中包含許多教室 (姓名,年齡,教室)plsql遊標插入到不同的模式

另一張表的模式爲每個classrom(教室,SCHEMA_NAME)

(所以有FO各classrom不同的架構)

的學生

所以我對每個類都有不同的模式。我需要從學生表中提取所有數據並將其複製到正確模式的目標表中。 (我登錄作爲管理員,我可以訪問所有模式)

這裏是我的發言:

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和我被告知我必須用光標來做。有人可以幫助我,告訴我這是否正確嗎?我的結構似乎不正確..如何避免這些錯誤

+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

我有一個額外的需求(現在剛剛發現),我的Table_1有一個額外的列(COL_COPIED),當該行被選擇並複製到正確的模式中時,我需要將它設置爲1 ..再次它只選擇沒有被複制的行(TABLE_1將總是獲得新的數據)。我可以在我的for循環中執行更新的additonal語句(如插入)嗎?還是有更好的解決方案 – Norbert94

+0

thx非常多,只是一個問題(我試圖理解你的陳述) 你的加入在開始時選擇了所有來自table_1的數據,就像你的第一個解決方案(沒有連接)。爲了引用循環內的schema_name權限? – Norbert94

+0

是的。一般來說,連接兩個表比循環中的查找要好,因爲集合操作比逐行處理更有效。它可能不會在你的情況有很大的不同,但它永遠不會過早進入良好的習慣 – 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 - 遊標的值應該已經超出字符串。 –