我需要将 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 目录对象服务器目录。