Oracle 关系型数据与XML数据之间的转化

 

  CREATE TABLE SCOTT.EMP
   (       EMPNONUMBER(4,0),
       ENAME VARCHAR2(10),
       JOB VARCHAR2(9),
       MGR NUMBER(4,0),
       HIREDATE DATE,
       SAL NUMBER(7,2),
       COMM NUMBER(7,2),
       DEPTNO NUMBER(2,0),
        CONSTRAINT PK_EMP PRIMARY KEY (EMPNO)

)

 

 

主要内容:将关系型结构化数据转化为XML文件

 

一、对象转化为XML文件

 

建立一个对象

CREATE OR REPLACE TYPE address_type AS OBJECT ( 

address_line1 VARCHAR2(100), 

address_line2 VARCHAR2(100), 

address_line3 VARCHAR2(100) );

 

declare
  v_addr address_type;
  v_xml xmltype;
begin
  -- 建立一个对象实例
  v_addr := address_type('n1', 'n2', 'n3');
  --将对象实例转化为xml
  v_xml := xmltype(v_addr);
  -- 显示 xml 输出
 dbms_output.put_line(v_xml.getstringval());
end;

 

输出结果:

<ADDRESS_TYPE>

    <ADDRESS_LINE1>n1</ADDRESS_LINE1>

    <ADDRESS_LINE2>n2</ADDRESS_LINE2>

    <ADDRESS_LINE3>n3</ADDRESS_LINE3>

</ADDRESS_TYPE>

 

xmltype 将数据转化为XML的一个结点;

xmltype也是数据表的一种数据类型,如同varchar2数据类型一样。

getstringval()将一个xml结点或者xml数据类型类型转化为varchar2类型;

其它的转化函数还有

getCLOBVal()

getStringVal()

getNumberVal()

getBLOBVal(csid)

 

上述匿名过程告诉我们一个方法,可以将关系型数据转化为集合,然后就可以转化为XML文件。

实际上oracle提供了较多的函数,方便我们的转化工作。

 

xmlelement

将一个普通查询(非层次查询)的结果,转化为XML

select
xmlelement("name", ename).getstringval()
from scott.emp

 

1、 将一个字段转化为XML的一个节点

 

XMLELEMENT("NAME",ENAME)

-----------------------------

<name>SMITH</name>

<name>ALLEN</name>

<name>WARD</name>

<name>JONES</name>

<name>MARTIN</name>

……

xmlattributes

增加属性

SELECT
XMLElement("Deptno",
   XMLATTRIBUTES(deptno AS dept_id),
   XMLElement("Name", ename),
   XMLElement("Date", hiredate)
). getstringval()
FROM scott.emp

 

<Deptno DEPT_ID="20"><Name>SMITH</Name><Date>1980-12-17</Date></Deptno>

<DeptnoDEPT_ID="30"><Name>ALLEN</Name><Date>1981-02-20</Date></Deptno>

<DeptnoDEPT_ID="30"><Name>WARD</Name><Date>1981-02-22</Date></Deptno>

<DeptnoDEPT_ID="20"><Name>JONES</Name><Date>1981-04-02</Date></Deptno>

……

但是上述XML节点不符合规范,不过没有关系,这个函数只是提供了一个转化方法

 

xmlforest

如果以已有的字段名称作为元素名称转化为XML文件

 

select xmlelement(

"emp",
xmlattributes(e.ename
as "name"),
xmlforest(e.hiredate, e.deptno
as "department_id")

).getstringval()
as "result"
from scott.emp e where e.deptno = 20;

 

         <Emp name="SMITH">

                   <HIREDATE>1980-12-17</HIREDATE>

                   <department_id>20</department_id>

         </Emp>

         <Emp name="JONES">

                   <HIREDATE>1981-04-02</HIREDATE>

                   <department_id>20</department_id>

         </Emp>

…..

 

利用对象将一对多的查询转化为xml

CREATEOR REPLACE TYPE emp_t AS OBJECT (

"@EMPNO" NUMBER(4),  --@转化为属性

ENAMEVARCHAR2(10)  --没有@转化为子结点

);

 

 

集合对象

CREATEOR REPLACE TYPE emplist_t AS TABLE OF emp_t;

 

CREATEOR REPLACE TYPE dept_t AS OBJECT (

"@DEPTNO"NUMBER(2),

DNAMEVARCHAR2(14),

EMP_LISTemplist_t

);

 

SELECT XMLElement("Department",
dept_t(deptno,
dname,
CAST(
   MULTISET(
      SELECT empno, ename
      FROM scott.emp e
      WHERE e.deptno = d.deptno) --多方
AS emplist_t))).getstringval()
AS deptxml
FROM scott.dept d
WHERE d.deptno = 20;

 

<Department>

         <DEPT_T DEPTNO="20">

                   <DNAME>RESEARCH</DNAME>

                   <EMP_LIST>

                            <EMP_T EMPNO="7369">

                                     <ENAME>SMITH</ENAME>

                            </EMP_T>

                            <EMP_T EMPNO="7566">

                                     <ENAME>JONES</ENAME>

                            </EMP_T>

                            <EMP_T EMPNO="7788">

                                     <ENAME>SCOTT</ENAME>

                            </EMP_T>

                            <EMP_T EMPNO="7876">

                                     <ENAME>ADAMS</ENAME>

                            </EMP_T>

                            <EMP_T EMPNO="7902">

                                     <ENAME>FORD</ENAME>

                            </EMP_T>

                   </EMP_LIST>

         </DEPT_T>

</Department>

 

注意:不能对cursor直接转化

 

select  
xmlelement("department",
                    xmlattributes(deptno
as  dept_id),
                   xmlelement(dname,dname),
                   xmlelement("emplist",

cursor(select empno,ename from scott.emp wheredeptno=d.deptno) )
                    )
from scott.dept d
where deptno=20

ORA-22902: 不允许 CURSOR 表达式

 

selectxmlforest(
dept_t(deptno,
dname,
cast (multiset (selectempno, ename
             from scott.emp e
             where e.deptno = d.deptno)
    as emplist_t)) –将多方转化为集合对象
as"department").getstringval()
as deptxml
from scott.dept  d
where deptno=20;

输出结果:

-----------------------------------------------------------
<departmentdeptno="20">
         <dname>research</dname>
         <emp_list>
                   <emp_tempno="7369">
                            <ename>smith</ename>
                   </emp_t>
                   <emp_tempno="7566">
                            <ename>jones</ename>
                   </emp_t>
                   <emp_tempno="7788">
                            <ename>scott</ename>
                   </emp_t>
                   <emp_tempno="7876">
                            <ename>adams</ename>
                   </emp_t>
                   <emp_tempno="7902">
                            <ename>ford</ename>
                   </emp_t>
         </emp_list>
</department>

 

 

XMLConcat

拼接XML结点

 

SELECTXMLConcat(XMLSequenceType(

XMLType('<PartNo>1236</PartNo>'),

XMLType('<PartName>Widget</PartName>'),

XMLType('<PartPrice>29.99</PartPrice>'))).getCLOBVal()

AS"RESULT"

FROM DUAL;

 

<partno>1236</partno>

<partname>widget</partname>

<partprice>29.99</partprice>

 

 

xmlagg
分组累积运算

select
xmlagg(
      xmlelement("deptno",
                 xmlattributes(deptno as  dept_id),
                 xmlagg( xmlelement("name",ename))
      )
      ). getstringval()
from scott.emp
where deptno in (20,10)
group by deptno

注意转成的XML文件没有ROOT节点。
         <deptnoDEPT_ID="10">
                   <name>CLARK</name>
                   <name>KING</name>
                   <name>MILLER</name>
         </deptno>
         <deptnoDEPT_ID="20">
                   <name>SMITH</name>
                   <name>ADAMS</name>
                   <name>FORD</name>
                   <name>SCOTT</name>
                   <name>JONES</name>
         </deptno>

 

select
xmlagg(
      xmlelement("deptno",
                 xmlattributes(deptno as dept_id),
                 xmlagg(xmlelement("emps",
                               xmlattributes(empno as  emp_id),
                                xmlelement("name",ename)
                                )))).getstringval()
