在Oracle DB中导入XML数据(ORACLE_LOADER)

时间:2015-08-12 08:58:05

标签: xml oracle loader

我是DBAdministration的新成员,我被要求从大(8Gb)xml文件开始设计db结构。

我正在测试将数据从XML导入到表中,但我不能在一次填充多个字段。对于其他人,我得到空结果。

这里是代码:

CREATE TABLE test
(d_name     CHAR(100),
 f_name     CHAR(100),
 w       CHAR(100))

ORGANIZATION EXTERNAL
  (TYPE ORACLE_LOADER
  DEFAULT DIRECTORY DIR
 ACCESS PARAMETERS
    (
   RECORDS DELIMITED BY NEWLINE 
   NOBADFILE NODISCARDFILE NOLOGFILE
   FIELDS MISSING FIELD VALUES ARE NULL        


   REJECT ROWS WITH ALL NULL FIELDS
            (
            d_name      CHAR(100) ENCLOSED BY '<d_name>' AND '</d_name>',
            f_name         CHAR(100) ENCLOSED BY '<f_name>' AND '</f_name>',
            w      CHAR(100) ENCLOSED BY '<w>' AND '</w>'
            )
    )
  LOCATION ('xmlFILE.xml')
 )
   reject limit unlimited;

我得到的是:

d_name|f_name|w
John|null|null
Peter|null|null

有人可以帮我理解错误在哪里吗?

非常感谢!

修改 XML以这样的方式开始:

<REC r_id_disclaimer="">
<UID>yyyyyyyyy</UID>
<static_data>
<summary>
<EWUID>
<WUID coll_id="WOS"/>
<edition value="WOS.AHCI"/>
</EWUID>
<pub_info coverdate="DEC 7 2014" has_abstract="N" issue="49" pubmonth="DEC 7" pubtype="Journal" pubyear="2014" sortdate="2014-12-07" special_issue="SI" vol="119">
<page begin="59" end="59" page_count="1">59-59</page>
</pub_info>
<titles count="1">
<title type="source">Title</title>
</titles>
<names count="2">
<name role="author" seq_no="1">
<d_name>John</d_name>
<f_name>John, RICHARD </f_name>
<w>jOHN, MI</w>
</name>
<name role="author" seq_no="2">
<d_name>Peter</d_name>
<f_name>Peter, RICHARD </f_name>
<w>Pet, MI</w>
</name>
</names>

1 个答案:

答案 0 :(得分:0)

由于换行符,这些字段位于不同的物理记录中。使用SQL * Loader,您可以concatenatecontinueif从物理记录中汇编逻辑记录,但我不认为外部表驱动程序支持这一点。或直接加载XMLType。

您可以通过CLOB字段加载它。在同一个DIR目录中创建一个数据文件,其中包含真正的XML文件名:说xmlfiles.txt只包含值xmlFILE.xml(但可能有多行,每行都指一个不同的XML文件)。然后你的外部表将是:

create table test (xml_clob clob)
organization external
(
  type oracle_loader
  default directory dir
  access parameters
  (
    records delimited by newline
    nobadfile nodiscardfile nologfile
    fields missing field values are null        
    reject rows with all null fields
    (
      xml_filename char(80)
    )
    column transforms (xml_clob from lobfile (xml_filename) from (dir) clob)
  )
  location ('xmlfiles.txt')
)
reject limit unlimited;

请注意,location现在是包含真实文件名称的新文件;并且the column transforms clause正在使用真实文件名 - 来自从新文件中提取的xml_filename来实际加载CLOB数据。您无法在加载程序数据文件中直接拥有CLOB,它必须位于引用的单独文件中。

test表现在将该XML文件存储为CLOB,您可以将其转换为XMLType来操作它,例如作为an XMLTable clause的一部分:

select x.*
from test t
cross join xmltable('/REC/static_data/summary/names/name'
  passing xmltype(t.xml_clob)
  columns d_name varchar2(20) path 'd_name',
    f_name varchar2(20) path 'f_name',
    w varchar2(20) path 'w'
) x;

D_NAME               F_NAME               W                  
-------------------- -------------------- --------------------
John                 John, RICHARD        jOHN, MI            
Peter                Peter, RICHARD       Pet, MI             

xmltype(t.xml_clob)正在进行转换,因此XPath应用于由表中的CLOB值组成的XML文档。

文档的一部分涉及loading XML content。如果以XML格式将其导入数据库,则可以对其进行操作以创建关系数据。

使用您在上一个问题中尝试过的机制,并重复该答案的部分部分,您可以使用XMLType列创建登台表并从bfile加载:

create table test (xml_file xmltype)
xmltype xml_file store as securefile binary xml;

insert into test (xml_file) 
select xmltype(bfilename('DIR', 'xmlFILE.xml'), nls_charset_id('WE8ISO8859P1'))
from dual;

然后,您可以再次使用XMLTable子句以关系形式获取数据:

select x.*
from test t
cross join xmltable('/REC/static_data/summary/names/name'
  passing t.xml_file 
  columns seq_no number path '@seq_no',
    d_name varchar2(20) path 'd_name',
    f_name varchar2(20) path 'f_name',
    w varchar2(20) path 'w'
) x;

    SEQ_NO D_NAME               F_NAME               W                  
---------- -------------------- -------------------- --------------------
         1 John                 John, RICHARD        jOHN, MI            
         2 Peter                Peter, RICHARD       Pet, MI             

我已经包含seq_no只是为了展示如何获取属性值。

XPath必须匹配您的真实文件;我添加了summary,static_data和REC的结束标记以使其有效,但是如果你还有一个封闭的records级别(如前一个问题所示),那么你需要在XPath中包含它,并指定命名空间:

...
cross join xmltable(xmlnamespaces(default 'http://xxxxxxxxxxxxxx'),
  '/records/REC/static_data/summary/names/name'
  passing t.xml_file
...

如果您想从两个级别获取数据,可以按照注释中的说明将其拉出,但如果有任何子节点重复则不能;在这里,每个REC都有多个名称,因此您获得ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence。您可以使用FLWOR语法去创建组合数据的新元素,但是提取names节点并将其传递给第二个XMLTable可能更简单:

select x.cd_uid, y.*
from test t
cross join xmltable(xmlnamespaces(default 'http://xxxxxxxxxxxxxx'),
  '/records/REC'
  passing t.xml_file 
  columns cd_uid varchar2(10) path 'UID',
    names xmltype path 'static_data/summary/names'
) x
cross join xmltable(xmlnamespaces(default 'http://xxxxxxxxxxxxxx'),
  'names/name'
  passing x.names 
  columns seq_no number path '@seq_no',
    d_name varchar2(20) path 'd_name',
    f_name varchar2(20) path 'f_name',
    w varchar2(20) path 'w'
) y;

CD_UID         SEQ_NO D_NAME               F_NAME               W                  
---------- ---------- -------------------- -------------------- --------------------
yyyyyyyyy           1 John                 John, RICHARD        jOHN, MI            
yyyyyyyyy           2 Peter                Peter, RICHARD       Pet, MI             

names子XML提取为x.names,然后将各个元素从y XMLTable中拉出。如果需要,您可以为多个级别执行此操作,并根据XML结构的复杂程度从每个级别中提取单个和序列数据的混合。