oracle xml操作


 

 

/*=====================生成\修改xml========================= */
--xmlelement多個標簽層級
SELECT XMLELEMENT("TEST",
                  XMLELEMENT("AA",
                             XMLELEMENT("BB", 'XXX'),
                             XMLELEMENT("CC", 'XXX')))
  FROM DUAL;
  SELECT XMLELEMENT("test")
    FROM DUAL
----XMLATTRIBUTES 多個屬性
SELECT XMLELEMENT("TEST",
                  '123',
                  XMLELEMENT("AA",
                             XMLATTRIBUTES('1235678' "test_attribute"),
                             XMLELEMENT("BB",
                                        XMLATTRIBUTES('z' "attr",NULL "XO"),
                                        'XXX'),
                             XMLELEMENT("CC", 'XXX')),
                  'qwe')
  FROM DUAL;
  
--xmlforest ,如果要定義標簽節點屬性值則不能用
SELECT XMLELEMENT("TEST",XMLFOREST(NULL "WW",'1' "XX",'3' "xx")) FROM dual;
--關於空值是否會生成生應的標簽
--1、xmlelement 空值或null都會有結束的標簽不會出現</> ,xmlattributes 空值或null對應的鍵名不會出現
    SELECT XMLELEMENT("test", XMLELEMENT("test1", XMLATTRIBUTES(1 "test1_attribute"),NULL),
                              XMLELEMENT("test2", XMLATTRIBUTES('' "test2_attribute"),''),
                              XMLELEMENT("test3", XMLATTRIBUTES(NULL "test3_attribute")),'haha')
    FROM dual;
--2.xmlforest  null整個標簽名不會出現,單引號會出現
SELECT XMLELEMENT("test", XMLFOREST(NULL "test1",'' test3)) FROM dual;
--xmlagg 生成xml片段
WITH t AS (SELECT '1' a,'A' b FROM dual)-- UNION ALL SELECT '2','A' b FROM dual UNION ALL SELECT '3','B' b FROM dual)
SELECT XMLELEMENT("KK",XMLAGG(XMLELEMENT("TEST",a))) FROM t GROUP BY b;
SELECT XMLELEMENT("TT",(SELECT XMLAGG(XMLELEMENT("TEST",a)  ORDER BY a) FROM t)) FROM dual;
--排序
SELECT XMLELEMENT("KK",XMLAGG(XMLELEMENT("TEST",a) ORDER BY a DESC)) FROM t GROUP BY b;
--可生成無效的xml,xml只能有一個根結節點
SELECT XMLAGG(XMLELEMENT("TEST",a)) FROM t
--以下會報錯
SELECT XMLTYPE.CreateXML('<dummy>X</dummy><dummy>y</dummy>') FROM dual;

--聚合,可替代 sys_path_connect_by,listagg
WITH Q AS
 (SELECT 1 KEY, 'A' X
    FROM DUAL
  UNION ALL
  SELECT 2 KEY, 'B' X
    FROM DUAL
  UNION ALL
  SELECT 3 KEY, 'A' X
    FROM DUAL
  UNION ALL
  SELECT 4 KEY, 'A' X
    FROM DUAL)
--SELECT X,
--RTRIM(
--XMLAGG (XMLELEMENT(e, key||',') ORDER BY key)
--) AS concatval
--FROM q
--GROUP BY X;
SELECT X,
       RTRIM(XMLAGG(XMLELEMENT(E, KEY || ',') ORDER BY KEY)
             .EXTRACT('//text()'),
             ',') AS CONCATVAL
  FROM Q
 GROUP BY X;
-- xmlconcat 拼接xml元素
SELECT XMLCONCAT(XMLELEMENT("x", Xmlattributes('123' "xmlns"),XMLELEMENT("y", '10'),XMLELEMENT("y", '20')), 
XMLELEMENT("x",Xmlattributes('xyz' "xmlns"), XMLELEMENT("y", '20'),XMLELEMENT("y", '10')),
XMLELEMENT("x",Xmlattributes('xyz' "xmlns"), XMLELEMENT("y", '60'),XMLELEMENT("y", '10')))  FROM dual;
 
--UPDATEXML 修改xml標准內容和attribute
--UPDATEXML(xmltype_instance, xpath_expression, value_expr, namespace_expr)
--xml:
<DEPT>
  <EMPID>1</EMPID>
  <EMPNAME>Martin Chadderton</EMPNAME>
  <SALARY>1000</SALARY>