from scott.emp
where deptno in (20,10)
group by deptno

       <deptno DEPT_ID="10">

                   <emps EMP_ID="7782">

                            <name>CLARK</name>

                   </emps>

                   <emps EMP_ID="7839">

                            <name>KING</name>

                   </emps>

                   <emps EMP_ID="7934">

                            <name>MILLER</name>

                   </emps>

         </deptno>

         <deptno DEPT_ID="20">

                   <emps EMP_ID="7369">

                            <name>SMITH</name>

                   </emps>

                   <emps EMP_ID="7876">

                            <name>ADAMS</name>

                   </emps>

                   <emps EMP_ID="7902">

                            <name>FORD</name>

                   </emps>

                   <emps EMP_ID="7788">

                            <name>SCOTT</name>

                   </emps>

                   <emps EMP_ID="7566">

                            <name>JONES</name>

                   </emps>

         </deptno>

 

试着比较以下语句

select

   xmlagg(

     xmlelement("emp",

                 xmlattributes(empno as  emp_id),

                xmlelement("name",ename),

                xmlelement("dept_id",deptno)

             )). getstringval()

from scott.emp

where deptno in (20,10)

 

    <empEMP_ID="7369">

       <name>SMITH</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7566">

       <name>JONES</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7782">

       <name>CLARK</name>

       <dept_id>10</dept_id>

    </emp>

    <empEMP_ID="7788">

       <name>SCOTT</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7839">

       <name>KING</name>

       <dept_id>10</dept_id>

    </emp>

    <empEMP_ID="7876">

       <name>ADAMS</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7902">

       <name>FORD</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7934">

       <name>MILLER</name>

       <dept_id>10</dept_id>

    </emp>

 

XMLComment

注释

SELECTXMLComment('This is a comment') AS cmnt FROM DUAL;

<!--This is a comment-->

 

 

 

xmlcolattval

select

  xmlelement(

  "emp",
  xmlattributes(e.ename  
as "fullname" ),
  xmlcolattval(e.hiredate, e.sal
as"salary")

   ).getstringval()
as "result"
from scott.emp e
where e.deptno = 30;

<emp fullname="ALLEN"><
column name= "HIREDATE">1981-02-20</column><columnname = "salary">1600</column></emp>
<emp fullname="WARD"><
column name ="HIREDATE">1981-02-22</column><columnname = "salary">1250</column></emp>
<emp fullname="MARTIN"><
column name ="HIREDATE">1981-09-28</column><columnname = "salary">1250</column></emp>
<emp fullname="BLAKE"><
column name ="HIREDATE">1981-05-01</column><columnname = "salary">2850</column></emp>
<emp fullname="TURNER"><
column name ="HIREDATE">1981-09-08</column><columnname = "salary">1500</column></emp>
<emp fullname="JAMES"><
column name ="HIREDATE">1981-12-03</column><columnname = "salary">950</column></emp>

 

 

 

select xmlelement("purchaseorder",
      xmlelement("address",
      xmlcdata('100 pennsylvaniaave.'),
      xmlelement("city", 'washington, d.c.'))).getstringval()
as result

from dual;

<purchaseorder>
       <address>
           <![CDATA[100 pennsylvaniaave.]]>
           <city>washington,d.c.</city>
       </address>
</purchaseorder>

 

 

 

 

select
  value(tab).getStringVal() "SomeCol"
