我是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>
答案 0 :(得分:0)
由于换行符,这些字段位于不同的物理记录中。使用SQL * Loader,您可以concatenate
或continueif
从物理记录中汇编逻辑记录,但我不认为外部表驱动程序支持这一点。或直接加载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结构的复杂程度从每个级别中提取单个和序列数据的混合。