暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 解析XML以加载到父表和子表

askTom 2015-09-21
303

问题描述

我有一个问题,是关于从XML文件开始将3个表放在关系中的代码。

这3个表分别是组织、出版和事实表,使它们相互关系。

表下的结构如下:
PUBLICATION
------------
CD_PUB (primary key, progressive number automatically generated when a new record has been inserted, thus the value is not taken from the XML file)
CD_REC 

ORGANISATION
------------
CD_ORG (primary key, progressive number automatically generated when a new record has been inserted, thus the value is not taken from the XML file)

FT_PUB_ORG
------------
CD_FT (primary key, progressive number automatically generated when a new record has been inserted, thus the value is not taken from the XML file)
CD_PUB (I want to insert here the related code of the Publication)
CD_ORG (I want to insert here the related code of the Organisation)


我使用的代码是:
BEGIN
  FOR i IN 1..10 LOOP



 INSERT INTO WOS_DM_PUBLICATION (
                                CD_UID 
                              , DT_COVERDATE 
                              , FL_HAS_ABSTRACT 
                              , QT_ISSUE 
                              , DT_PUBMONTH 
                              , CD_PUBTYPE 
                              , DT_PUBYEAR 
                              , DT_SORTDATE 
                              , QT_VOL 
                              , CD_PAGE_BEGIN 
                              , CD_PAGE_END 
                              , CD_PAGE 
                              , QT_PAGE_COUNT 
                              , QT_TITLE_COUNT 
                              , LB_TITLE_SOURCE 
                              , LB_TITLE_SERIES 
                              , LB_TITLE_SOURCE_ABBREV 
                              , LB_TITLE_ABBREV_ISO 
                              , LB_TITLE_ABBREV_11 
                              , LB_TITLE_ABBREV_29 
                              , LB_TITLE_ITEM                
                              , LB_TITLE_BOOK_SERIES 
                              , CD_ACCESSION_NO 
                              , CD_LANG_TYPE 
                              , CD_LANG_NORM 
                              , CD_IDS 
                              , FL_IDS_AVAIL 
                              , CD_BIB_ID 
                              , CD_BIB_PAGECOUNT                                 
                            )


                   select 
                             RecUid.cd_uid
                           , PubInfo.*
                           , Titles.*
                           , Title.*
                           , Acc_no.*
                           , Lang.*
                           , Lang2.*
                           , Items.*

                    from testtable2 t
            cross join  xmltable(xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
                     'records/REC'
                      passing t.xml_file 
                      columns 
                   CD_UID varchar2(200) path 'UID',
                          names xmltype path 'static_data/summary',
                       identifi xmltype path 'dynamic_data/cluster_related',
                           lang xmltype path 'static_data/fullrecord_metadata',
                           item xmltype path 'static_data/item'
                        ) RecUid

                 cross join  xmltable(xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
                     'summary/pub_info'
                      passing RecUid.names
                      columns                           
                           DT_COVERDATE varchar2(20) path '@coverdate',
                        FL_HAS_ABSTRACT varchar2(20) path '@has_abstract',
                               QT_ISSUE varchar2(20) path '@issue',
                            DT_PUBMONTH varchar2(20) path '@pubmonth',
                             CD_PUBTYPE varchar2(20) path '@pubtype',
                             DT_PUBYEAR varchar2(20) path '@pubyear',
                            DT_SORTDATE varchar2(20) path '@sortdate',
                                 QT_VOL varchar2(20) path '@vol',
                          CD_PAGE_BEGIN varchar2(20) path 'page/@begin',
                            CD_PAGE_END varchar2(20) path 'page/@end',
                                CD_PAGE varchar2(20) path 'page',
                          CD_PAGE_COUNT varchar2(20) path 'page/@page_count'    
                        ) PubInfo

                cross join  xmltable(xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
                     'summary/titles'
                       passing RecUid.names
                      columns     
                         QT_TITLE_COUNT varchar2(20) path '@count'
                       ) Titles

                cross join  xmltable(xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
                     'summary/titles'
                       passing RecUid.names
                      columns                                 
             LB_TITLE_SOURCE varchar2(200) path 'title[@type="source"]',
             LB_TITLE_SERIES varchar2(200) path 'title[@type="series"]',
      LB_TITLE_SOURCE_ABBREV varchar2(200) path 'title[@type="source_abbrev"]',
         LB_TITLE_ABBREV_ISO varchar2(200) path 'title[@type="abbrev_iso"]',
          LB_TITLE_ABBREV_11 varchar2(200) path 'title[@type="abbrev_11"]',
          LB_TITLE_ABBREV_29 varchar2(200) path 'title[@type="abbrev_29"]',
               LB_TITLE_ITEM varchar2(200) path 'title[@type="item"]',
        LB_TITLE_BOOK_SERIES varchar2(200) path 'title[@type="book_series"]'
                       ) Title

                cross join  xmltable( xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
                     'cluster_related/identifiers/identifier[@type="accession_no"]'
                      passing RecUid.identifi
                      columns 
                         CD_ACCESSION_NO varchar2(200) path '@value'
                        )   Acc_no   

            cross join  xmltable(xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
                     'fullrecord_metadata/languages/language[@type="primary"]'
                      passing RecUid.lang
                      columns 
                         CD_LANG_TYPE varchar2(200) path '.'
                         --CD_LANG_NORM varchar2(200) path 'normalized_languages/language'
                        )   Lang

            cross join  xmltable(xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
           'fullrecord_metadata/normalized_languages/language[@type="primary"]'
                      passing RecUid.lang
                      columns 
                         CD_LANG_NORM varchar2(200) path '.'
                        )   Lang2

           cross join  xmltable(xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
                     'item'
                      passing RecUid.item
                      columns 
                              CD_IDS VARCHAR(200) path 'ids',
                        FL_IDS_AVAIL VARCHAR(2)   path 'ids/@avail',
                           CD_BIB_ID VARCHAR(50)  path 'bib_id',
                    CD_BIB_PAGECOUNT VARCHAR(25)  path 'bib_pagecount'

                      )   Items  ;

      INSERT     INTO  WOS_DM_ORGANISATION (
                                      LB_LEGAL_NAME 
                                    ,   CD_ADD_NO 
                                    ,   LB_FULL_ADDRESS 
                                    ,   CD_CITY 
                                    ,   CD_STATE 
                                    ,   CD_COUNTRY_NAME 
                         --           , CD_POSTAL_CODE 
                                    ,   CD_ZIP_LOCATION 
                                    , FL_PARENT
                                       )

                          select                              
                                    Organis.* 
                                 ,  'Y' FL_PARENT 

                          from testtable2 t
            cross join  xmltable(xmlnamespaces(default 'xxxxxxxxxxxxxxxx'),
            'records/REC/static_data/fullrecord_metadata/addresses/address_name'
                            passing t.xml_file 
                            columns 

     LB_LEGAL_NAME varchar2(200) path 'address_spec/organizations/organization',
         CD_ADD_NO varchar2(200) path 'address_spec/@addr_no',
   LB_FULL_ADDRESS varchar2(200) path 'address_spec/full_address',
           CD_CITY varchar2(200) path 'address_spec/city',
          CD_STATE varchar2(200) path 'address_spec/state',  
     _COUNTRY_NAME varchar2(200) path 'address_spec/country',
 -- CD_POSTAL_CODE varchar2(200) path 'address_spec/zip/.'--,
   CD_ZIP_LOCAZION varchar2(200) path 'address_spec/@location'
                               )   Organis ;
  INSERT INTO FT_PUB_ORG_TEST

                (  
                   CD_PUB_ID ,
                   CD_ORG_ID )
                VALUES
                (

                WOS_DM_PUBLICATION_id_seq.currval,
                WOS_DM_ORGANISATION_id_seq.currval);

  x := x + 1;
