3

XML をテーブルに保存しようとしています。XML の形式は次のとおりです。

<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:
4

3 に答える 3

2

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 の配列を好みますが、今のところこれに固執します)。カーソルを宣言する必要はありませんnumber。その名前で宣言した変数は、このバージョンに置き換えられます。また、返される値の 1 つを参照するときは、名前で指定する必要があるため、この場合はLREC$EMPLOYEES_EMPNO.employee_id. 個人的にはもっと短い名前にしたい *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>
于 2013-04-06T16:40:42.340 に答える
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() を実行する必要をなくすこともできます。

于 2013-04-06T16:07:42.800 に答える
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;
于 2013-04-06T14:02:20.680 に答える