• 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'  
    ;  
  • 相关阅读:
    .Net Core 5.x Api开发笔记 -- 消息队列RabbitMQ实现事件总线EventBus(二)
    .Net Core 5.x Api开发笔记 -- 消息队列RabbitMQ实现事件总线EventBus(一)
    SQL 入门教程:创建视图
    微信小程序-企业微信PC端,对接echarts图无法显示
    SQL查看表结构以及表说明
    Skoruba.IdentityServer4.STS.Identity 踩坑
    Docker部署文档
    eCharts图形在IE11中不能渲染
    Cookie中文乱码问题
    Blazor Webassembly多标签页实现
  • 原文地址:https://www.cnblogs.com/willspring/p/5840232.html
Copyright © 2020-2023  润新知