在Oracle表数据和xml文件间相互导入导出

5 篇文章 0 订阅
在Oracle表数据和xml文件间相互导入导出 - sardden - 技术园

  

create or replace directory xml as 'e:\app\xmls';

grant read,write on directory xml to UserName;

 

Oracle表数据和xml文件间相互导入导出的PL/SQL 过程

将已知格式xml文件中的数据导入Oracle数据库、把数据库中的数据导出成xml文件的过程。
已知格式xml文件如下:

<?xml version="1.0"?>
<PEOPLE>
    
<PERSON PERSONID="E01">
        
<NAME>Tony Blair</NAME>
        
<ADDRESS>10 Downing Street, London, UK</ADDRESS>
        
<TEL>(061) 98765</TEL><FAX>(061) 98768</FAX>
        
<EMAIL>blair@everywhere.com</EMAIL>
    
</PERSON>
    
<PERSON PERSONID="E02">
        
<NAME>Bill Clinton</NAME>
        
<ADDRESS>White House, USA</ADDRESS>
        
<TEL>(001) 6400 98765</TEL><FAX>(001) 6400 98769</FAX>
        
<EMAIL>bill@everywhere.com</EMAIL>
    
</PERSON>
    
<PERSON PERSONID="E03">
        
<NAME>Tom Cruise</NAME>
        
<ADDRESS>57 Jumbo Street, New York, USA</ADDRESS>
        
<TEL>(001) 4500 67859</TEL><FAX>(001) 4500 67895</FAX>
        
<EMAIL>cruise@everywhere.com</EMAIL>
    
</PERSON>
    
<PERSON PERSONID="E04">
        
<NAME>Linda Goodman</NAME>
        
<ADDRESS>78 Crax Lane, London, UK</ADDRESS>
        
<TEL>(061) 54 56789</TEL><FAX>(061) 54 56772</FAX>
        
<EMAIL>linda@everywhere.com</EMAIL>
    
</PERSON>
</PEOPLE>


于是写出过程如下:

