暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL的函数和运算符 - XML 函数(1)

数据库杂货铺 2021-07-17
752
XML 函数
 
名称
说明
ExtractValue()
使用 XPath 表示法从 XML 字符串中提取值
UpdateXML()
返回替换的 XML 片段
 
注意
 
可以通过在 mysql mysqldump 客户端使用 --xml 选项调用,从 MySQL 中获得 XML 格式的输出。
 
两个函数提供了基础的 XPath 1.0 (XML 路径语言,1.0)功能。本节稍后将提供关于 XPath 语法和用法的一些基本信息,但是,对这些主题的深入讨论超出了本部分的范围,您应该参考 XML 路径语言(XPath) 1.0 标准以获得确切的信息。
 
与这些函数一起使用的 XPath 表达式支持用户变量和局部存储程序变量。对用户变量进行弱检查,对存储程序的局部变量进行强检查:
 
● 用户变量(弱检查)。使用 $@variable_name 语法的变量(即用户变量)不会被检查。如果变量的类型错误,或者之前没有给变量赋值,服务器不会发出任何警告或错误。这也意味着用户要对任何排版错误负全部责任,因为如果(例如)需要 $@myvariable 的地方却使用了 $@myvairable,则不会给出警告。
 
示例:
 
    mysql> SET @xml = '<a><b>X</b><b>Y</b></a>';
    Query OK, 0 rows affected (0.00 sec)

    mysql> SET @i =1, @j = 2;
    Query OK, 0 rows affected (0.00 sec)

    mysql> SELECT @i, ExtractValue(@xml, '//b[$@i]');
    +------+--------------------------------+
    | @i | ExtractValue(@xml, '//b[$@i]') |
    +------+--------------------------------+
    | 1 | X |
    +------+--------------------------------+
    1 row in set (0.00 sec)

    mysql> SELECT @j, ExtractValue(@xml, '//b[$@j]');
    +------+--------------------------------+
    | @j | ExtractValue(@xml, '//b[$@j]') |
    +------+--------------------------------+
    | 2 | Y |
    +------+--------------------------------+
    1 row in set (0.00 sec)

    mysql> SELECT @k, ExtractValue(@xml, '//b[$@k]');
    +------+--------------------------------+
    | @k | ExtractValue(@xml, '//b[$@k]') |
    +------+--------------------------------+
    | NULL | |
    +------+--------------------------------+
    1 row in set (0.00 sec)
     
     存储程序中的变量(强检查)。存储程序内部可以使用 $variable_name 语法声明和使用变量。这些变量对于定义它们的存储程序来说是本地的,并且会对其类型和值进行严格检查。
     
    示例:
     
      mysql> DELIMITER |

      mysql> CREATE PROCEDURE myproc ()
      -> BEGIN
      -> DECLARE i INT DEFAULT 1;
      -> DECLARE xml VARCHAR(25) DEFAULT '<a>X</a><a>Y</a><a>Z</a>';
      ->
      -> WHILE i < 4 DO
      -> SELECT xml, i, ExtractValue(xml, '//a[$i]');
      -> SET i = i+1;
      -> END WHILE;
      -> END |
      Query OK, 0 rows affected (0.01 sec)

      mysql> DELIMITER ;

      mysql> CALL myproc();
      +--------------------------+---+------------------------------+
      | xml | i | ExtractValue(xml, '//a[$i]') |
      +--------------------------+---+------------------------------+
      | <a>X</a><a>Y</a><a>Z</a> | 1 | X |
      +--------------------------+---+------------------------------+
      1 row in set (0.00 sec)

      +--------------------------+---+------------------------------+
      | xml | i | ExtractValue(xml, '//a[$i]') |
      +--------------------------+---+------------------------------+
      | <a>X</a><a>Y</a><a>Z</a> | 2 | Y |
      +--------------------------+---+------------------------------+
      1 row in set (0.01 sec)

      +--------------------------+---+------------------------------+
      | xml | i | ExtractValue(xml, '//a[$i]') |
      +--------------------------+---+------------------------------+
      | <a>X</a><a>Y</a><a>Z</a> | 3 | Z |
      +--------------------------+---+------------------------------+
      1 row in set (0.01 sec)
       
      参数。作为参数传入的存储例程中 XPath 表达式中使用的变量也要接受强检查。
       
      包含用户变量或存储程序局部变量的表达式必须(符号除外)遵守 XPath 1.0 规范中给出的包含变量的 XPath 表达式规则。
       
      注意
       
      用于存储 XPath 表达式的用户变量被视为空字符串。因此,不可能将 XPath 表达式存储为用户变量。
       
      ● ExtractValue(xml_frag, xpath_expr)
       
      ExtractValue() 接受两个字符串参数,一个 XML 标记片段 xml_frag 和一个 XPath 表达式 xpath_expr (也称为定位器),它返回第一个文本节点的文本(CDATA),该节点是 XPath 表达式匹配的一个或多个元素的子元素。
       
      使用这个函数相当于在使用 xpath_expr 附加 /text() 之后执行匹配。换句话说,ExtractValue('<a><b>Sakila</b></a>', '/a/b') ExtractValue('<a><b>Sakila</b></a>', '/a/b/text()') 产生相同的结果。
       
      如果找到多个匹配,则每个匹配元素的第一个子文本节点的内容将通过空格分隔连成一个字符串返回(按匹配的顺序)
       
      如果没有为表达式找到匹配的文本节点(包括隐式的 /text())——无论出于什么原因,只要 xpath_expr 有效,并且 xml_frag 由正确嵌套和封闭的元素组成——将返回一个空字符串。对空元素不进行任何匹配。
       
      如果需要确定在 xml_frag 中是否没有找到匹配的元素,或者找到了这样的元素但没有包含子文本节点,则应该测试 XPath count() 函数的表达式的结果。例如,这两个语句都返回一个空字符串,如下所示:
       
        mysql> SELECT ExtractValue('<a><b/></a>', '/a/b');
        +-------------------------------------+
        | ExtractValue('<a><b/></a>', '/a/b') |
        +-------------------------------------+
        | |
        +-------------------------------------+
        1 row in set (0.00 sec)

        mysql> SELECT ExtractValue('<a><c/></a>', '/a/b');
        +-------------------------------------+
        | ExtractValue('<a><c/></a>', '/a/b') |
        +-------------------------------------+
        | |
        +-------------------------------------+
        1 row in set (0.00 sec)
         
        但是,你可以用下面的方法来确定是否存在一个匹配的元素:
         
          mysql> SELECT ExtractValue('<a><b/></a>', 'count(/a/b)');
          +-------------------------------------+
          | ExtractValue('<a><b/></a>', 'count(/a/b)') |
          +-------------------------------------+
          | 1 |
          +-------------------------------------+
          1 row in set (0.00 sec)

          mysql> SELECT ExtractValue('<a><c/></a>', 'count(/a/b)');
          +-------------------------------------+
          | ExtractValue('<a><c/></a>', 'count(/a/b)') |
          +-------------------------------------+
          | 0 |
          +-------------------------------------+
          1 row in set (0.01 sec)
           
          重要
           
          ExtractValue() 只返回 CDATA,不返回可能包含在匹配标记中的任何标记,也不返回它们的任何内容(参见下面示例中返回的 val1 结果)
           
            mysql> SELECT
            -> ExtractValue('<a>ccc<b>ddd</b></a>', '/a') AS val1,
            -> ExtractValue('<a>ccc<b>ddd</b></a>', '/a/b') AS val2,
            -> ExtractValue('<a>ccc<b>ddd</b></a>', '//b') AS val3,
            -> ExtractValue('<a>ccc<b>ddd</b></a>', '/b') AS val4,
            -> ExtractValue('<a>ccc<b>ddd</b><b>eee</b></a>', '//b') AS val5;

            +------+------+------+------+---------+
            | val1 | val2 | val3 | val4 | val5 |
            +------+------+------+------+---------+
            | ccc | ddd | ddd | | ddd eee |
            +------+------+------+------+---------+
             
            此函数使用当前的 SQL 排序规则与 contains() 进行比较,执行与其他字符串函数(CONCAT())相同的排序规则聚合。
             
            (以前总是使用二进制比较,即区分大小写的比较)
             
            如果 xml_frag 包含没有正确嵌套或关闭的元素,则返回 NULL,并生成一个警告,如下例所示:
             
              mysql> SELECT ExtractValue('<a>c</a><b', '//a');
              +-----------------------------------+
              | ExtractValue('<a>c</a><b', '//a') |
              +-----------------------------------+
              | NULL |
              +-----------------------------------+
              1 row in set, 1 warning (0.00 sec)

              mysql> SHOW WARNINGS\G
              *************************** 1. row ***************************
              Level: Warning
              Code: 1525
              Message: Incorrect XML value: 'parse error at line 1 pos 11:
              END-OF-INPUT unexpected ('>' wanted)'
              1 row in set (0.00 sec)

              mysql> SELECT ExtractValue('<a>c</a><b/>', '//a');
              +-------------------------------------+
              | ExtractValue('<a>c</a><b/>', '//a') |
              +-------------------------------------+
              | c |
              +-------------------------------------+
              1 row in set (0.00 sec)
               
              ● UpdateXML(xml_target, xpath_expr, new_xml)
               
              这个函数用新的 XML 片段 new_xml 替换给定 XML 标记 xml_target 片段的单个部分,然后返回更改后的 XML。被替换的 xml_target 部分与用户提供的 XPath 表达式 xpath_expr 匹配。
               
              如果没有找到匹配 xpath_expr 的表达式,或者找到多个匹配,则函数返回原始的 xml_target XML 片段。所有三个参数都应该是字符串。
               
                mysql> SELECT
                -> UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1,
                -> UpdateXML('<a><b>ccc</b><d></d></a>', '/b', '<e>fff</e>') AS val2,
                -> UpdateXML('<a><b>ccc</b><d></d></a>', '//b', '<e>fff</e>') AS val3,
                -> UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val4,
                -> UpdateXML('<a><d></d><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val5
                -> \G

                *************************** 1. row ***************************
                val1: <e>fff</e>
                val2: <a><b>ccc</b><d></d></a>
                val3: <a><e>fff</e><d></d></a>
                val4: <a><b>ccc</b><e>fff</e></a>
                val5: <a><d></d><b>ccc</b><d></d></a>
                 
                下面是一些基本 XPath 表达式的描述和示例
                 
                ● /tag
                 
                当且仅当 <tag/> 是根元素时匹配 <tag/>
                 
                例如:/a <a><b/></a> 中有一个匹配,因为它匹配最外层()标记。它不匹配 <b><a/></b> 中的内部元素,因为在本例中它是另一个元素的子元素。
                 
                ● /tag1/tag2
                 
                当且仅当 <tag2/> <tag1/> 的子元素,且 <tag1/> 是根元素时匹配。
                 
                例如:/a/b 匹配 XML 片段 <a><b/></a> 中的 b 元素,因为它是根元素 a 的子元素。在 <b><a/></b> 中没有匹配,因为在这种情况下,b 是根元素(不是其他元素的子元素)。此 XPath 表达式在 <a><c><b/></c></a> 中也没有匹配,因为 b a 的后代,但不是 a 的孩子节点。
                 
                此构造可扩展到三个或更多元素。例如,XPath 表达式 /a/b/c 匹配 <a><b><c/></b></a> 片段中的 c 元素。
                 
                ● //tag
                 
                匹配 <tag> 的任何实例。
                 
                例如://a 匹配以下结构中的 a 元素:<a><b><c/></b></a>; <c><a><b/></a></b>; <c><b><a/></b></c>
                 
                //可以与 / 组合使用。例如,//a/b 匹配片段 <a><b/></a> <c><a><b/></a></c> 中的 b 元素。
                 
                注意
                 
                //tag 相当于 /descendant-or-self::*/tag。一个常见的错误是将其与 /descendant-or-self::tag 混淆,尽管后一种表达式实际上会导致非常不同的结果,如图所示:
                 
                  mysql> SET @xml = '<a><b><c>w</c><b>x</b><d>y</d>z</b></a>';
                  Query OK, 0 rows affected (0.00 sec)

                  mysql> SELECT @xml;
                  +-----------------------------------------+
                  | @xml |
                  +-----------------------------------------+
                  | <a><b><c>w</c><b>x</b><d>y</d>z</b></a> |
                  +-----------------------------------------+
                  1 row in set (0.00 sec)

                  mysql> SELECT ExtractValue(@xml, '//b[1]');
                  +------------------------------+
                  | ExtractValue(@xml, '//b[1]') |
                  +------------------------------+
                  | x z |
                  +------------------------------+
                  1 row in set (0.00 sec)

                  mysql> SELECT ExtractValue(@xml, '//b[2]');
                  +------------------------------+
                  | ExtractValue(@xml, '//b[2]') |
                  +------------------------------+
                  | |
                  +------------------------------+
                  1 row in set (0.01 sec)

                  mysql> SELECT ExtractValue(@xml, '/descendant-or-self::*/b[1]');
                  +---------------------------------------------------+
                  | ExtractValue(@xml, '/descendant-or-self::*/b[1]') |
                  +---------------------------------------------------+
                  | x z |
                  +---------------------------------------------------+
                  1 row in set (0.06 sec)

                  mysql> SELECT ExtractValue(@xml, '/descendant-or-self::*/b[2]');
                  +---------------------------------------------------+
                  | ExtractValue(@xml, '/descendant-or-self::*/b[2]') |
                  +---------------------------------------------------+
                  | |
                  +---------------------------------------------------+
                  1 row in set (0.00 sec)


                  mysql> SELECT ExtractValue(@xml, '/descendant-or-self::b[1]');
                  +-------------------------------------------------+
                  | ExtractValue(@xml, '/descendant-or-self::b[1]') |
                  +-------------------------------------------------+
                  | z |
                  +-------------------------------------------------+
                  1 row in set (0.00 sec)

                  mysql> SELECT ExtractValue(@xml, '/descendant-or-self::b[2]');
                  +-------------------------------------------------+
                  | ExtractValue(@xml, '/descendant-or-self::b[2]') |
                  +-------------------------------------------------+
                  | x |
                  +-------------------------------------------------+
                  1 row in set (0.00 sec)
                   
                  ● * 操作符充当匹配任何元素的“通配符”。例如,表达式 /*/b 匹配 XML 片段 <a><b/></a> <c><b/></c> 中的 b 元素。但是,表达式不会与 <b><a/></b> 片段产生匹配,因为 b 必须是其他元素的子元素。通配符可以在任何位置使用:表达式 /*/b/* 匹配 b 元素的任何子元素,且 b 元素本身不是根元素的情况。
                   
                  ● 可以使用 | (UNION) 操作符匹配多个定位器中的任何一个。例如,表达式 //b|//c 匹配 XML 目标中的所有 b c 元素。
                   
                  ● 也可以根据元素的一个或多个属性的值来匹配元素。这是使用语法 tag[@attribute="value"] 完成的。例如,表达式 //b[@id="idB"] 匹配 <a><b id="idA"/><c/><b id="idB"/></a> 片段中的第二个 b 元素。要匹配任何具有 attribute="value" 的元素,请使用 XPath 表达式 //*[attribute="value"]
                   
                  要过滤多个属性值,只需连续使用多个属性比较子句。例如,表达式 //b[@c="x"][@d="y"] 匹配在给定 XML 片段中的任何地方出现的 <b c="x" d="y"/> 元素。
                   
                  要找到相同属性匹配多个值的元素,可以使用 | 操作符连接多个定位器。例如,要匹配 c 属性值为 23 17 的所有 b 元素,使用表达式 //b[@c="23"]|//b[@c="17"]。也可以使用逻辑 or 操作符://b[@c="23" or @c="17"]
                   
                  注意
                   
                  or | 的区别在于 or 连接条件,而 | 连接结果集。
                   
                   
                  官方网址:
                  https://dev.mysql.com/doc/refman/8.0/en/xml-functions.html
                  文章转载自数据库杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论