from
  table (
    XMLSequence(extract (
     XMLType('<things>

                <item>car</item>

                 <item>bottle</item>

                <item>chair</item>

              </things>'),
     '/things/item')
    )
  ) tab;

<item>car</item>

<item>bottle</item>

<item>chair</item>

 

 

SYS_XMLAgg

包装XML文件

selectsys_XMLAgg(value(em),XMLFormat('emps')).getstringval() as "xmltype"
from
table(

xmlsequence(cursor(select empno,ename fromscott.emp where deptno = 10))

) em;


<?xml version="1.0"?>
<emps>
<ROW>
  <EMPNO>7782</EMPNO>
  <ENAME>CLARK</ENAME>
</ROW>
<ROW>
  <EMPNO>7839</EMPNO>
  <ENAME>KING</ENAME>
</ROW>
<ROW>
  <EMPNO>7934</EMPNO>
  <ENAME>MILLER</ENAME>
</ROW>
</emps>

 

 

select

sys_xmlagg(

     xmlelement("deptno",

                 xmlattributes(deptno as  dept_id),

                 xmlagg(xmlelement("emps",

                               xmlattributes(empno as  emp_id),

                               xmlelement("name", ename)

                                ))),xmlformat('depts')). getstringval()

from scott.emp

where deptno in (20,10)

group by deptno

 

<?xmlversion="1.0"?>

<depts>

         <deptno DEPT_ID="10">

                   <emps EMP_ID="7782">

                            <name>CLARK</name>

                   </emps>

                   <emps EMP_ID="7839">

                            <name>KING</name>

                   </emps>

                   <emps EMP_ID="7934">

                            <name>MILLER</name>

                   </emps>

         </deptno>

         <deptno DEPT_ID="20">

                   <emps EMP_ID="7369">

                            <name>SMITH</name>

                   </emps>

                   <emps EMP_ID="7876">

                            <name>ADAMS</name>

                   </emps>

                   <emps EMP_ID="7902">

                            <name>FORD</name>

                   </emps>

                   <emps EMP_ID="7788">

                            <name>SCOTT</name>

                   </emps>

                   <emps EMP_ID="7566">

                            <name>JONES</name>

                   </emps>

         </deptno>

</depts>

 

以上介绍的一些XML函数,将一个查询结果转化为XML文件。Oracle还提供了一个pl/sql包,负责将查询结果转化为XML。

dbms_xmlgen的用法

 

declare
  qryctx dbms_xmlgen.ctxhandle;
 
result clob;
begin
  qryctx := dbms_xmlgen.newcontext('selectdeptno, dname from scott.dept d ');
  -- set therow header to be employee
  dbms_xmlgen.setrowtag(qryctx, 'dept');
  -- get theresult
 
result :=dbms_xmlgen.getxml(qryctx);
  dbms_output.put_line(
result);
  --closecontext
  dbms_xmlgen.closecontext(qryctx);
end;



<?xml version="1.0"?>
<ROWSET>
 <DEPT>
  <DEPTNO>10</DEPTNO>
  <DNAME>ACCOUNTING</DNAME>
 </DEPT>
 <DEPT>
  <DEPTNO>20</DEPTNO>
  <DNAME>RESEARCH</DNAME>
 </DEPT>
 <DEPT>
  <DEPTNO>30</DEPTNO>
  <DNAME>SALES</DNAME>
 </DEPT>
 <DEPT>
  <DEPTNO>40</DEPTNO>
  <DNAME>OPERATIONS</DNAME>
 </DEPT>
 <DEPT>
  <DEPTNO>50</DEPTNO>
  <DNAME>a</DNAME>
 </DEPT>
</ROWSET>

 

 

 

declare
  qryctx dbms_xmlgen.ctxhandle;
  resultclob;
begin
  -- get the query context;
  qryctx := dbms_xmlgen.newcontext('select * from scott.dept');
  -- set the maximum number of rows to be 2
  dbms_xmlgen.setmaxrows(qryctx, 2); --转化2条数据组成一个文件
  loop
    -- get the result
    result := dbms_xmlgen.getxml(qryctx);
    -- if no rows were processed, then quit
    exit whendbms_xmlgen.getnumrowsprocessed(qryctx) = 0;
    -- do some processing with the lob data
    -- here, we insert the results into a table.
    -- you can print the lob out, output it to astream,
    -- put it in a queue, or do any otherprocessing.
    dbms_output.put_line(result);
  endloop;
  --close context
  dbms_xmlgen.closecontext(qryctx);
end;

 

<?xmlversion="1.0"?>
<ROWSET>
 <ROW>
  <DEPTNO>10</DEPTNO>
  <DNAME>ACCOUNTING</DNAME>
  <LOC>NEW YORK</LOC>
 </ROW>
 <ROW>
  <DEPTNO>20</DEPTNO>
  <DNAME>RESEARCH</DNAME>
  <LOC>DALLAS</LOC>
 </ROW>
</ROWSET>

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <DEPTNO>30</DEPTNO>
  <DNAME>SALES</DNAME>
  <LOC>hhhhh</LOC>
 </ROW>
 <ROW>
  <DEPTNO>40</DEPTNO>
  <DNAME>OPERATIONS</DNAME>
  <LOC>BOSTON</LOC>
 </ROW>
</ROWSET>

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <DEPTNO>50</DEPTNO>
  <DNAME>a</DNAME>
  <LOC>b</LOC>
 </ROW>
</ROWSET>

 

 

层次查询结果返回XML文件

 

create table t_clob(a clob)

 

declare

  qryctx dbms_xmlgen.ctxhandle;

  result xmltype;

begin

  qryctx := dbms_xmlgen.newcontextfromhierarchy(

   'select level,

         xmlelement("employees",

         xmlelement("enumber", empno),

         xmlelement("name", ename),

         xmlelement("salary", sal),

         xmlelement("hiredate",hiredate)

        )

from scott.emp

start with ename=''KING'' connect by prior empno=mgr

order siblings by hiredate'

);

  result :=dbms_xmlgen.getxmltype(qryctx);

  dbms_output.put_line('<resultnum rows>');

 dbms_output.put_line(to_char(dbms_xmlgen.getnumrowsprocessed(qryctx)));

--得到处理的行数

  --dbms_output.put_line('</resultnum rows>');

  --dbms_output.put_line(result.getstringval());

  insert into t_clob values (result.getstringval());

  commit;

  dbms_xmlgen.closecontext(qryctx);

end;

<?xml version="1.0"?>

<employees>

       <enumber>7839</enumber>

       <name>KING</name>

       <salary>5000</salary>

       <hiredate>1981-11-17</hiredate>

       <employees>

              <enumber>7566</enumber>

              <name>JONES</name>

              <salary>2975</salary>

              <hiredate>1981-04-02</hiredate>

              <employees>

                     <enumber>7902</enumber>

                     <name>FORD</name>

                     <salary>3000</salary>

                     <hiredate>1981-12-03</hiredate>

                     <employees>

                            <enumber>7369</enumber>

                            <name>SMITH</name>

                            <salary>800</salary>

                            <hiredate>1980-12-17</hiredate>

                     </employees>

              </employees>

              <employees>

                     <enumber>7788</enumber>

                     <name>SCOTT</name>

                     <salary>3000</salary>

                     <hiredate>1987-04-19</hiredate>

                     <employees>

                            <enumber>7876</enumber>

                            <name>ADAMS</name>

                            <salary>1100</salary>

                            <hiredate>1987-05-23</hiredate>

                     </employees>

              </employees>

       </employees>

       <employees>

              <enumber>7698</enumber>

              <name>BLAKE</name>

              <salary>2850</salary>

              <hiredate>1981-05-01</hiredate>

              <employees>

                     <enumber>7499</enumber>

                     <name>ALLEN</name>

                     <salary>1600</salary>

                     <hiredate>1981-02-20</hiredate>

              </employees>

              <employees>

                     <enumber>7521</enumber>

                     <name>WARD</name>

                     <salary>1250</salary>

                     <hiredate>1981-02-22</hiredate>

              </employees>

              <employees>

                     <enumber>7844</enumber>

                     <name>TURNER</name>

                     <salary>1500</salary>

                     <hiredate>1981-09-08</hiredate>

              </employees>

              <employees>

                     <enumber>7654</enumber>

                     <name>MARTIN</name>

                     <salary>1250</salary>

                     <hiredate>1981-09-28</hiredate>

              </employees>

              <employees>

                     <enumber>7900</enumber>

                     <name>JAMES</name>

                     <salary>950</salary>

                     <hiredate>1981-12-03</hiredate>

              </employees>

       </employees>

       <employees>

              <enumber>7782</enumber>

              <name>CLARK</name>

              <salary>2450</salary>

              <hiredate>1981-06-09</hiredate>

              <employees>

                     <enumber>7934</enumber>

                     <name>MILLER</name>

                     <salary>1300</salary>

                     <hiredate>1982-01-23</hiredate>

              </employees>

       </employees>

</employees>

 

 

By default, the ROWSET tag is NULL: there is no default ROWSET tag used to enclose the XML result. However, you canexplicitly set the ROWSET tag by using procedure

setRowSetTag(), as follows:

 

declare

 qryctx dbms_xmlgen.ctxhandle;

 result xmltype;

begin

 qryctx := dbms_xmlgen.newcontextfromhierarchy('select level,

xmlelement("employees",

 xmlelement("enumber", empno),

 xmlelement("name", ename),

 xmlelement("salary", sal),

 xmlelement("hiredate", hiredate))

from scott.emp

start with ename=''KING'' connect by priorempno=mgr

order siblings by hiredate');

dbms_xmlgen.setrowsettag(qryctx,'mynum_hierarchy');

 result := dbms_xmlgen.getxmltype(qryctx);

  dbms_output.put_line('<resultnum rows>');

 dbms_output.put_line(to_char(dbms_xmlgen.getnumrowsprocessed(qryctx)));

 dbms_output.put_line('</result num rows>');

 --dbms_output.put_line (result.getstringval());

 insert into sqlx_display values (3, result);

 commit;

 dbms_xmlgen.closecontext(qryctx);

end;

 

 

绑定变量

 

declare
  ctx   
number;
  xmldoc
clob;
begin
  ctx := dbms_xmlgen.newcontext('select * from scott.emp where deptno =:no');
  dbms_xmlgen.setbindvalue(ctx, 'no', '20');
  xmldoc := dbms_xmlgen.getxml(ctx);
  dbms_output.put_line(xmldoc);
  dbms_xmlgen.closecontext(ctx);
exception
 
when others then
    dbms_xmlgen.closecontext(ctx);
   
raise;
end;

 

绑定变量多次使用

declare
  ctx   
number;
  xmldoc
clob;
begin
  ctx := dbms_xmlgen.newcontext('select * from scott.empwhere deptno = :mdate');
  dbms_xmlgen.setbindvalue(ctx, 'mdate', '10');
  xmldoc := dbms_xmlgen.getxml(ctx);
  dbms_output.put_line(xmldoc);
  dbms_xmlgen.setbindvalue(ctx, 'mdate', '10');
  xmldoc := dbms_xmlgen.getxml(ctx);
  dbms_output.put_line(xmldoc);
  dbms_xmlgen.closecontext(ctx);
exception
 
when others then
    dbms_xmlgen.closecontext(ctx);
   
raise;
end;

 

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <EMPNO>7782</EMPNO>
  <ENAME>CLARK</ENAME>
  <JOB>MANAGER</JOB>
  <MGR>7839</MGR>
  <HIREDATE>09-6ÔÂ-81</HIREDATE>
  <SAL>2450</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7839</EMPNO>
  <ENAME>KING</ENAME>
  <JOB>PRESIDENT</JOB>
 <HIREDATE>17-11ÔÂ-81</HIREDATE>
  <SAL>5000</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7934</EMPNO>
  <ENAME>MILLER</ENAME>
  <JOB>CLERK</JOB>
  <MGR>7782</MGR>
  <HIREDATE>23-1ÔÂ-82</HIREDATE>
  <SAL>1300</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
</ROWSET>

<?xmlversion="1.0"?>
<ROWSET>
 <ROW>
  <EMPNO>7782</EMPNO>
  <ENAME>CLARK</ENAME>
  <JOB>MANAGER</JOB>
  <MGR>7839</MGR>
  <HIREDATE>09-6ÔÂ -81</HIREDATE>
  <SAL>2450</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7839</EMPNO>
  <ENAME>KING</ENAME>
  <JOB>PRESIDENT</JOB>
 <HIREDATE>17-11ÔÂ-81</HIREDATE>
  <SAL>5000</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7934</EMPNO>
  <ENAME>MILLER</ENAME>
  <JOB>CLERK</JOB>
  <MGR>7782</MGR>
  <HIREDATE>23-1ÔÂ-82</HIREDATE>
  <SAL>1300</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
</ROWSET>


 

多个绑定变量

declare
  ctx   
number;
  xmldoc
clob;
begin
  ctx := dbms_xmlgen.newcontext('select * from scott.emp
where deptno = :no
and sal > :mdate');
  dbms_xmlgen.setbindvalue(ctx, 'no', '20');
  dbms_xmlgen.setbindvalue(ctx, 'mdate', '1000');
  xmldoc := dbms_xmlgen.getxml(ctx);
  dbms_output.put_line(xmldoc);
  dbms_xmlgen.closecontext(ctx);
exception
  whenothers then
    dbms_xmlgen.closecontext(ctx);
    raise;
end;

 

 

参考游标

declare
  ctx   number;
  maxrow number;
  xmldoc clob;
  refcur sys_refcursor;
begin
  dbms_lob.createtemporary(xmldoc, true);
  maxrow := 2;
  openrefcur for 'select * from scott.empwhere rownum <= :1'
    using maxrow;
  ctx := dbms_xmlgen.newcontext(refcur);
  -- xmldoc will have 2 rows
  dbms_xmlgen.getxml(ctx, xmldoc, dbms_xmlgen.none);
  dbms_output.put_line(xmldoc);
  dbms_lob.freetemporary(xmldoc);
  closerefcur;
  dbms_xmlgen.closecontext(ctx);
end;

 

 

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <EMPNO>7369</EMPNO>
  <ENAME>SMITH</ENAME>
  <JOB>CLERK</JOB>
  <MGR>7902</MGR>
  <HIREDATE>17-12ÔÂ-80</HIREDATE>
  <SAL>800</SAL>
  <DEPTNO>20</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7499</EMPNO>
  <ENAME>ALLEN</ENAME>
  <JOB>SALESMAN</JOB>
  <MGR>7698</MGR>
  <HIREDATE>20-2ÔÂ-81</HIREDATE>
  <SAL>1600</SAL>
  <COMM>300</COMM>
  <DEPTNO>30</DEPTNO>
 </ROW>
</ROWSET>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CREATE TABLEemp_tab(

emp_id NUMBERPRIMARY KEY,

name VARCHAR2(20),

dept_id NUMBER);

 

TINSERT INTO emp_tabVALUES(30, 'Scott', NULL);

INSERT INTO emp_tabVALUES(31, 'Mary', NULL);

INSERT INTO emp_tabVALUES(40, 'John', NULL);

COMMIT;

CREATE TABLEtemp_clob_tab(result CLOB);

 

declare
  qryctx dbms_xmlgen.ctxhandle;
 
result clob;
begin
  qryctx := dbms_xmlgen.newcontext('select * from emp_tabwhere name = :name');
  -- set the row header to be employee
  dbms_xmlgen.setrowtag(qryctx, 'employee');
  -- drop nulls
  dbms_xmlgen.setbindvalue(qryctx, 'name', 'scott');
  dbms_xmlgen.setnullhandling(qryctx, dbms_xmlgen.drop_nulls);
 
result :=dbms_xmlgen.getxml(qryctx);
 
insert into temp_clob_tabvalues (result);
  -- null attribute
  dbms_xmlgen.setbindvalue(qryctx, 'name', 'mary');
  dbms_xmlgen.setnullhandling(qryctx, dbms_xmlgen.null_attr);
 
result :=dbms_xmlgen.getxml(qryctx);
 
insert into temp_clob_tabvalues (result);
  -- empty tag
  dbms_xmlgen.setbindvalue(qryctx, 'name', 'john');
  dbms_xmlgen.setnullhandling(qryctx, dbms_xmlgen.empty_tag);
 
result :=dbms_xmlgen.getxml(qryctx);
 
insert into temp_clob_tabvalues (result);
  --close context
  dbms_xmlgen.closecontext(qryctx);
end;

 

 

 

 

 

 

 

 

XML转化为关系型表数据

CREATE OR REPLACE TYPE address_type AS OBJECT ( 

address_line1 VARCHAR2(100), 

address_line2 VARCHAR2(100), 

address_line3 VARCHAR2(100) );

 

declare
  v_xml XMLTYPE;
  v_addr address_type;  
BEGIN
  -- create XML  
  v_xml := XMLTYPE('
<ADDRESS_TYPE>
 <ADDRESS_LINE1>line1</ADDRESS_LINE1>
<ADDRESS_LINE2>line2</ADDRESS_LINE2>
<ADDRESS_LINE3>line3</ADDRESS_LINE3>            
</ADDRESS_TYPE>
');
  --convert xml to object  
  v_xml.
toObject(v_addr);
  -- display xml output  
  DBMS_OUTPUT.put_line('Address Line 1: ' || v_addr.address_line1 ||
                                              ', Address Line 2: ' || v_addr.address_line2 ||
                                              ', dress Line 3: ' || v_addr.address_line3);
END;

 

输出结果

Address Line 1: line1,
Address Line 2: line2, 
Address Line 3: line3

 

 

 

 

 

CREATE TABLEdept_xml_tab OF XMLType;

 

INSERT INTOdept_xml_tab

VALUES(

XMLType('<Departmentdeptno="100">

<DeptName>Sports</DeptName>

<EmployeeList>

<Employeeempno="200"><Ename>John</Ename><Salary>33333</Salary>

</Employee>

<Employeeempno="300"><Ename>Jack</Ename><Salary>333444</Salary>

</Employee>

</EmployeeList>

</Department>'));

1 row created.

INSERT INTOdept_xml_tab

VALUES (

XMLType('<Departmentdeptno="200">

<DeptName>Sports</DeptName>

<EmployeeList>

<Employeeempno="400"><Ename>Marlin</Ename><Salary>20000</Salary>

</Employee>

</EmployeeList>

</Department>'));

1 row created.

COMMIT;

You can use SQL function XMLSequenceto un-nest the Employee list items as

top-level SQL rows:

SELECTextractValue(OBJECT_VALUE, '/Department/@deptno') AS deptno,

extractValue(value(em),'/Employee/@empno') AS empno,

extractValue(value(em),'/Employee/Ename') AS ename

FROM dept_xml_tab,

table(XMLSequence(extract(OBJECT_VALUE,

'/Department/EmployeeList/Employee')))em;

This returns the following:

DEPTNO EMPNO ENAME

---------------------------------

100 200 John

100 300 Jack

200 400 Marlin

 

 

 

 

 

 


CREATE TABLE tblControllerProjectsXML OF XMLType
 

insert into tblControllerProjectsXML
values
(
xmltype(
'<Solution>
       <Project ProjectID="5"Name="Unassigned TeamWork Project">
              <DatabaseMonitoredDBID="2" />
              <DatabaseMonitoredDBID="5" />
              <DatabaseMonitoredDBID="13" />
              <DatabaseMonitoredDBID="12" />
              <DatabaseMonitoredDBID="14" />
              <DatabaseMonitoredDBID="15" />
       </Project>
       <Project ProjectID="9"Name="Unassigned TeamWork Project">
              <DatabaseMonitoredDBID="9" />
              <DatabaseMonitoredDBID="10" />
              <DatabaseMonitoredDBID="15" />
       </Project>
</Solution>'
))

select * from
(
SELECT  extractValue(value(d),'/Database/@MonitoredDBID') AS MonDBID,
        extractValue(
value(p), '/Project/@ProjectID') AS ProId
FROM tblControllerProjectsXML X,
TABLE(XMLSequence(extract(X.OBJECT_VALUE,'/Solution/Project/Database'))) d,
TABLE(XMLSequence(extract(X.OBJECT_VALUE,'/Solution/Project'))) p
)
order by proid,mondbid desc

 

MONDBID

PROID

9

5

5

5

2

5

15

5

15

5

14

5

13

5

12

5

10

5

9

9

5

9

2

9

15

9

15

9

14

9

13

9

12

9

10

9

 

Oracle 关系型数据与XML数据之间的转化学习

 

 

  CREATE TABLE SCOTT.EMP
   (       EMPNONUMBER(4,0),
       ENAME VARCHAR2(10),
       JOB VARCHAR2(9),
       MGR NUMBER(4,0),
       HIREDATE DATE,
       SAL NUMBER(7,2),
       COMM NUMBER(7,2),
       DEPTNO NUMBER(2,0),
        CONSTRAINT PK_EMP PRIMARY KEY (EMPNO)

)

 

 

主要内容:将关系型结构化数据转化为XML文件

 

一、对象转化为XML文件

 

建立一个对象

CREATE OR REPLACE TYPE address_type AS OBJECT ( 

address_line1 VARCHAR2(100), 

address_line2 VARCHAR2(100), 

address_line3 VARCHAR2(100) );

 

declare
  v_addr address_type;
  v_xml xmltype;
begin
  -- 建立一个对象实例
  v_addr := address_type('n1', 'n2', 'n3');
  --将对象实例转化为xml
  v_xml := xmltype(v_addr);
  -- 显示 xml 输出
 dbms_output.put_line(v_xml.getstringval());
end;

 

输出结果:

<ADDRESS_TYPE>

    <ADDRESS_LINE1>n1</ADDRESS_LINE1>

    <ADDRESS_LINE2>n2</ADDRESS_LINE2>

    <ADDRESS_LINE3>n3</ADDRESS_LINE3>

</ADDRESS_TYPE>

 

xmltype 将数据转化为XML的一个结点;

xmltype也是数据表的一种数据类型,如同varchar2数据类型一样。

getstringval()将一个xml结点或者xml数据类型类型转化为varchar2类型;

其它的转化函数还有

getCLOBVal()

getStringVal()

getNumberVal()

getBLOBVal(csid)

 

上述匿名过程告诉我们一个方法,可以将关系型数据转化为集合,然后就可以转化为XML文件。

实际上oracle提供了较多的函数,方便我们的转化工作。

 

xmlelement

将一个普通查询(非层次查询)的结果,转化为XML

select
xmlelement("name", ename).getstringval()
from scott.emp

 

1、 将一个字段转化为XML的一个节点

 

XMLELEMENT("NAME",ENAME)

-----------------------------

<name>SMITH</name>

<name>ALLEN</name>

<name>WARD</name>

<name>JONES</name>

<name>MARTIN</name>

……

xmlattributes

增加属性

SELECT
XMLElement("Deptno",
   XMLATTRIBUTES(deptno AS dept_id),
   XMLElement("Name", ename),
   XMLElement("Date", hiredate)
). getstringval()
FROM scott.emp

 

<Deptno DEPT_ID="20"><Name>SMITH</Name><Date>1980-12-17</Date></Deptno>

<DeptnoDEPT_ID="30"><Name>ALLEN</Name><Date>1981-02-20</Date></Deptno>

<DeptnoDEPT_ID="30"><Name>WARD</Name><Date>1981-02-22</Date></Deptno>

<DeptnoDEPT_ID="20"><Name>JONES</Name><Date>1981-04-02</Date></Deptno>

……

但是上述XML节点不符合规范,不过没有关系,这个函数只是提供了一个转化方法

 

xmlforest

如果以已有的字段名称作为元素名称转化为XML文件

 

select xmlelement(

"emp",
xmlattributes(e.ename
as "name"),
xmlforest(e.hiredate, e.deptno
as "department_id")

).getstringval()
as "result"
from scott.emp e where e.deptno = 20;

 

         <Emp name="SMITH">

                   <HIREDATE>1980-12-17</HIREDATE>

                   <department_id>20</department_id>

         </Emp>

         <Emp name="JONES">

                   <HIREDATE>1981-04-02</HIREDATE>

                   <department_id>20</department_id>

         </Emp>

…..

 

利用对象将一对多的查询转化为xml

CREATEOR REPLACE TYPE emp_t AS OBJECT (

"@EMPNO" NUMBER(4),  --@转化为属性

ENAMEVARCHAR2(10)  --没有@转化为子结点

);

 

 

集合对象

CREATEOR REPLACE TYPE emplist_t AS TABLE OF emp_t;

 

CREATEOR REPLACE TYPE dept_t AS OBJECT (

"@DEPTNO"NUMBER(2),

DNAMEVARCHAR2(14),

EMP_LISTemplist_t

);

 

SELECT XMLElement("Department",
dept_t(deptno,
dname,
CAST(
   MULTISET(
      SELECT empno, ename
      FROM scott.emp e
      WHERE e.deptno = d.deptno) --多方
AS emplist_t))).getstringval()
AS deptxml
FROM scott.dept d
WHERE d.deptno = 20;

 

<Department>

         <DEPT_T DEPTNO="20">

                   <DNAME>RESEARCH</DNAME>

                   <EMP_LIST>

                            <EMP_T EMPNO="7369">

                                     <ENAME>SMITH</ENAME>

                            </EMP_T>

                            <EMP_T EMPNO="7566">

                                     <ENAME>JONES</ENAME>

                            </EMP_T>

                            <EMP_T EMPNO="7788">

                                     <ENAME>SCOTT</ENAME>

                            </EMP_T>

                            <EMP_T EMPNO="7876">

                                     <ENAME>ADAMS</ENAME>

                            </EMP_T>

                            <EMP_T EMPNO="7902">

                                     <ENAME>FORD</ENAME>

                            </EMP_T>

                   </EMP_LIST>

         </DEPT_T>

</Department>

 

注意:不能对cursor直接转化

 

select  
xmlelement("department",
                    xmlattributes(deptno
as  dept_id),
                   xmlelement(dname,dname),
                   xmlelement("emplist",

cursor(select empno,ename from scott.emp wheredeptno=d.deptno) )
                    )
from scott.dept d
where deptno=20

ORA-22902: 不允许 CURSOR 表达式

 

selectxmlforest(
dept_t(deptno,
dname,
cast (multiset (selectempno, ename
             from scott.emp e
             where e.deptno = d.deptno)
    as emplist_t)) –将多方转化为集合对象
as"department").getstringval()
as deptxml
from scott.dept  d
where deptno=20;

输出结果:

-----------------------------------------------------------
<departmentdeptno="20">
         <dname>research</dname>
         <emp_list>
                   <emp_tempno="7369">
                            <ename>smith</ename>
                   </emp_t>
                   <emp_tempno="7566">
                            <ename>jones</ename>
                   </emp_t>
                   <emp_tempno="7788">
                            <ename>scott</ename>
                   </emp_t>
                   <emp_tempno="7876">
                            <ename>adams</ename>
                   </emp_t>
                   <emp_tempno="7902">
                            <ename>ford</ename>
                   </emp_t>
         </emp_list>
</department>

 

 

XMLConcat

拼接XML结点

 

SELECTXMLConcat(XMLSequenceType(

XMLType('<PartNo>1236</PartNo>'),

XMLType('<PartName>Widget</PartName>'),

XMLType('<PartPrice>29.99</PartPrice>'))).getCLOBVal()

AS"RESULT"

FROM DUAL;

 

<partno>1236</partno>

<partname>widget</partname>

<partprice>29.99</partprice>

 

 

xmlagg
分组累积运算

select
xmlagg(
      xmlelement("deptno",
                 xmlattributes(deptno as  dept_id),
                 xmlagg( xmlelement("name",ename))
      )
      ). getstringval()
from scott.emp
where deptno in (20,10)
group by deptno

注意转成的XML文件没有ROOT节点。
         <deptnoDEPT_ID="10">
                   <name>CLARK</name>
                   <name>KING</name>
                   <name>MILLER</name>
         </deptno>
         <deptnoDEPT_ID="20">
                   <name>SMITH</name>
                   <name>ADAMS</name>
                   <name>FORD</name>
                   <name>SCOTT</name>
                   <name>JONES</name>
         </deptno>

 

select
xmlagg(
      xmlelement("deptno",
                 xmlattributes(deptno as dept_id),
                 xmlagg(xmlelement("emps",
                               xmlattributes(empno as  emp_id),
                                xmlelement("name",ename)
                                )))).getstringval()
from scott.emp
where deptno in (20,10)
group by deptno

       <deptno DEPT_ID="10">

                   <emps EMP_ID="7782">

                            <name>CLARK</name>

                   </emps>

                   <emps EMP_ID="7839">

                            <name>KING</name>

                   </emps>

                   <emps EMP_ID="7934">

                            <name>MILLER</name>

                   </emps>

         </deptno>

         <deptno DEPT_ID="20">

                   <emps EMP_ID="7369">

                            <name>SMITH</name>

                   </emps>

                   <emps EMP_ID="7876">

                            <name>ADAMS</name>

                   </emps>

                   <emps EMP_ID="7902">

                            <name>FORD</name>

                   </emps>

                   <emps EMP_ID="7788">

                            <name>SCOTT</name>

                   </emps>

                   <emps EMP_ID="7566">

                            <name>JONES</name>

                   </emps>

         </deptno>

 

试着比较以下语句

select

   xmlagg(

     xmlelement("emp",

                 xmlattributes(empno as  emp_id),

                xmlelement("name",ename),

                xmlelement("dept_id",deptno)

             )). getstringval()

from scott.emp

where deptno in (20,10)

 

    <empEMP_ID="7369">

       <name>SMITH</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7566">

       <name>JONES</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7782">

       <name>CLARK</name>

       <dept_id>10</dept_id>

    </emp>

    <empEMP_ID="7788">

       <name>SCOTT</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7839">

       <name>KING</name>

       <dept_id>10</dept_id>

    </emp>

    <empEMP_ID="7876">

       <name>ADAMS</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7902">

       <name>FORD</name>

       <dept_id>20</dept_id>

    </emp>

    <empEMP_ID="7934">

       <name>MILLER</name>

       <dept_id>10</dept_id>

    </emp>

 

XMLComment

注释

SELECTXMLComment('This is a comment') AS cmnt FROM DUAL;

<!--This is a comment-->

 

 

 

xmlcolattval

select

  xmlelement(

  "emp",
  xmlattributes(e.ename  
as "fullname" ),
  xmlcolattval(e.hiredate, e.sal
as"salary")

   ).getstringval()
as "result"
from scott.emp e
where e.deptno = 30;

<emp fullname="ALLEN"><
column name= "HIREDATE">1981-02-20</column><columnname = "salary">1600</column></emp>
<emp fullname="WARD"><
column name ="HIREDATE">1981-02-22</column><columnname = "salary">1250</column></emp>
<emp fullname="MARTIN"><
column name ="HIREDATE">1981-09-28</column><columnname = "salary">1250</column></emp>
<emp fullname="BLAKE"><
column name ="HIREDATE">1981-05-01</column><columnname = "salary">2850</column></emp>
<emp fullname="TURNER"><
column name ="HIREDATE">1981-09-08</column><columnname = "salary">1500</column></emp>
<emp fullname="JAMES"><
column name ="HIREDATE">1981-12-03</column><columnname = "salary">950</column></emp>

 

 

 

select xmlelement("purchaseorder",
      xmlelement("address",
      xmlcdata('100 pennsylvaniaave.'),
      xmlelement("city", 'washington, d.c.'))).getstringval()
as result

from dual;

<purchaseorder>
       <address>
           <![CDATA[100 pennsylvaniaave.]]>
           <city>washington,d.c.</city>
       </address>
</purchaseorder>

 

 

 

 

select
  value(tab).getStringVal() "SomeCol"
from
  table (
    XMLSequence(extract (
     XMLType('<things>

                <item>car</item>

                 <item>bottle</item>

                <item>chair</item>

              </things>'),
     '/things/item')
    )
  ) tab;

<item>car</item>

<item>bottle</item>

<item>chair</item>

 

 

SYS_XMLAgg

包装XML文件

selectsys_XMLAgg(value(em),XMLFormat('emps')).getstringval() as "xmltype"
from
table(

xmlsequence(cursor(select empno,ename fromscott.emp where deptno = 10))

) em;


<?xml version="1.0"?>
<emps>
<ROW>
  <EMPNO>7782</EMPNO>
  <ENAME>CLARK</ENAME>
</ROW>
<ROW>
  <EMPNO>7839</EMPNO>
  <ENAME>KING</ENAME>
</ROW>
<ROW>
  <EMPNO>7934</EMPNO>
  <ENAME>MILLER</ENAME>
</ROW>
</emps>

 

 

select

sys_xmlagg(

     xmlelement("deptno",

                 xmlattributes(deptno as  dept_id),

                 xmlagg(xmlelement("emps",

                               xmlattributes(empno as  emp_id),

                               xmlelement("name", ename)

                                ))),xmlformat('depts')). getstringval()

from scott.emp

where deptno in (20,10)

group by deptno

 

<?xmlversion="1.0"?>

<depts>

         <deptno DEPT_ID="10">

                   <emps EMP_ID="7782">

                            <name>CLARK</name>

                   </emps>

                   <emps EMP_ID="7839">

                            <name>KING</name>

                   </emps>

                   <emps EMP_ID="7934">

                            <name>MILLER</name>

                   </emps>

         </deptno>

         <deptno DEPT_ID="20">

                   <emps EMP_ID="7369">

                            <name>SMITH</name>

                   </emps>

                   <emps EMP_ID="7876">

                            <name>ADAMS</name>

                   </emps>

                   <emps EMP_ID="7902">

                            <name>FORD</name>

                   </emps>

                   <emps EMP_ID="7788">

                            <name>SCOTT</name>

                   </emps>

                   <emps EMP_ID="7566">

                            <name>JONES</name>

                   </emps>

         </deptno>

</depts>

 

以上介绍的一些XML函数,将一个查询结果转化为XML文件。Oracle还提供了一个pl/sql包,负责将查询结果转化为XML。

dbms_xmlgen的用法

 

declare
  qryctx dbms_xmlgen.ctxhandle;
 
result clob;
begin
  qryctx := dbms_xmlgen.newcontext('selectdeptno, dname from scott.dept d ');
  -- set therow header to be employee
  dbms_xmlgen.setrowtag(qryctx, 'dept');
  -- get theresult
 
result :=dbms_xmlgen.getxml(qryctx);
  dbms_output.put_line(
result);
  --closecontext
  dbms_xmlgen.closecontext(qryctx);
end;



<?xml version="1.0"?>
<ROWSET>
 <DEPT>
  <DEPTNO>10</DEPTNO>
  <DNAME>ACCOUNTING</DNAME>
 </DEPT>
 <DEPT>
  <DEPTNO>20</DEPTNO>
  <DNAME>RESEARCH</DNAME>
 </DEPT>
 <DEPT>
  <DEPTNO>30</DEPTNO>
  <DNAME>SALES</DNAME>
 </DEPT>
 <DEPT>
  <DEPTNO>40</DEPTNO>
  <DNAME>OPERATIONS</DNAME>
 </DEPT>
 <DEPT>
  <DEPTNO>50</DEPTNO>
  <DNAME>a</DNAME>
 </DEPT>
</ROWSET>

 

 

 

declare
  qryctx dbms_xmlgen.ctxhandle;
  resultclob;
begin
  -- get the query context;
  qryctx := dbms_xmlgen.newcontext('select * from scott.dept');
  -- set the maximum number of rows to be 2
  dbms_xmlgen.setmaxrows(qryctx, 2); --转化2条数据组成一个文件
  loop
    -- get the result
    result := dbms_xmlgen.getxml(qryctx);
    -- if no rows were processed, then quit
    exit whendbms_xmlgen.getnumrowsprocessed(qryctx) = 0;
    -- do some processing with the lob data
    -- here, we insert the results into a table.
    -- you can print the lob out, output it to astream,
    -- put it in a queue, or do any otherprocessing.
    dbms_output.put_line(result);
  endloop;
  --close context
  dbms_xmlgen.closecontext(qryctx);
end;

 

<?xmlversion="1.0"?>
<ROWSET>
 <ROW>
  <DEPTNO>10</DEPTNO>
  <DNAME>ACCOUNTING</DNAME>
  <LOC>NEW YORK</LOC>
 </ROW>
 <ROW>
  <DEPTNO>20</DEPTNO>
  <DNAME>RESEARCH</DNAME>
  <LOC>DALLAS</LOC>
 </ROW>
</ROWSET>

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <DEPTNO>30</DEPTNO>
  <DNAME>SALES</DNAME>
  <LOC>hhhhh</LOC>
 </ROW>
 <ROW>
  <DEPTNO>40</DEPTNO>
  <DNAME>OPERATIONS</DNAME>
  <LOC>BOSTON</LOC>
 </ROW>
</ROWSET>

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <DEPTNO>50</DEPTNO>
  <DNAME>a</DNAME>
  <LOC>b</LOC>
 </ROW>
</ROWSET>

 

 

层次查询结果返回XML文件

 

create table t_clob(a clob)

 

declare

  qryctx dbms_xmlgen.ctxhandle;

  result xmltype;

begin

  qryctx := dbms_xmlgen.newcontextfromhierarchy(

   'select level,

         xmlelement("employees",

         xmlelement("enumber", empno),

         xmlelement("name", ename),

         xmlelement("salary", sal),

         xmlelement("hiredate",hiredate)

        )

from scott.emp

start with ename=''KING'' connect by prior empno=mgr

order siblings by hiredate'

);

  result :=dbms_xmlgen.getxmltype(qryctx);

  dbms_output.put_line('<resultnum rows>');

 dbms_output.put_line(to_char(dbms_xmlgen.getnumrowsprocessed(qryctx)));

--得到处理的行数

  --dbms_output.put_line('</resultnum rows>');

  --dbms_output.put_line(result.getstringval());

  insert into t_clob values (result.getstringval());

  commit;

  dbms_xmlgen.closecontext(qryctx);

end;

<?xml version="1.0"?>

<employees>

       <enumber>7839</enumber>

       <name>KING</name>

       <salary>5000</salary>

       <hiredate>1981-11-17</hiredate>

       <employees>

              <enumber>7566</enumber>

              <name>JONES</name>

              <salary>2975</salary>

              <hiredate>1981-04-02</hiredate>

              <employees>

                     <enumber>7902</enumber>

                     <name>FORD</name>

                     <salary>3000</salary>

                     <hiredate>1981-12-03</hiredate>

                     <employees>

                            <enumber>7369</enumber>

                            <name>SMITH</name>

                            <salary>800</salary>

                            <hiredate>1980-12-17</hiredate>

                     </employees>

              </employees>

              <employees>

                     <enumber>7788</enumber>

                     <name>SCOTT</name>

                     <salary>3000</salary>

                     <hiredate>1987-04-19</hiredate>

                     <employees>

                            <enumber>7876</enumber>

                            <name>ADAMS</name>

                            <salary>1100</salary>

                            <hiredate>1987-05-23</hiredate>

                     </employees>

              </employees>

       </employees>

       <employees>

              <enumber>7698</enumber>

              <name>BLAKE</name>

              <salary>2850</salary>

              <hiredate>1981-05-01</hiredate>

              <employees>

                     <enumber>7499</enumber>

                     <name>ALLEN</name>

                     <salary>1600</salary>

                     <hiredate>1981-02-20</hiredate>

              </employees>

              <employees>

                     <enumber>7521</enumber>

                     <name>WARD</name>

                     <salary>1250</salary>

                     <hiredate>1981-02-22</hiredate>

              </employees>

              <employees>

                     <enumber>7844</enumber>

                     <name>TURNER</name>

                     <salary>1500</salary>

                     <hiredate>1981-09-08</hiredate>

              </employees>

              <employees>

                     <enumber>7654</enumber>

                     <name>MARTIN</name>

                     <salary>1250</salary>

                     <hiredate>1981-09-28</hiredate>

              </employees>

              <employees>

                     <enumber>7900</enumber>

                     <name>JAMES</name>

                     <salary>950</salary>

                     <hiredate>1981-12-03</hiredate>

              </employees>

       </employees>

       <employees>

              <enumber>7782</enumber>

              <name>CLARK</name>

              <salary>2450</salary>

              <hiredate>1981-06-09</hiredate>

              <employees>

                     <enumber>7934</enumber>

                     <name>MILLER</name>

                     <salary>1300</salary>

                     <hiredate>1982-01-23</hiredate>

              </employees>

       </employees>

</employees>

 

 

By default, the ROWSET tag is NULL: there is no default ROWSET tag used to enclose the XML result. However, you canexplicitly set the ROWSET tag by using procedure

setRowSetTag(), as follows:

 

declare

 qryctx dbms_xmlgen.ctxhandle;

 result xmltype;

begin

 qryctx := dbms_xmlgen.newcontextfromhierarchy('select level,

xmlelement("employees",

 xmlelement("enumber", empno),

 xmlelement("name", ename),

 xmlelement("salary", sal),

 xmlelement("hiredate", hiredate))

from scott.emp

start with ename=''KING'' connect by priorempno=mgr

order siblings by hiredate');

dbms_xmlgen.setrowsettag(qryctx,'mynum_hierarchy');

 result := dbms_xmlgen.getxmltype(qryctx);

  dbms_output.put_line('<resultnum rows>');

 dbms_output.put_line(to_char(dbms_xmlgen.getnumrowsprocessed(qryctx)));

 dbms_output.put_line('</result num rows>');

 --dbms_output.put_line (result.getstringval());

 insert into sqlx_display values (3, result);

 commit;

 dbms_xmlgen.closecontext(qryctx);

end;

 

 

绑定变量

 

declare
  ctx   
number;
  xmldoc
clob;
begin
  ctx := dbms_xmlgen.newcontext('select * from scott.emp where deptno =:no');
  dbms_xmlgen.setbindvalue(ctx, 'no', '20');
  xmldoc := dbms_xmlgen.getxml(ctx);
  dbms_output.put_line(xmldoc);
  dbms_xmlgen.closecontext(ctx);
exception
 
when others then
    dbms_xmlgen.closecontext(ctx);
   
raise;
end;

 

绑定变量多次使用

declare
  ctx   
number;
  xmldoc
clob;
begin
  ctx := dbms_xmlgen.newcontext('select * from scott.empwhere deptno = :mdate');
  dbms_xmlgen.setbindvalue(ctx, 'mdate', '10');
  xmldoc := dbms_xmlgen.getxml(ctx);
  dbms_output.put_line(xmldoc);
  dbms_xmlgen.setbindvalue(ctx, 'mdate', '10');
  xmldoc := dbms_xmlgen.getxml(ctx);
  dbms_output.put_line(xmldoc);
  dbms_xmlgen.closecontext(ctx);
exception
 
when others then
    dbms_xmlgen.closecontext(ctx);
   
raise;
end;

 

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <EMPNO>7782</EMPNO>
  <ENAME>CLARK</ENAME>
  <JOB>MANAGER</JOB>
  <MGR>7839</MGR>
  <HIREDATE>09-6ÔÂ-81</HIREDATE>
  <SAL>2450</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7839</EMPNO>
  <ENAME>KING</ENAME>
  <JOB>PRESIDENT</JOB>
 <HIREDATE>17-11ÔÂ-81</HIREDATE>
  <SAL>5000</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7934</EMPNO>
  <ENAME>MILLER</ENAME>
  <JOB>CLERK</JOB>
  <MGR>7782</MGR>
  <HIREDATE>23-1ÔÂ-82</HIREDATE>
  <SAL>1300</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
</ROWSET>

<?xmlversion="1.0"?>
<ROWSET>
 <ROW>
  <EMPNO>7782</EMPNO>
  <ENAME>CLARK</ENAME>
  <JOB>MANAGER</JOB>
  <MGR>7839</MGR>
  <HIREDATE>09-6ÔÂ -81</HIREDATE>
  <SAL>2450</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7839</EMPNO>
  <ENAME>KING</ENAME>
  <JOB>PRESIDENT</JOB>
 <HIREDATE>17-11ÔÂ-81</HIREDATE>
  <SAL>5000</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7934</EMPNO>
  <ENAME>MILLER</ENAME>
  <JOB>CLERK</JOB>
  <MGR>7782</MGR>
  <HIREDATE>23-1ÔÂ-82</HIREDATE>
  <SAL>1300</SAL>
  <DEPTNO>10</DEPTNO>
 </ROW>
</ROWSET>


 

多个绑定变量

declare
  ctx   
number;
  xmldoc
clob;
begin
  ctx := dbms_xmlgen.newcontext('select * from scott.emp
where deptno = :no
and sal > :mdate');
  dbms_xmlgen.setbindvalue(ctx, 'no', '20');
  dbms_xmlgen.setbindvalue(ctx, 'mdate', '1000');
  xmldoc := dbms_xmlgen.getxml(ctx);
  dbms_output.put_line(xmldoc);
  dbms_xmlgen.closecontext(ctx);
exception
  whenothers then
    dbms_xmlgen.closecontext(ctx);
    raise;
end;

 

 

参考游标

declare
  ctx   number;
  maxrow number;
  xmldoc clob;
  refcur sys_refcursor;
begin
  dbms_lob.createtemporary(xmldoc, true);
  maxrow := 2;
  openrefcur for 'select * from scott.empwhere rownum <= :1'
    using maxrow;
  ctx := dbms_xmlgen.newcontext(refcur);
  -- xmldoc will have 2 rows
  dbms_xmlgen.getxml(ctx, xmldoc, dbms_xmlgen.none);
  dbms_output.put_line(xmldoc);
  dbms_lob.freetemporary(xmldoc);
  closerefcur;
  dbms_xmlgen.closecontext(ctx);
end;

 

 

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <EMPNO>7369</EMPNO>
  <ENAME>SMITH</ENAME>
  <JOB>CLERK</JOB>
  <MGR>7902</MGR>
  <HIREDATE>17-12ÔÂ-80</HIREDATE>
  <SAL>800</SAL>
  <DEPTNO>20</DEPTNO>
 </ROW>
 <ROW>
  <EMPNO>7499</EMPNO>
  <ENAME>ALLEN</ENAME>
  <JOB>SALESMAN</JOB>
  <MGR>7698</MGR>
  <HIREDATE>20-2ÔÂ-81</HIREDATE>
  <SAL>1600</SAL>
  <COMM>300</COMM>
  <DEPTNO>30</DEPTNO>
 </ROW>
</ROWSET>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CREATE TABLEemp_tab(

emp_id NUMBERPRIMARY KEY,

name VARCHAR2(20),

dept_id NUMBER);

 

TINSERT INTO emp_tabVALUES(30, 'Scott', NULL);

INSERT INTO emp_tabVALUES(31, 'Mary', NULL);

INSERT INTO emp_tabVALUES(40, 'John', NULL);

COMMIT;

CREATE TABLEtemp_clob_tab(result CLOB);

 

declare
  qryctx dbms_xmlgen.ctxhandle;
 
result clob;
begin
  qryctx := dbms_xmlgen.newcontext('select * from emp_tabwhere name = :name');
  -- set the row header to be employee
  dbms_xmlgen.setrowtag(qryctx, 'employee');
  -- drop nulls
  dbms_xmlgen.setbindvalue(qryctx, 'name', 'scott');
  dbms_xmlgen.setnullhandling(qryctx, dbms_xmlgen.drop_nulls);
 
result :=dbms_xmlgen.getxml(qryctx);
 
insert into temp_clob_tabvalues (result);
  -- null attribute
  dbms_xmlgen.setbindvalue(qryctx, 'name', 'mary');
  dbms_xmlgen.setnullhandling(qryctx, dbms_xmlgen.null_attr);
 
result :=dbms_xmlgen.getxml(qryctx);
 
insert into temp_clob_tabvalues (result);
  -- empty tag
  dbms_xmlgen.setbindvalue(qryctx, 'name', 'john');
  dbms_xmlgen.setnullhandling(qryctx, dbms_xmlgen.empty_tag);
 
result :=dbms_xmlgen.getxml(qryctx);
 
insert into temp_clob_tabvalues (result);
  --close context
  dbms_xmlgen.closecontext(qryctx);
end;

 

 

 

 

 

 

 

 

XML转化为关系型表数据

CREATE OR REPLACE TYPE address_type AS OBJECT ( 

address_line1 VARCHAR2(100), 

address_line2 VARCHAR2(100), 

address_line3 VARCHAR2(100) );

 

declare
  v_xml XMLTYPE;
  v_addr address_type;  
BEGIN
  -- create XML  
  v_xml := XMLTYPE('
<ADDRESS_TYPE>
 <ADDRESS_LINE1>line1</ADDRESS_LINE1>
<ADDRESS_LINE2>line2</ADDRESS_LINE2>
<ADDRESS_LINE3>line3</ADDRESS_LINE3>            
</ADDRESS_TYPE>
');
  --convert xml to object  
  v_xml.
toObject(v_addr);
  -- display xml output  
  DBMS_OUTPUT.put_line('Address Line 1: ' || v_addr.address_line1 ||
                                              ', Address Line 2: ' || v_addr.address_line2 ||
                                              ', dress Line 3: ' || v_addr.address_line3);
END;

 

输出结果

Address Line 1: line1,
Address Line 2: line2, 
Address Line 3: line3

 

 

 

 

 

CREATE TABLEdept_xml_tab OF XMLType;

 

INSERT INTOdept_xml_tab

VALUES(

XMLType('<Departmentdeptno="100">

<DeptName>Sports</DeptName>

<EmployeeList>

<Employeeempno="200"><Ename>John</Ename><Salary>33333</Salary>

</Employee>

<Employeeempno="300"><Ename>Jack</Ename><Salary>333444</Salary>

</Employee>

</EmployeeList>

</Department>'));

1 row created.

INSERT INTOdept_xml_tab

VALUES (

XMLType('<Departmentdeptno="200">

<DeptName>Sports</DeptName>

<EmployeeList>

<Employeeempno="400"><Ename>Marlin</Ename><Salary>20000</Salary>

</Employee>

</EmployeeList>

</Department>'));

1 row created.

COMMIT;

You can use SQL function XMLSequenceto un-nest the Employee list items as

top-level SQL rows:

SELECTextractValue(OBJECT_VALUE, '/Department/@deptno') AS deptno,

extractValue(value(em),'/Employee/@empno') AS empno,

extractValue(value(em),'/Employee/Ename') AS ename

FROM dept_xml_tab,

table(XMLSequence(extract(OBJECT_VALUE,

'/Department/EmployeeList/Employee')))em;

This returns the following:

DEPTNO EMPNO ENAME

---------------------------------

100 200 John

100 300 Jack

200 400 Marlin

 

 

 

 

 

 


CREATE TABLE tblControllerProjectsXML OF XMLType
 

insert into tblControllerProjectsXML
values
(
xmltype(
'<Solution>
       <Project ProjectID="5"Name="Unassigned TeamWork Project">
              <DatabaseMonitoredDBID="2" />
              <DatabaseMonitoredDBID="5" />
              <DatabaseMonitoredDBID="13" />
              <DatabaseMonitoredDBID="12" />
              <DatabaseMonitoredDBID="14" />
              <DatabaseMonitoredDBID="15" />
       </Project>
       <Project ProjectID="9"Name="Unassigned TeamWork Project">
              <DatabaseMonitoredDBID="9" />
              <DatabaseMonitoredDBID="10" />
              <DatabaseMonitoredDBID="15" />
       </Project>
</Solution>'
))

select * from
(
SELECT  extractValue(value(d),'/Database/@MonitoredDBID') AS MonDBID,
        extractValue(
value(p), '/Project/@ProjectID') AS ProId
FROM tblControllerProjectsXML X,
TABLE(XMLSequence(extract(X.OBJECT_VALUE,'/Solution/Project/Database'))) d,
TABLE(XMLSequence(extract(X.OBJECT_VALUE,'/Solution/Project'))) p
)
order by proid,mondbid desc

 

MONDBID

PROID

9

5

5

5

2

5

15

5

15

5

14

5

13

5

12

5

10

5

9

9

5

9

2

9

15

9

15

9

14

9

13

9

12

9

10

9

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值