END LOOP;
   COMMIT;
     END;                  



插入到WOS_DM_PURLICA中,使用触发器和WOS_DM_PURLICA_id_seq序列插入n行,主键为CD_PURL_ID。类似地,在WOS_DM_NOMISING中插入时,使用触发器和WOS_DM_OMBSING_id序列正好插入了n行,主键为CD_ORG_ID。在两个插入操作运行之后,对于介于1和n之间的i ,我希望使用前面两个插入语句中的第i个键的主键,将一行插入FT_ . . . . . . . . . . . . . . . . . . . . . . . . . .

问题是,对于这个代码,我在FT表中只得到了最终的值,但我需要所有的关系。我已经尝试使用INSERTALL语句,但它似乎不能将SELECT作为值使用。

请考虑到循环只是一个尝试,但它不工作,因为我需要。

专家解答

如果XML包含的内容足以构成父表的*自然*键,那么我建议将父记录加载到临时表中。例如,


  
     
     
       
     
  
     etc


然后从XML中提取,并加载到父GTT中:

PK                    NATURAL_KEY
parent_seq.nextval    A
parent_seq.nextval    B


然后,在加载这个(或多个)表时,您将连接到父自然键上的这个临时表,以获得前面分配的父序列值。

如果在父XML中没有可以称为自然键的内容,也就是说,您实际上只有XML本身的层次结构,那么解决方法可以是将数据拖入PL/SQL数组并从该数组中工作。从逻辑上讲,这将是:

declare
   type parent_array is table of parent%rowtype index by pls_integer;
   type child_array is table of child%rowtype index by pls_integer;
   
   p parent_array;
   c child_array;
begin
  for i in ( [your large query producing ALL data, see below] )
  loop
    if i.is_first_parent = 'Y' then
       if p.count > 10000 then
         forall x in 1 .. p.count 
           insert into PARENT values p(x);
 
         forall x in 1 .. c.count 
           insert into CHILD values c(x);

         p.delete;
         c.delete;
       end if;

       p(p.count+1).pk := parent_seq.nextval;
       p(p.count).col1 := i.parent_col1;
       p(p.count).col2 := i.parent_col2;
    end if;
    
    c(c.count+1).pk := child_seq.nextval;
    c(c.count).col1 := i.child_col1;
    c(c.count).col2 := i.child_col2;
    c(c.count).parent_fk := p(p.count).pk;   -- the link
 end loop;
end;


where your large query is a flattening of the XML, so the data looks like:


PARENT         CHILD       IS_FIRST_PARENT
parent1        child1      Y
parent1        child2   
parent1        child3
parent2        child1      Y
parent2        child2
etc


希望这个能帮上忙
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论