--建表
CREATE TABLE PEOPLE
(
   PERSONID 
VARCHAR2(10PRIMARY KEY,
   NAME 
VARCHAR2(20),
   ADDRESS 
VARCHAR2(60),
   TEL  
VARCHAR2(20),
   FAX  
VARCHAR2(20),
   EMAIL 
VARCHAR2(40)
);

--xml文件载入数据保存到数据库的过程 
create or replace procedure xml2db(xmlfile varchar2as
  p xmlparser.Parser;
  doc xmldom.DOMDocument;
  n xmldom.DOMNode;
  nl xmldom.DOMNodeList;
  
len number;
  
--根据PERSON结点生成插入SQL语句的过程 
  function insertsql(node xmldom.DOMNode) return varchar2
  
is
    n xmldom.DOMNode;
    nl xmldom.DOMNodeList;
    
len number;
    nnm xmldom.DOMNamedNodeMap;
    isql 
varchar2(200);
  
begin
    
--取得PERSON结点所有属性 
    nnm := xmldom.getAttributes(node);
    isql :
= 'insert into people values(';
    isql :
= isql || '''';
    
--取得所有属性中的第一个属性,即"PERSONID",并拼接到SQL语句中 
    isql := isql || xmldom.getNodeValue(xmldom.item(nnm,0));
    isql :
= isql || '''';
    
--取得PERSON结点下的所有结点,准备遍历 
    nl := xmldom.getChildNodes(node);
    
len := xmldom.getLength(nl);
    
for i in 0..len-1 loop
      
--取出第i个结点 
      n := xmldom.item(nl,i);
      isql :
= isql || ',';
      isql :
= isql || '''';
      
--将结点的文本值取出并拼接到SQL语句中
      isql := isql || xmldom.getNodeValue(xmldom.getFirstChild(n));
      isql :
= isql || '''';
    
end loop;
    isql :
= isql || ')';
    
return isql;
  
end insertsql;
begin
  p :
= xmlparser.newParser;
  xmlparser.parse(p,xmlfile);
  
--转换xml文件成DOM对像 
  doc := xmlparser.getDocument(p);
  xmlparser.freeParser(p);
  
--取出所有PERSON元素 
  nl := xmldom.getElementsByTagName(doc,'PERSON');
  
len := xmldom.getLength(nl);
  
--清空people表的内容 
  delete from people;
  
for i in 0..len-1 loop
    
--取出第iPERSON元素 
    n := xmldom.item(nl,i);
    
--执行插入该PERSON元素所用的SQL语句 
    execute immediate insertsql(n);
  
end loop;
  
commit;
  xmldom.freeDocument(doc);
end xml2db;
/

--将数据库中的数据导出成xml文件的过程 
create or replace procedure db2xml(xmlfile varchar2as
  doc xmldom.DOMDocument;
  ret xmldom.DOMNode;
  peoplenode xmldom.DOMNode;
  
--遍历整个people表的游标 
  Cursor cur_people is select * from people;
  
--people表中一行记录转换为元素
  --并插入到DOM文档对像根结点PEOPLE下的过程 
  procedure addperson(doc xmldom.DOMDocument,people xmldom.DOMNode,
                      v_pid 
varchar2,v_name varchar2,v_addr varchar2,
                      v_tel 
varchar2,v_fax varchar2,v_email varchar2)
  
is
    personelem xmldom.DOMElement;
    personnode xmldom.DOMNode;
    itemelem xmldom.DOMElement;
    itemnode xmldom.DOMNode;
    
text xmldom.DOMText;
  
begin
    
--创建PERSON结点 
    personelem := xmldom.createElement(doc,'PERSON');
    
--设置PERSONID属性 
    xmldom.setAttribute(personelem,'PERSONID',v_pid);
    personnode :
= xmldom.appendChild(peoplenode,xmldom.makeNode(personelem));
    
--PERSON结点中添加NAME元素
    itemelem := xmldom.createElement(doc,'NAME');
    
--  NAME结点添加到PERSON结点中
    itemnode := xmldom.appendChild(personnode,xmldom.makeNode(itemelem));
    
--  创建文本结点
    text := xmldom.createTextNode(doc,v_name);
    
--  将文本结点添加到NAME结点下,以构成完整NAME元素
    itemnode := xmldom.appendChild(itemnode,xmldom.makeNode(text));
    
--PERSON结点中添加ADDRESS元素
    itemelem := xmldom.createElement(doc,'ADDRESS');
    itemnode :
= xmldom.appendChild(personnode,xmldom.makeNode(itemelem));
    
text := xmldom.createTextNode(doc,v_addr);
    itemnode :
= xmldom.appendChild(itemnode,xmldom.makeNode(text));
    
--PERSON结点中添加TEL元素
    itemelem := xmldom.createElement(doc,'TEL');
    itemnode :
= xmldom.appendChild(personnode,xmldom.makeNode(itemelem));
    
text := xmldom.createTextNode(doc,v_tel);
    itemnode :
= xmldom.appendChild(itemnode,xmldom.makeNode(text));
    
--PERSON结点中添加FAX元素
    itemelem := xmldom.createElement(doc,'FAX');
    itemnode :
= xmldom.appendChild(personnode,xmldom.makeNode(itemelem));
    
text := xmldom.createTextNode(doc,v_fax);
    itemnode :
= xmldom.appendChild(itemnode,xmldom.makeNode(text));
    
--PERSON结点中添加EMAIL元素
    itemelem := xmldom.createElement(doc,'EMAIL');
    itemnode :
= xmldom.appendChild(personnode,xmldom.makeNode(itemelem));
    
text := xmldom.createTextNode(doc,v_email);
    itemnode :
= xmldom.appendChild(itemnode,xmldom.makeNode(text));
  
end addperson;
begin
  
--创建一个新DOM文档对像 
  doc := xmldom.newDOMDocument;
  
--为文档添加根结点PEOPLE
  peoplenode := xmldom.makeNode(xmldom.createElement(doc,'PEOPLE'));
  ret :
= xmldom.appendChild(xmldom.makeNode(doc),peoplenode);
  
--使用游标遍历people中的每行,生成每一行对应的PERSON元素并添加到PEOPLE根结点中
  for v_row in cur_people loop
    addperson(doc,peoplenode,v_row.personid,v_row.name,
              v_row.address,v_row.tel,v_row.fax,v_row.email);
  
end loop;
  
--将结果写入指定文件 
  xmldom.writeToFile(doc,xmlfile);
  xmldom.freeDocument(doc);
end db2xml;
/

 

exec xml2db('XML'||'\'||'asd.xml');

exec db2xml('XML'||'\'||'asd2.xml');    // 运行上述编译的程序。

 

 

 

使用存储过程将数据以XML格式导出到XML文件

文章分类:数据库

最近看到有网上有很多人问怎么把数据导出到XML文件,大多的解决方法就是dbms_xmlgen+utl_file,首先要说的是,这种方法确实不错,但是有些缺点。如果系统中需要把数据导出XML文件,通常数据量都比较大,因此,对于大数据量的导出,UTL_FILE就显得比较苍白了。而且DBMS_XMLGEN获得数据本身就是有格式的,因此UTL_FILEINSTR 就显得有些多余了。但是,我还要把这个方法记录下来,另外,还有一个是使用DBMS_XSLPROCESSOR包的方法。

一、准备工作

      准备数据:

      CREATE TABLE xml_table(ID VARCHAR2(20),

                                             OBJECT_VALUE VARCHAR2(200));

      导入数据:      

       BEGIN

       FOR i IN 1 .. 100000 LOOP

            INSERT INTO xml_table VALUES (i,'blog.csdn.net/zhangchu_63');

       END LOOP;

       COMMIT;

       END;

       /

      通过上面的操作,我们已经建立了一张名叫xml_table的表,并向里面插入了100000条数据。大家知道XML文件是导出到OS的,因此,需要在ORACLE中为文件创建一个路径:

      CREATE OR REPLACE DIRECTORY D_OUTPUT AS 'D:\TEMP';

     下面是我们就要开始。

二、开始干活

      1dbms_xmlgen+utl_file方式

     create or replace procedure xml_output is
        /**
          
本存储过程使用dbms_xmlgen+utl_file两个包来完成数据导出到XML
        */

       xml_ctx dbms_xmlgen.ctxType;
       v_file utl_file.file_type;
       xml_txt varchar2(4000);
       line varchar2(500);
       begin

        xml_ctx := dbms_xmlgen.newContext('select * from xml_table order by id');
       dbms_xmlgen.setRowSetTag(xml_ctx,'DBMS');
       dbms_xmlgen.setRowTag(xml_ctx,'XML_TABLE');
       xml_txt := dbms_xmlgen.getXML(xml_ctx);

       v_file := utl_file.fopen('XML_OUTPUT','test.xml','w');
       loop
  
         line := substr(xml_txt,1,instr(xml_txt,chr(10))-1);
         utl_file.put_line(v_file,line); 
         exit when instr(line,'</DBMS>')>0;
         xml_txt := substr(xml_txt,instr(xml_txt,chr(10))+1);
       end loop;
 

       dbms_xmlgen.closeContext(xml_ctx);
       utl_file.fclose(v_file);
    end xml_output ;

      上面就是使用dbms_xmlgen+utl_file方式导出XML的,我的存储过程是没有参数的,如果大家需要可以自己加。

  

     2dbms_xmlgen+DBMS_XSLPROCESSOR方式

     create or replace procedure xml_print is
        /**
         
本存储过程使用dbms_xmlgen+DBMS_XSLPROCESSOR两个包

         来完成数据导出到XML
       */

       xml_ctx dbms_xmlgen.ctxType;
       xml_txt clob;
     begin

       xml_ctx := dbms_xmlgen.newContext('select * from xml_table

                         order by id');

      dbms_xmlgen.setRowSetTag(xml_ctx,'DBMS');
      dbms_xmlgen.setRowTag(xml_ctx,'XML_TABLE');
      xml_txt := to_clob(dbms_xmlgen.getXML(xml_ctx));
      DBMS_XSLPROCESSOR.clob2file

                                  (xml_txt,'XML_OUTPUT','test.xml');

      dbms_xmlgen.closeContext(xml_ctx);

     

     end xml_print;

     这个好处就是它不管xml_txt的格式,直接把所有数据写入test.xml中。

三、方法比较

     dbms_xmlgen+utl_file方式:导出100000条数据,2分钟没导完,我没耐心等了。dbms_xmlgen+DBMS_XSLPROCESSOR方式:导出100000条数据用了10秒钟。

四、总结

     看了上面我写的过程和比较,不用我说,大家也都知道怎么选了吧。在这里我还是要说,没有最好的办法,只有最合适的办法,根据具体问题具体对待。

      注:我上面的过程是为了简便,所以没有注释,没有EXCEPTION,希望大家别学我,要养成良好的书写习惯。

          为了方便大家学习,我把dbms_xslprocessor中用到的过程描述贴出来,供大家参考:

 

CLOB2FILE Procedure

This procedure writes content of a CLOB into a file.

Syntax

DBMS_XSLPROCESSOR.CLOB2FILE(
  cl          IN  CLOB;
  flocation   IN  VARCHAR2,
  fname       IN  VARCHAR2,
  csid        IN  NUMBER:=0);

 

Parameter

Description

CLOB

File directory

flocation

File directory

fname

File name

csid

Character set id of the file

·         Must be a valid Oracle id; otherwise returns an error

·         If 0 , content of the output file will be in the database character set

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值