正在 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,您可以从物理记录 concatenate
或 continueif
到 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
,然后从y
XML表中提取各个元素.如有必要,您可以针对多个级别执行此操作,并从每个级别中提取单例和序列数据的混合,具体取决于您的 XML 结构的复杂程度。
我是 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,您可以从物理记录 concatenate
或 continueif
到 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.
文档中有一部分涉及 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
,然后从y
XML表中提取各个元素.如有必要,您可以针对多个级别执行此操作,并从每个级别中提取单例和序列数据的混合,具体取决于您的 XML 结构的复杂程度。