2013-04-06 56 views
3

我試圖在表中保存XML。 XML的格式如下:在表中保存嵌套XML時出現PL/SQL錯誤

<employees> 
    <employees_id> 1</employees_id> 
    <employees_name>Teradata</employees_name> 
    <department_id>100</department_id> 
    <department_name>Techinical</department_name> 
    <department_id>200</department_id> 
    <department_name>Management</department_name> 
    <department_id>300</department_id> 
    <department_name>Telecom</department_name> 
    </employees> 
    <employees> 
    <employees_id> 2</employees_id> 
    <employees_name>AT&T</employees_name> 
    <department_id>400</department_id> 
    <department_name>Techinical</department_name> 
    <department_id>500</department_id> 
    <department_name>Management</department_name> 
    <department_id>600</department_id> 
    <department_name>Telecom</department_name> 
    </employees> 

我的表只有一個id列和xmltype列。

,我現在用的程序如下:

DECLARE 
    CTX   DBMS_XMLGEN.CTXHANDLE; 
    LCLOB$XML_AS_CLOB CLOB; 
    LREC$EMPLOYEES_EMPNO NUMBER; 
BEGIN 
    FOR LREC$EMPLOYEES_EMPNO IN (198, 197, 180) 
    LOOP 
    --Create context for XML 
    CTX := 
     DBMS_XMLGEN.NEWCONTEXT (
     'SELECT employees.EMPLOYEE_ID, employees.FIRST_NAME, 
     departments.DEPARTMENT_ID, departments.DEPARTMENT_NAME 
     FROM EMPLOYEES, departments 
     WHERE employees.department_id = departments.department_id and 
     employees.employees_id =' || LREC$EMPLOYEES_EMPNO); 
    --Get XML file of Context 
    -- Set the row header to be EMPLOYEE 
    DBMS_XMLGEN.setRowTag(CTX, 'EMPLOYEE'); 
    LCLOB$XML_AS_CLOB := DBMS_XMLGEN.GETXML (CTX); 
    DBMS_XMLGEN.CLOSECONTEXT (CTX); 
    INSERT INTO HR.OFFLINE_XML (id, XML_FILE) 
     VALUES (LREC$EMPLOYEES_EMPNO, XMLTYPE (LCLOB$XML_AS_CLOB)); 
    END LOOP; 
    COMMIT; 
END; 

錯誤報告:

ORA-06550: line 7, column 4: 
PLS-00103: Encountered the symbol "LOOP" when expecting one of the following: 

    * & - +/at mod remainder rem .. <an exponent (**)> || 
    multiset year day 
ORA-06550: line 18, column 16: 
PLS-00103: Encountered the symbol "." when expecting one of the following: 

    constant exception <an identifier> 
    <a double-quoted delimited-identifier> table long double ref 
    char time timestamp interval date binary national charac 
ORA-06550: line 19, column 23: 
PLS-00103: Encountered the symbol "=" when expecting one of the following: 

    constant exception <an identifier> 
    <a double-quoted delimited-identifier> table long double ref 
    char time timestamp interval date binary national charac 
ORA-06550: line 20, column 16: 
PLS-00103: Encountered the symbol "." when expecting one of the following: 

    constant exception <an identifier> 
    <a double-quoted delimited-identifier> table long double ref 
    char time timestamp interval date binary national charac 
ORA-06550: line 21, column 5: 
PLS-00103: Encountered the symbol "INSERT" when expecting one of the following: 

    begin function pragma procedure subtype type <an identifier> 
    <a double-quoted delimited-identifier> current cursor delete 
    exists prior 
The symbol "b 
ORA-06550: line 24, column 4: 
PLS-00103: Encountered the symbol "COMMIT" when expecting one of the following: 

    end not pragma final instantiable order overriding static 
    member constructor map 
06550. 00000 - "line %s, column %s:\n%s" 
*Cause: Usually a PL/SQL compilation error. 
*Action: 
+0

例外堆棧,請嗎? – Rachcha 2013-04-06 08:39:26

回答

2

正如Noel所說,您無法將固定值提供給for這樣的循環。 (報告中的所有其他錯誤都是偶然的,儘管還有其他問題)。您可以提供一個範圍,如for i in 1..10 loop,但即使對於您的示例數據,這也無濟於事。由於這只是測試你可以使用一個虛假光標現在:

FOR LREC$EMPLOYEES_EMPNO IN (
     SELECT 198 AS employee_id FROM dual 
     UNION ALL SELECT 197 FROM dual 
     UNION ALL SELECT 180 FROM dual 
    ) LOOP 

(儘管其實我更喜歡DazzaL的陣列,但我會用這根棍子現在)。您不必聲明遊標,並且使用該名稱聲明的變量將被此版本取代。當你引用其中一個值時,它必須是名字,所以在這種情況下,LREC$EMPLOYEES_EMPNO.employee_id。 Persoanlly我會去一個較短的名稱* 8-)