</DEPT> 
--可以同時修改多個標簽內容
SELECT UPDATEXML(XMLTYPE('<DEPT>
                          <EMPID>1</EMPID>
                           <EMPNAME>Martin Chadderton</EMPNAME>
                           <SALARY>1000</SALARY>
                         </DEPT>'),
                 '/DEPT/SALARY/text()', --通過XPath表達式,指定要修改的標簽元素 
                 '1100',
                 '/DEPT/EMPID/text()',
                 'AA')
  FROM DUAL;
--如果標簽元素沒有值,則更新該標簽的數據時也會無效,這是Oracle bug 2962474
SELECT UPDATEXML(XMLTYPE('<DEPT>
    <EMPID>1</EMPID>
      <EMPNAME>Martin Chadderton</EMPNAME>
     <SALARY></SALARY>
    </DEPT>'),
                 '/DEPT/SALARY/text()',
                 '1100')
  FROM DUAL;
--可通過下面語句解決,重寫該標簽,找不到對應要修改的標簽不會報錯
SELECT UPDATEXML(XMLTYPE('<DEPT>
    <EMPID>1</EMPID>
      <EMPNAME>Martin Chadderton</EMPNAME>
      <SALARY />
    </DEPT>'),
                 '/DEPT/SALARY',
                 XMLTYPE('<SALARY>1100</SALARY>'))
  FROM DUAL;
--修改屬性,找不到對應要修改的屬性不會報錯
SELECT
      UPDATEXML(XMLTYPE('<DEPT>
                           <EMPID>1</EMPID>
                           <EMPNAME>Martin Chadderton</EMPNAME>
                           <SALARY taxable="yes">3</SALARY>
                         </DEPT>'),
      '/DEPT/SALARY/@taxable', 'no','/DEPT/SALARY/text()','123')
    FROM dual;
--更新為null
--1.
SELECT
      UPDATEXML(XMLTYPE('<DEPT>
                           <EMPID>1</EMPID>
                           <EMPNAME>Martin Chadderton</EMPNAME>
                          <SALARY>1000</SALARY>
                         </DEPT>'),
     '/DEPT/SALARY/text()', NULL)
    FROM dual;
--2、
SELECT
      UPDATEXML(XMLTYPE('<DEPT>
                           <EMPID>1</EMPID>
                           <EMPNAME>Martin Chadderton</EMPNAME>
                           <SALARY taxable="yes">1000</SALARY>
                         </DEPT>'),
      '/DEPT/SALARY', null)
    FROM dual;
--更新父節點,為null則所有字節點都消失,剩下父節點
SELECT
      UPDATEXML(XMLTYPE('<DEPT>
                           <EMPID>1</EMPID>
                           <EMPNAME>Martin Chadderton</EMPNAME>
                           <SALARY taxable="yes">1000</SALARY>
                         </DEPT>'),
      '/DEPT', null)
    FROM dual;
--去除父節點下所有字節點的值(采用通配符)
--1.
SELECT
      UPDATEXML(XMLTYPE('<DEPT>
                           <EMPID>1</EMPID>
                           <EMPNAME>Martin Chadderton</EMPNAME>
                           <SALARY>1000</SALARY>
                         </DEPT>'),
    '/DEPT//*', NULL)
    FROM dual;
--2.如果父節點有屬性,一定要指出,或則更新不到數據
SELECT
      UPDATEXML(XMLTYPE('<DEPT xmlns="xyz">
    <EMPID>1</EMPID>
      <EMPNAME>Martin Chadderton</EMPNAME>
      <SALARY>1000</SALARY>
    </DEPT>'),
     '/DEPT/EMPID/text()', NULL,
     '/DEPT/EMPNAME/text()', NULL,
     '/DEPT/SALARY/text()', NULL,'xmlns="xyz"')
   FROM dual;

--高級應用,指定的namespace_expr 下,更新z='10'的數值
DECLARE
    X XMLTYPE := XMLTYPE('<x xmlns="xyz"><y>10</y><z>20</z><z>10</z></x>');
BEGIN
    SELECT UPDATEXML(X, '/x/z[. = "10"]/text()','30','xmlns="xyz"')
      INTO X
      FROM DUAL;
    DBMS_OUTPUT.PUT_LINE(X.GETCLOBVAL);
END;

--UPDATEXML可修改非標准xml(根節點多個)
DECLARE
    X XMLTYPE := XMLTYPE('<x xmlns="xyz"><y>10</y><y>20</y></x>');
BEGIN
    SELECT UPDATEXML(XMLCONCAT(XMLELEMENT("x", Xmlattributes('123' "xmlns"),XMLELEMENT("y", '10'),XMLELEMENT("y", '20')), 
XMLELEMENT("x",Xmlattributes('xyz' "xmlns"), XMLELEMENT("y", '20'),XMLELEMENT("y", '10')),
XMLELEMENT("x",Xmlattributes('xyz' "xmlns"), XMLELEMENT("y", '10'),XMLELEMENT("y", '10'))), '/x/y[. = "10"]/text()','AA','xmlns="xyz"')
      INTO X
      FROM DUAL;
    DBMS_OUTPUT.PUT_LINE(X.GETCLOBVAL);
END;

--刪除某個節點
--1.通用做法 10.1之前
DECLARE
      x   XMLTYPE := XMLTYPE('<a><b><c>10X</c></b><b><c>20</c></b><b><c>10Y</c></b></a>');
    BEGIN
      SELECT UPDATEXML(x, '/a/b[starts-with(c,10)]', NULL)
            INTO x
            FROM dual;
      dbms_output.put_line(REPLACE(x.getstringval,'<b/>',''));
    END;
--2.10.2及以上(DELETEXML)
--DELETEXML(xmltype_instance, xpath_expression, namespace_expr)
DECLARE
      x   XMLTYPE := XMLTYPE('<a xmlns="xyz"><b><c>10X</c></b><b><c>20</c></b><b><c>10Y</c></b></a>');
    BEGIN
      SELECT DELETEXML(x, '/a/b[starts-with(c,10)]','xmlns="xyz"')
            INTO x
            FROM dual;
      dbms_output.put_line(x.getstringval);
    END;
--如果有父節點有屬性,一定要指出,或則刪不了
DECLARE
      x  XMLTYPE := XMLTYPE('<a xmlns="xyz"><b><c>10X</c></b><b xmlns="xyz"><c>110X</c></b></a>');
    BEGIN
      SELECT DELETEXML(x, '/a/b','xmlns="xyz"')
        INTO x
        FROM dual;
      dbms_output.put_line(x.getclobval);
    END;
--XMLROOT 增加xml開頭信息,這個目前不支持編碼的指定
SELECT XMLROOT(XMLELEMENT("x", dummy), VERSION '1.0' , STANDALONE YES)  FROM dual;
--XMLCOMMENT 增加xml注釋 EXTRACT('/')在sqlplus顯示的時候格式會好看一些
SELECT XMLELEMENT("x",
             XMLELEMENT("x1", dummy),
             XMLCOMMENT('Test Comment'),
             XMLELEMENT("x2", dummy)
           ).EXTRACT('/')
      FROM dual;

--XMLCDATA 10g之前沒有這個函數, CDATA節是用來告訴XML解析器將一切作為數據。如果你有一個要求發送信息,例如,有很多XML“非法”字符,如&、<和>,
--但不能包含 ]]>
 SELECT UPDATEXML(XMLELEMENT("parent", XMLCDATA('Here is a string with a < and a >')),'/parent//text()','123')
  FROM dual;
  
   SELECT XMLELEMENT("parent", XMLCDATA('Here is a![[ string with a < and a'))  FROM dual;
--如果值為空或null不會生成CDATA
  SELECT XMLELEMENT("x", XMLCDATA(''))    FROM dual;

 

/*=====================通過xml獲取數據========================= */
--xmltable 
--XMLTABLE(<xpath/query> PASSING <xmltype document>
--                        COLUMNS <column alias> <datatype> PATH <xpath/query>, {<column alias> <datatype> PATH <xpath/query>...})
select * 
from tt,xmltable('/ipmp/head' passing xmltype(tt.clb_content)
              columns reference varchar2(99) path 'reference',
                      busiCode varchar2(99) path 'busiCode') 
                      WHERE clb_content LIKE '%ipmp%';

--如果字段類型長度比值還短,會進行截取              
select *
from xmltable('/a/b' passing xmltype('<a><b>1120</b><b>21230</b></a>')
              columns b varchar2(2) path '.');
--不用xmltable的實現方式
SELECT 
  EXTRACTVALUE(VALUE(t), '/a/b') b,
  EXTRACTVALUE(VALUE(t), '/a/c') a
FROM 
  TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE('<a><b>10</b><c>20</c></a>'), '/a'))) t;
--指定返回類型
SELECT * 
  FROM XMLTABLE('/a/b' 
                PASSING XMLTYPE('<a><b>10</b></a>')
                COLUMNS b_as_varchar2 VARCHAR2(2) PATH '../b',
                        b_as_xmltype  XMLTYPE     PATH '/',
                        b_as  VARCHAR2(3)     PATH '.');

--獲取屬性
select *
from xmltable('/a' passing xmltype('<a><b battr="1">10</b><c>20</c></a>')
              columns b varchar2(2) path 'b',
                      battr varchar2(1) path 'b/@battr',
                      c varchar2(2) path 'c');
--獲取指定命名空間的相關標簽
select t.b, t.c
from XMLTABLE(XMLNAMESPACES('namespace2' AS "ns1"),
              '/t/ns1:a' 
              PASSING XMLTYPE('<t><a xmlns="namespace1"><b>aa</b><c>bb</c></a><a xmlns="namespace2"><b>10</b><c>20</c></a></t>')
              COLUMNS b VARCHAR2(2) PATH 'ns1:b',
                      c VARCHAR2(2) PATH 'ns1:c') t;

--獲取指定不同命名空間的相關標簽,如果xml里面有指定,在獲取的時候也要指定,否則取不到數據
select t.b, t.c
from XMLTABLE(XMLNAMESPACES('namespace1' AS "ns1", 'namespace2' AS "ns2"),
              '/ns1:a' 
              PASSING XMLTYPE('<a xmlns="namespace1"><b xmlns="namespace2">10</b><c>20</c></a>')
              COLUMNS b VARCHAR2(2) PATH 'ns2:b',
                      c VARCHAR2(2) PATH 'ns1:c') t;--如果節點下有相關的標簽,則可以通過下面去獲取各自的值
--12c
SELECT c.ref, c.val
  FROM XMLTABLE('/a/b/c'
                PASSING XMLTYPE('<a><b><ref>1</ref><c>10</c><c>20</c><c>30</c></b></a>')
                RETURNING SEQUENCE BY REF
                COLUMNS ref INTEGER PATH '../ref',
                        val INTEGER PATH '/') p
--12c以下 
SELECT p.ref, c.val
  FROM XMLTABLE('/a/b'
                PASSING XMLTYPE('<a><b><ref>1</ref><cc>1</cc><c>10</c><c>20</c><c>30</c></b></a>')
                COLUMNS ref INTEGER PATH 'ref',
                        cxml  XMLTYPE PATH 'c') p,
       XMLTABLE('/c'
                PASSING p.cxml
                COLUMNS val INTEGER PATH '/') c

---XMLEXISTS 11g以上才有 XMLEXISTS(<xpath/xquery> PASSING <xmltype document>) 判斷xml是否存在節點
WITH x AS (
SELECT XMLTYPE('<a><b></b></a>') a FROM dual
)
SELECT CASE WHEN XMLEXISTS('/a/c' PASSING x.a) THEN 'TRUE' ELSE 'FALSE' END
FROM x;

--帶命名空間
WITH x AS (
SELECT XMLTYPE('<a xmlns="abc"><b xmlns="q"></b></a>') a FROM dual
)
SELECT CASE WHEN XMLEXISTS('declare namespace ns1="abc";declare namespace ns2="q"; (::) /ns1:a/ns2:b' PASSING x.a) THEN 'TRUE' ELSE 'FALSE' END
FROM x;

--例子
WITH t as (select xmltype('<CODEVALUE>AA</CODEVALUE>') xmlvar from dual )
select xmlvar
from t
where XMLEXISTS ('/CODEVALUE[.="AA"]' PASSING xmlvar);

WITH t as (select xmltype('
<ROWSET>
<ROW>
  <CODETYPE>ClaimCause</CODETYPE>
  <CODESEQNO>1</CODESEQNO>
  <CODEVALUE>A</CODEVALUE>
  </ROW>
<ROW>
  <CODETYPE>Claim</CODETYPE>
  <CODESEQNO>1</CODESEQNO>
  <CODEVALUE>AA</CODEVALUE>
</ROW>
<ROW>
  <VALID>Y</VALID>
  <CODETYPE>Remarks</CODETYPE>
  <CODESEQNO>1</CODESEQNO>
</ROW>
</ROWSET>
') xmlvar from dual )
select xmlvar
from t
where XMLEXISTS ('/ROWSET/ROW/CODEVALUE[.="AA" ]'        PASSING xmlvar)
  AND XMLEXISTS ('/ROWSET/ROW/CODETYPE[.="ClaimCause"]' PASSING xmlvar)
AND
XMLEXISTS ('/ROWSET/ROW[CODEVALUE="AA" and CODETYPE="Claim"]' PASSING xmlvar);


WITH t as (select xmltype('  
<ROWSET>  
<ROW>  
  <CODETYPE>ClaimCause</CODETYPE>  
  <CODESEQNO>1</CODESEQNO>  
  <CODEVALUE>A</CODEVALUE>  
  </ROW>  
<ROW>  
  <CODETYPE>Claim</CODETYPE>  
  <CODESEQNO>1</CODESEQNO>  
  <CODEVALUE>AA</CODEVALUE>  
</ROW>  
<ROW>  
  <VALID>Y</VALID>  
  <CODETYPE>Remarks</CODETYPE>  
  <CODESEQNO>1</CODESEQNO>  
</ROW>  
</ROWSET>  
') xmlvar from dual )  
select xmlvar , CODETYPE, CODEVALUE  
from t  
    ,xmltable ('for $i in /ROWSET/ROW  
                return $i'  
                passing xmlvar  
                columns CODETYPE varchar2(100) path 'CODETYPE'  
                      ,CODEVALUE varchar2(100) path 'CODEVALUE'  
                ) x  
where x.codevalue = 'AA'  
and  x.codetype = 'ClaimCause'  
;  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM