2013-04-22 9 views
3

我正在使用PL/SQL過程將值從XML插入到關係表中。 XML文件位於XMLTYPE列中。包含XML表格的
列(OFFLINE_XML)是
將PL/SQL XML解析到關係表中

ID, XML_FILE, STATUS 

有兩個表中,我要插入值IE部門和節部 結構如下: -

ID, NAME 
SECTIONS表

結構是: -

ID, NAME, DEPARTMENT_ID 

現在有第三個表(LIST_1)在WHI我想插入上面提到的表中已經存在的值。 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; 

回答

2

看起來首先你需要一點點複雜的XQuery來從XMLType字段中提取行。

有沒有必要分開提取部門和部門,然後嘗試匹配回來。

試試這個變種:

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 fiddle - 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 fiddle - 2

因爲我實際上並不瞭解這個要求背後的邏輯,所以我不能建議任何未來的處理指令。但是,您似乎錯過了OFFLINE_XMLLIST_1中的表格,它需要識別錯誤/重複的來源。

0

要做到這一點是與Oracle內置的錯誤記錄的最好方法。使用DBMS_ERRLOG.CREATE_ERROR_LOG()爲每個目標表(即您的案例中的SECTION和DEPARTMENT)生成的日誌表。 Find out more

使用這些表的INSERT所有的語法並不直觀,但是這是做什麼:

insert all 
    into department (id, name) 
     values (unit_id, unit_name) 
     log errors into err$_department ('XML Load failure') 
    into sections (id, name, department_id) 
     values (sect_id, sect_name, department_id) 
     log errors into err$_section ('XML Load failure') 
select department.id as department_id 
     .... 

你可以把任何(短ISH)串入錯誤日誌標籤,但要確保它的這將有助於你在當地的相關記錄。您可能希望將REJECT LIMIT設置爲某個值,具體取決於您是否希望在一個(或幾個)錯誤上失敗,或者處理整個XML並在之後進行整理。 Find out more


我建議你使用單獨的日誌中爲每個目標表,而一個日誌都出於兩個原因:

  1. 在我豁達的解決方案,利用Oracle內置feartures往往會變得更好和更比手寫代碼更健壯。
  2. 這更適合可能發生的事情。您有三種情況可能導致裝載投擲DUP_VAL_ON_INDEX:
    • 記錄有重複的部門ID
    • 記錄有重複的部分ID
    • 記錄有重複的部門ID 重複的部分ID

單獨的表格可以更容易地理解錯誤發生了什麼。加載大量數據時,這是一個很大的好處。

「我需要告訴我的用戶,這多少重複的條目都是在XML中找到 」

你仍然可以做到這一點有兩個錯誤日誌。哎呀,你甚至可以將錯誤日誌加入名爲LIST_1的視圖,這對你來說非常重要。

+0

我想知道這將如何幫助我將已存在的DEPARTMENT和SECTIONS表中的值插入到LIST_1表中? – 2013-04-23 14:31:53

+0

我假設您在這些表上定義了主鍵:在這種情況下,LOG ERROR INTO將通過將重複記錄寫入日誌表來處理唯一鍵違規。 – APC 2013-04-23 14:53:54

+0

也就是說,對每個目標表使用單獨的日誌,而對兩者都使用單獨的日誌。 – APC 2013-04-23 15:06:16