由於DazzaL也提到你不需要中間的CLOB。當你可以使用綁定變量代替時,似乎也沒有必要在每次循環時創建和關閉上下文。

這工作,並得到了相同的結果,你的版本(適合修正),但不能輸出你的建議,你在這個問題想:

DECLARE 
    ctx DBMS_XMLGEN.CTXHANDLE; 
BEGIN 
    ctx := DBMS_XMLGEN.NEWCONTEXT(
     'SELECT employees.EMPLOYEE_ID, employees.FIRST_NAME, 
     departments.DEPARTMENT_ID, departments.DEPARTMENT_NAME 
     FROM EMPLOYEES, departments 
     WHERE employees.department_id = departments.department_id and  
     employees.employee_id = :id'); 
    DBMS_XMLGEN.setRowTag(ctx, 'EMPLOYEE'); 
    FOR r IN (
     SELECT 198 AS employee_id FROM dual 
     UNION ALL SELECT 197 FROM dual 
     UNION ALL SELECT 180 FROM dual 
    ) LOOP 
     DBMS_XMLGEN.SETBINDVALUE(ctx, 'ID', r.employee_id); 
     INSERT INTO OFFLINE_XML (id, xml_file) 
     VALUES (r.employee_id, DBMS_XMLGEN.GETXMLTYPE(ctx)); 
    END LOOP; 
    DBMS_XMLGEN.CLOSECONTEXT(ctx); 
END; 
/

與填充表:

 ID XML_FILE 
---------- -------------------------------------------------- 
     198 <ROWSET> 
      <EMPLOYEE> 
       <EMPLOYEE_ID>198</EMPLOYEE_ID> 
       <FIRST_NAME>Bob</FIRST_NAME> 
       <DEPARTMENT_ID>1</DEPARTMENT_ID> 
       <DEPARTMENT_NAME>First</DEPARTMENT_NAME> 
      </EMPLOYEE> 
      </ROWSET> 

     197 <ROWSET> 
      <EMPLOYEE> 
       <EMPLOYEE_ID>197</EMPLOYEE_ID> 
       <FIRST_NAME>Adam</FIRST_NAME> 
       <DEPARTMENT_ID>1</DEPARTMENT_ID> 
       <DEPARTMENT_NAME>First</DEPARTMENT_NAME> 
      </EMPLOYEE> 
      </ROWSET> 

     180 <ROWSET> 
      <EMPLOYEE> 
       <EMPLOYEE_ID>180</EMPLOYEE_ID> 
       <FIRST_NAME>Charlie</FIRST_NAME> 
       <DEPARTMENT_ID>2</DEPARTMENT_ID> 
       <DEPARTMENT_NAME>Second</DEPARTMENT_NAME> 
      </EMPLOYEE> 
      </ROWSET> 
0

我認爲你不能寫FOR循環這種方式。您應該編寫一個光標來選擇員工編號,然後在FOR循環中使用光標。

declare 
    cursor cur_emp is select employee_id from employees; 
begin 
    for i in cur_emp 
    loop 
    /*your code here. Use i.employee_id to get the employee_id*/ 
    end loop; 
end; 
+0

我無法在for循環中使用遊標,因爲我正在實施已修復employee_id的過程。這些ID將被傳遞給函數,但在這裏,我正在像他的做..只是爲了測試 – 2013-04-06 14:37:31

2

聲明數組來遍歷:

DECLARE 
    CTX   DBMS_XMLGEN.CTXHANDLE; 
    LCLOB$XML_AS_CLOB CLOB; 
    type number_tab is table of number; 
    t_num number_tab := number_tab(198,197,180); 
BEGIN 
    FOR idx IN t_num.first..t_num.last 
    LOOP 
    --Create context for XML 
    CTX := 
     DBMS_XMLGEN.NEWCONTEXT (
     'SELECT employees.EMPLOYEE_ID, employees.FIRST_NAME, 
     departments.DEPARTMENT_ID, departments.DEPARTMENT_NAME 
     FROM EMPLOYEES, departments 
     WHERE employees.department_id = departments.department_id and 
     employees.employees_id =' || t_num(idx)); 
    --Get XML file of Context 
    -- Set the row header to be EMPLOYEE 
    DBMS_XMLGEN.setRowTag(CTX, 'EMPLOYEE'); 
    LCLOB$XML_AS_CLOB := DBMS_XMLGEN.GETXML (CTX); 
    DBMS_XMLGEN.CLOSECONTEXT (CTX); 
    INSERT INTO HR.OFFLINE_XML (id, XML_FILE) 
     VALUES (t_num(idx), XMLTYPE (LCLOB$XML_AS_CLOB)); 
    END LOOP; 
    COMMIT; 
END; 
/

幾個其他點。先用dbmx_xmlgen你應該使用的綁定和未剪接療法字面這裏:

employees.employees_id =' || LREC$EMPLOYEES_EMPNO); 

,你也可以在最後使用getxmltype代替getxml,救你得到一個CLOB,然後在具有XMLTYPE()插。