我需要将 XML 数据传输到 Oracle table
I need to transfer XML data into Oracle table
我正在尝试将数据从 XML 文件导入 Oracle 中的 table。我正在使用 TOAD
我也关注了以下 Oracle 论坛主题:
https://community.oracle.com/thread/2182669
XML文件如下(Example2.xml;同论坛中的站点只是改了名字):
<?xml version="1.0"?>
<ACCOUNT_HEADER_ACK>
<HEADER>
<STATUS_CODE>100</STATUS_CODE>
<STATUS_REMARKS>check</STATUS_REMARKS>
</HEADER>
<DETAILS>
<DETAIL>
<SEGMENT_NUMBER>2</SEGMENT_NUMBER>
<REMARKS>rp polytechnic</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>3</SEGMENT_NUMBER>
<REMARKS>rp polytechnic administration</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>4</SEGMENT_NUMBER>
<REMARKS>rp polytechnic finance</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>5</SEGMENT_NUMBER>
<REMARKS>rp polytechnic logistics</REMARKS>
</DETAIL>
</DETAILS>
<HEADER>
<STATUS_CODE>500</STATUS_CODE>
<STATUS_REMARKS>process exception</STATUS_REMARKS>
</HEADER>
<DETAILS>
<DETAIL>
<SEGMENT_NUMBER>20</SEGMENT_NUMBER>
<REMARKS> base polytechnic</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>30</SEGMENT_NUMBER>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>40</SEGMENT_NUMBER>
<REMARKS> base polytechnic finance</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>50</SEGMENT_NUMBER>
<REMARKS> base polytechnic logistics</REMARKS>
</DETAIL>
</DETAILS>
</ACCOUNT_HEADER_ACK>
我已经创建了要获取数据的目录和 tables:
create directory test_direc as 'C:\Documents and Settings\adeb01\Desktop'
create table xxrp_acct_details(
segment_number number,
status_code number,
status_remarks varchar2(100),
remarks varchar2(100)
);
创建 table 和目录后,我 运行 宁此:
DECLARE
acct_doc xmltype := xmltype( bfilename('test_direc','Example2.xml'), nls_charset_id('AL32UTF8') );
BEGIN
insert into xxrp_acct_details (status_code, status_remarks, segment_number, remarks)
select x.*
from xmltable(
'for $i in /ACCOUNT_HEADER_ACK/HEADER
return
for $j in $i/following-sibling::DETAILS[1]/DETAIL
return element r {$i, $j}'
passing acct_doc
columns status_code number path 'HEADER/STATUS_CODE',
status_remarks varchar2(100) path 'HEADER/STATUS_REMARKS',
segment_number number path 'DETAIL/SEGMENT_NUMBER',
remarks varchar2(100) path 'DETAIL/REMARKS'
) x
;
END;
当我 运行 这样做时,我得到的错误是:
ORA-22285: non-existent directory or file for FILEOPEN operation
ORA-06512: at "SYS.XMLTYPE", line 296
ORA-06512: at line 3
我没有明白我做错了什么。
我感觉控制文件可能是个问题,因为我没有创建任何文件。
============================================= ===========
在我之前的代码中,问题是连接没有正确建立。
我现在所做的是将整个 XML 存储到声明中的一个文件中,然后调用它。
但是我遇到以下错误:
ORA-06550:第 14 行,第 19 列:
PLS-00382: 表达式类型错误
我这样修改了我的代码:
DECLARE
v_outputfile UTL_FILE.FILE_TYPE:=UTL_FILE.FOPEN('\home\apradh01\','Example2.xml','w');
BEGIN
insert into xxrp_acct_details (status_code, status_remarks, segment_number, remarks)
select x.*
from xmltable(
'for $i in /ACCOUNT_HEADER_ACK/HEADER
return
for $j in $i/following-sibling::DETAILS[1]/DETAIL
return element r {$i, $j}'
passing XMLTYPE(v_outputfile)
columns status_code number path 'HEADER/STATUS_CODE',
status_remarks varchar2(100) path 'HEADER/STATUS_REMARKS',
segment_number number path 'DETAIL/SEGMENT_NUMBER',
remarks varchar2(100) path 'DETAIL/REMARKS'
) x
;
END;
============================================= ====
好吧,当我像下面这样修改我的代码时(即不是从文件中读取 XML 内容,我手动输入它)它工作正常:
DECLARE
BEGIN
insert into xxrp_acct_details (status_code, status_remarks, segment_number, remarks)
select x.*
from xmltable(
'for $i in /ACCOUNT_HEADER_ACK/HEADER
return
for $j in $i/following-sibling::DETAILS[1]/DETAIL
return element r {$i, $j}'
passing XMLTYPE('<?xml version="1.0"?>
<ACCOUNT_HEADER_ACK>
<HEADER>
<STATUS_CODE>100</STATUS_CODE>
<STATUS_REMARKS>check</STATUS_REMARKS>
</HEADER>
<DETAILS>
<DETAIL>
<SEGMENT_NUMBER>2</SEGMENT_NUMBER>
<REMARKS>rp polytechnic</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>3</SEGMENT_NUMBER>
<REMARKS>rp polytechnic administration</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>4</SEGMENT_NUMBER>
<REMARKS>rp polytechnic finance</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>5</SEGMENT_NUMBER>
<REMARKS>rp polytechnic logistics</REMARKS>
</DETAIL>
</DETAILS>
<HEADER>
<STATUS_CODE>500</STATUS_CODE>
<STATUS_REMARKS>process exception</STATUS_REMARKS>
</HEADER>
<DETAILS>
<DETAIL>
<SEGMENT_NUMBER>20</SEGMENT_NUMBER>
<REMARKS> base polytechnic</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>30</SEGMENT_NUMBER>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>40</SEGMENT_NUMBER>
<REMARKS> base polytechnic finance</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>50</SEGMENT_NUMBER>
<REMARKS> base polytechnic logistics</REMARKS>
</DETAIL>
</DETAILS>
</ACCOUNT_HEADER_ACK>'
)
columns status_code number path 'HEADER/STATUS_CODE',
status_remarks varchar2(100) path 'HEADER/STATUS_REMARKS',
segment_number number path 'DETAIL/SEGMENT_NUMBER',
remarks varchar2(100) path 'DETAIL/REMARKS'
) x
;
END;
所以我选择 XML 数据并将其传输到 table 的代码是正确的
现在唯一的问题是我应该如何传输文件名而不是手动输入 XML
我觉得我们可以利用 UTL_FILE 读取文件的内容,然后将其存储并与
一起传递
acct_doc xmltype := xmltype( bfilename('TEST_DIR','acct.xml'), nls_charset_id('AL32UTF8') );
任何建议...
您使用 create directory test_direc ...
创建了您的目录,这意味着您使用了一个不带引号的标识符,这很好;但这意味着它以大写的名称存储在数据字典中。如果查询 all_directories
视图为 TEST_DIREC
。因此,当您将目录名称作为字符串传递时,您需要使用该大写名称:
bfilename('TEST_DIREC','Example2.xml')
除此之外,您所展示的作品;你实际上并不需要 PL/SQL 块,你可以使用普通的 SQL 插入语句并直接在 passing
子句中提供文件:
passing xmltype( bfilename('TEST_DIREC','Example2.xml'), nls_charset_id('AL32UTF8') )
这假设您指向的目录 C:\Documents and Settings\adeb01\Desktop
位于数据库本身 运行 所在的同一台机器上,并且 Oracle 可以看到它。您只能访问服务器上的目录,而不能访问连接到它的任何客户端——这是安全模型的一部分。来自 the create directory
documentation:
A directory object specifies an alias for a directory on the server file system ...
...无论哪个帐户 运行 Oracle 数据库都必须具有访问该目录的操作系统权限,如果它在您的个人帐户下,情况可能并非如此。
如果文件当前在您的 PC 上而数据库在其他地方,您需要将文件复制到服务器 - 到 Oracle 有权访问的目录 - 并创建指向该目录的 Oracle 目录对象服务器目录。
我正在尝试将数据从 XML 文件导入 Oracle 中的 table。我正在使用 TOAD
我也关注了以下 Oracle 论坛主题: https://community.oracle.com/thread/2182669
XML文件如下(Example2.xml;同论坛中的站点只是改了名字):
<?xml version="1.0"?>
<ACCOUNT_HEADER_ACK>
<HEADER>
<STATUS_CODE>100</STATUS_CODE>
<STATUS_REMARKS>check</STATUS_REMARKS>
</HEADER>
<DETAILS>
<DETAIL>
<SEGMENT_NUMBER>2</SEGMENT_NUMBER>
<REMARKS>rp polytechnic</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>3</SEGMENT_NUMBER>
<REMARKS>rp polytechnic administration</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>4</SEGMENT_NUMBER>
<REMARKS>rp polytechnic finance</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>5</SEGMENT_NUMBER>
<REMARKS>rp polytechnic logistics</REMARKS>
</DETAIL>
</DETAILS>
<HEADER>
<STATUS_CODE>500</STATUS_CODE>
<STATUS_REMARKS>process exception</STATUS_REMARKS>
</HEADER>
<DETAILS>
<DETAIL>
<SEGMENT_NUMBER>20</SEGMENT_NUMBER>
<REMARKS> base polytechnic</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>30</SEGMENT_NUMBER>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>40</SEGMENT_NUMBER>
<REMARKS> base polytechnic finance</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>50</SEGMENT_NUMBER>
<REMARKS> base polytechnic logistics</REMARKS>
</DETAIL>
</DETAILS>
</ACCOUNT_HEADER_ACK>
我已经创建了要获取数据的目录和 tables:
create directory test_direc as 'C:\Documents and Settings\adeb01\Desktop'
create table xxrp_acct_details(
segment_number number,
status_code number,
status_remarks varchar2(100),
remarks varchar2(100)
);
创建 table 和目录后,我 运行 宁此:
DECLARE
acct_doc xmltype := xmltype( bfilename('test_direc','Example2.xml'), nls_charset_id('AL32UTF8') );
BEGIN
insert into xxrp_acct_details (status_code, status_remarks, segment_number, remarks)
select x.*
from xmltable(
'for $i in /ACCOUNT_HEADER_ACK/HEADER
return
for $j in $i/following-sibling::DETAILS[1]/DETAIL
return element r {$i, $j}'
passing acct_doc
columns status_code number path 'HEADER/STATUS_CODE',
status_remarks varchar2(100) path 'HEADER/STATUS_REMARKS',
segment_number number path 'DETAIL/SEGMENT_NUMBER',
remarks varchar2(100) path 'DETAIL/REMARKS'
) x
;
END;
当我 运行 这样做时,我得到的错误是:
ORA-22285: non-existent directory or file for FILEOPEN operation
ORA-06512: at "SYS.XMLTYPE", line 296
ORA-06512: at line 3
我没有明白我做错了什么。
我感觉控制文件可能是个问题,因为我没有创建任何文件。
============================================= ===========
在我之前的代码中,问题是连接没有正确建立。 我现在所做的是将整个 XML 存储到声明中的一个文件中,然后调用它。 但是我遇到以下错误: ORA-06550:第 14 行,第 19 列: PLS-00382: 表达式类型错误
我这样修改了我的代码:
DECLARE
v_outputfile UTL_FILE.FILE_TYPE:=UTL_FILE.FOPEN('\home\apradh01\','Example2.xml','w');
BEGIN
insert into xxrp_acct_details (status_code, status_remarks, segment_number, remarks)
select x.*
from xmltable(
'for $i in /ACCOUNT_HEADER_ACK/HEADER
return
for $j in $i/following-sibling::DETAILS[1]/DETAIL
return element r {$i, $j}'
passing XMLTYPE(v_outputfile)
columns status_code number path 'HEADER/STATUS_CODE',
status_remarks varchar2(100) path 'HEADER/STATUS_REMARKS',
segment_number number path 'DETAIL/SEGMENT_NUMBER',
remarks varchar2(100) path 'DETAIL/REMARKS'
) x
;
END;
============================================= ====
好吧,当我像下面这样修改我的代码时(即不是从文件中读取 XML 内容,我手动输入它)它工作正常:
DECLARE
BEGIN
insert into xxrp_acct_details (status_code, status_remarks, segment_number, remarks)
select x.*
from xmltable(
'for $i in /ACCOUNT_HEADER_ACK/HEADER
return
for $j in $i/following-sibling::DETAILS[1]/DETAIL
return element r {$i, $j}'
passing XMLTYPE('<?xml version="1.0"?>
<ACCOUNT_HEADER_ACK>
<HEADER>
<STATUS_CODE>100</STATUS_CODE>
<STATUS_REMARKS>check</STATUS_REMARKS>
</HEADER>
<DETAILS>
<DETAIL>
<SEGMENT_NUMBER>2</SEGMENT_NUMBER>
<REMARKS>rp polytechnic</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>3</SEGMENT_NUMBER>
<REMARKS>rp polytechnic administration</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>4</SEGMENT_NUMBER>
<REMARKS>rp polytechnic finance</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>5</SEGMENT_NUMBER>
<REMARKS>rp polytechnic logistics</REMARKS>
</DETAIL>
</DETAILS>
<HEADER>
<STATUS_CODE>500</STATUS_CODE>
<STATUS_REMARKS>process exception</STATUS_REMARKS>
</HEADER>
<DETAILS>
<DETAIL>
<SEGMENT_NUMBER>20</SEGMENT_NUMBER>
<REMARKS> base polytechnic</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>30</SEGMENT_NUMBER>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>40</SEGMENT_NUMBER>
<REMARKS> base polytechnic finance</REMARKS>
</DETAIL>
<DETAIL>
<SEGMENT_NUMBER>50</SEGMENT_NUMBER>
<REMARKS> base polytechnic logistics</REMARKS>
</DETAIL>
</DETAILS>
</ACCOUNT_HEADER_ACK>'
)
columns status_code number path 'HEADER/STATUS_CODE',
status_remarks varchar2(100) path 'HEADER/STATUS_REMARKS',
segment_number number path 'DETAIL/SEGMENT_NUMBER',
remarks varchar2(100) path 'DETAIL/REMARKS'
) x
;
END;
所以我选择 XML 数据并将其传输到 table 的代码是正确的 现在唯一的问题是我应该如何传输文件名而不是手动输入 XML
我觉得我们可以利用 UTL_FILE 读取文件的内容,然后将其存储并与
一起传递acct_doc xmltype := xmltype( bfilename('TEST_DIR','acct.xml'), nls_charset_id('AL32UTF8') );
任何建议...
您使用 create directory test_direc ...
创建了您的目录,这意味着您使用了一个不带引号的标识符,这很好;但这意味着它以大写的名称存储在数据字典中。如果查询 all_directories
视图为 TEST_DIREC
。因此,当您将目录名称作为字符串传递时,您需要使用该大写名称:
bfilename('TEST_DIREC','Example2.xml')
除此之外,您所展示的作品;你实际上并不需要 PL/SQL 块,你可以使用普通的 SQL 插入语句并直接在 passing
子句中提供文件:
passing xmltype( bfilename('TEST_DIREC','Example2.xml'), nls_charset_id('AL32UTF8') )
这假设您指向的目录 C:\Documents and Settings\adeb01\Desktop
位于数据库本身 运行 所在的同一台机器上,并且 Oracle 可以看到它。您只能访问服务器上的目录,而不能访问连接到它的任何客户端——这是安全模型的一部分。来自 the create directory
documentation:
A directory object specifies an alias for a directory on the server file system ...
...无论哪个帐户 运行 Oracle 数据库都必须具有访问该目录的操作系统权限,如果它在您的个人帐户下,情况可能并非如此。
如果文件当前在您的 PC 上而数据库在其他地方,您需要将文件复制到服务器 - 到 Oracle 有权访问的目录 - 并创建指向该目录的 Oracle 目录对象服务器目录。