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

importing XML data in Oracle DB (ORACLE_LOADER)

我是 DBAdministration 的新手,有人要求我从大 (8Gb) xml 文件开始设计数据库结构。

我正在测试将数据从 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>

由于换行,这些字段位于不同的物理记录中。使用 SQL*Loader,您可以从物理记录 concatenatecontinueif 到 assemble 逻辑记录,但我认为外部 table 驱动程序不支持。或者加载XML直接输入

您可以通过 CLOB 字段加载它。在相同的 DIR 目录中创建一个数据文件,其中包含真正的 XML 文件名:比如 xmlfiles.txt 仅包含值 xmlFILE.xml (但可以有多行,每个都引用不同的 XML 文件)。那么你的外部 table 将是:

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 table 现在将 XML 文件存储为 CLOB,您可以将其转换为 XML 类型以对其进行操作,例如作为 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 应用于由 table.

中的 CLOB 值形成的 XML 文档

文档中有一部分涉及 loading XML content。如果您将它作为 XML 放入数据库,那么您可以操纵它来创建关系数据。

使用您在上一个问题中尝试过的机制,并重复该答案的 某些 部分,您可以使用 XML 创建暂存 table键入列并从 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 必须与您的真实文件匹配;我为摘要添加了结束标记,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,然后从yXML表中提取各个元素.如有必要,您可以针对多个级别执行此操作,并从每个级别中提取单例和序列数据的混合,具体取决于您的 XML 结构的复杂程度。