3

XML からリレーショナル テーブルに値を挿入するために PL/SQL プロシージャを使用しています。XML ファイルは XMLTYPE 列にあります。
XML を含むテーブル (OFFLINE_XML) の列は、

ID, XML_FILE, STATUS

DEPARTMENT と SECTIONS という値を挿入したいテーブルが 2 つあります DEPARTMENT の構造は次のとおりです。

ID, NAME

SECTIONS テーブルの構造は次のとおりです。

ID, NAME, DEPARTMENT_ID

上記の両方のテーブルに既に存在する値を挿入したい 3 番目のテーブル (LIST_1) があります。
LIST_1 の構造は次のとおりです:-

ID, DEPARTMENT_ID,DEPARTMENT_NAME,SECTIONS_ID, SECTIONS_NAME

XML 形式は次のとおりです。

<ROWSET> 
 <DEPARTMENT>
  <DEPARTMENT_ID>DEP22681352268280797</DEPARTMENT_ID>
  <DEPARTMENT_NAME>myDEPARTMENT</DEPARTMENT_NAME>
  <SECTIONS_ID>6390135666643567</SECTIONS_ID>
  <SECTIONS_NAME>mySection</SECTIONS_NAME>
 </DEPARTMENT>
 <DEPARTMENT>
  <DEPARTMENT_ID>DEP255555555550797</DEPARTMENT_ID>
  <DEPARTMENT_NAME>myDEPARTMENT2</DEPARTMENT_NAME>
  <SECTIONS_ID>63901667779243567</SECTIONS_ID>
  <SECTIONS_NAME>mySection2</SECTIONS_NAME>
 </DEPARTMENT>
</ROWSET>


DECLARE
  BEGIN
    insert all
        into department (id, name)
           values (unit_id, unit_name)
        into sections (id, name, department _id)
          values ( sect_id, sect_name, department _id)
    select department .id as department _id
          , department.name as department_name
           , sect.id as sect_id
          , sect.name as sect_name
    from OFFLINE_XML
         , xmltable('/ROWSET/DEPARTMENT'
                   passing OFFLINE_XML.xml_file
                   columns
                      "ID"  varchar2(20) path 'UNIT_ID'
                      , "NAME"  varchar2(20) path 'UNIT_NAME'
                  ) department
          , xmltable('/ROWSET/DEPARTMENT'
               passing OFFLINE_XML.xml_file
               columns
                  "ID"  varchar2(20) path 'SECTIONS_ID'
                  , "NAME"  varchar2(20) path 'SECTIONS_NAME'
              ) sect
               where status = 3;
  EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
    dbms_output.put_line('Duplicate='|| department.id );
    --insert into LIST_1 values(ID,DEPARTMENT_ID, SECTIONS_ID, DEPARTMENT_NAME,SECTIONS_NAME);
END;

問題は、テーブル DEPARTMENT と SECTIONS に既に存在する主キーに基づいて値を挿入または識別し、その後既存の値を LIST_1 テーブルに挿入する方法です。 ------更新された取り組み --------------

私は別の解決策を思いつきましたが、これもまた問題を引き起こしています。以下の手順では、カーソルは xquery ごとに繰り返される傾向があります。私はこの問題をどのように処理するのかわかりません..

DECLARE
    department_id varchar2(20);
    department_name varchar2(20);
    sect_id varchar2(20);
    sect_name varchar2(20);
    sections_unit_id varchar2(20);
    var number;
    CURSOR C1 IS
     select
            sect.id as sect_id
          , sect.name as sect_name
          , sect.unit_id  as sections_unit_id
    from OFFLINE_XML
           , xmltable('/ROWSET/DEPARTMENT'
                   passing OFFLINE_XML.xml_file
                   columns
                      "ID"  varchar2(20) path 'UNIT_ID'
                      , "NAME"  varchar2(20) path 'UNIT_NAME'
                  ) DEPARTMENT
          , xmltable('/ROWSET/DEPARTMENT'
               passing OFFLINE_XML.xml_file
               columns
                  "ID"  varchar2(20) path 'SECTIONS_ID'
                  , "NAME"  varchar2(20) path 'SECTIONS_NAME'
                  , "DEPARTMENT_ID" varchar2(20) path 'DEPARTMENT_ID'
              ) sect
               where status = 3;

BEGIN
      FOR R_C1 IN C1 LOOP
      BEGIN
      var :=1;
         --insert into sections_temp_1 (id, name)values ( R_C1.sect_id, R_C1.sect_name);
         -- commit;
           dbms_output.put_line('Duplicate='||var);
      EXCEPTION
         WHEN DUP_VAL_ON_INDEX THEN
         dbms_output.put_line('Duplicate='||R_C1.sect_id);
      END;
      var:=var+1;
      END LOOP;

END;
4

2 に答える 2

2

XMLType フィールドから行を抽出するには、まずもう少し複雑な XQuery が必要なようです。

セクションと部門を別々に抽出して、後で突き合わせを試みる必要はありません。

このバリアントを試してください:

select 
  department_id,
  department_name,
  sections_id,
  sections_name
from 
  OFFLINE_XML xml_list,
  xmltable(
    '
      for $dept in $param/ROWSET/DEPARTMENT
        return $dept
    '
    passing xml_list.xml_file as "param"
    columns
      "DEPARTMENT_ID"   varchar2(100) path '//DEPARTMENT/DEPARTMENT_ID',
      "DEPARTMENT_NAME" varchar2(4000) path '//DEPARTMENT/DEPARTMENT_NAME',
      "SECTIONS_ID"     varchar2(100) path '//DEPARTMENT/SECTIONS_ID',
      "SECTIONS_NAME"   varchar2(4000) path '//DEPARTMENT/SECTIONS_NAME'
  ) section_list
where 
  xml_list.Status = 3

SQL フィドル - 1

その後、値が既に存在するかどうかを確認したい場合は、主キー (または必要なロジックによって異なります) で既存のテーブルに外部結合できるデータセットを取得しました。

select 
  offline_set.offline_xml_id,
  offline_set.department_id,
  offline_set.department_name,
  offline_set.sections_id,
  offline_set.sections_name,
  nvl2(dept.id,'Y', 'N') is_dept_exists, 
  nvl2(sect.id,'Y', 'N') is_sect_exists 
from 
  (  
    [... skipped text of previous query ...]
  ) offline_set,
  department dept,
  sections   sect
where
  dept.id (+) = offline_set.department_id
  and
  sect.id (+) = offline_set.sections_id

SQL フィドル - 2

この要件の背後にあるロジックについて実際には知らないため、今後の処理手順を提案することはできません。しかし、エラー/重複の原因を特定するために必要なOFFLINE_XMLテーブルへの参照を見逃したようです。LIST_1

于 2013-04-23T17:44:47.097 に答える