我需要将XML数据传输到Oracle表中

时间:2015-01-28 11:57:10

标签: xml oracle oracle11g

我正在尝试将数据从XML文件导入Oracle中的表。我正在使用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>

我已经创建了我打算获取数据的目录和表:

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)
);

创建表和目录后,我正在运行它:

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数据并将其传输到表格的代码是正确的 现在唯一的问题是我应该如何传输文件名而不是手动输入XML

我觉得我们可以利用UTL_FILE来读取文件的内容,然后存储&amp;将它传递给

acct_doc xmltype := xmltype( bfilename('TEST_DIR','acct.xml'), nls_charset_id('AL32UTF8') );

任何建议......

1 个答案:

答案 0 :(得分:1)

您使用create directory test_direc ...创建了目录,这意味着您使用了非引用的标识符,这是好的;但这意味着它存储在数据字典中,名称大写。如果您将all_directories视图查询为TEST_DIREC。因此,当您将目录名称作为字符串传递时,您需要使用该大写名称:

bfilename('TEST_DIREC','Example2.xml')

除此之外,你所展示的作品;你真的不需要PL / SQL块,你可以使用普通的SQL insert语句直接在passing子句中提供文件:

passing xmltype( bfilename('TEST_DIREC','Example2.xml'), nls_charset_id('AL32UTF8') )

这假定您指向的目录C:\Documents and Settings\adeb01\Desktop位于运行数据库本身的同一台计算机上,并且Oracle可以看到它。您只能访问服务器上的目录,而不能访问连接到它的任何客户端 - 这是安全模型的一部分。来自the create directory documentation

  

目录对象指定服务器文件系统上的目录的别名 ...

...无论运行哪个帐户,Oracle数据库都必须具有访问该目录的操作系统权限,如果它位于您的个人帐户下,则可能不是这种情况。

如果文件当前在您的PC上并且数据库位于其他位置,则需要将文件复制到服务器 - 到Oracle有权访问的目录 - 并创建指向该服务器目录的Oracle目录对象