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

MySQL的语言结构 - 模式对象名 - 函数名解析

数据库杂货铺 2021-05-17
441
函数名解析Function Name Parsing and Resolution
 
MySQL 支持内置(原生)函数、可加载函数和存储函数。本节介绍服务器如何识别内置函数的名称是用作函数调用还是用作标识符,以及服务器如何在不同类型的函数使用相同名称的情况下确定要使用哪个函数。
 
内置函数名解析Parsing
 
解析器使用默认规则来解析内置函数的名称。可以通过启用 IGNORE_SPACE SQL 模式来更改这些规则。
 
当解析器遇到作为内置函数名的单词时,它必须确定该名称是表示函数调用,还是表示对标识符(如表名或列名)的非表达式引用。例如,在以下语句中,第一个对 count 的引用是函数调用,而第二个引用是表名:
 
    SELECT COUNT(*) FROM mytable;
    CREATE TABLE count (i INT);
    复制
     
    只有在解析预期的表达式时,解析器才应该将内置函数的名称识别为函数调用。也就是说,在非表达式上下文中,允许函数名作为标识符。
     
    但是,一些内置函数有特殊的解析或实现考虑,因此解析器默认使用以下规则来区分它们的名称是用作函数调用还是用作非表达式上下文中的标识符:
     
     要将名称用作表达式中的函数调用,名称和跟随的 ( 之间不能有空格。
     
     相反,要使用函数名作为标识符,它后面不能紧跟着括号。
     
    函数调用在名称和括号之间不能有空格的要求只适用于有特殊考虑的内置函数。COUNT 就是其中一个。sql/lex.h 源文件列出了这些特殊函数的名称,对于这些函数,后面跟随的空格决定了对它们的解释:名称由宏 SYM_FN() 定义在 symbols[] 数组中。
     
    下面的列表列出了 MySQL 8.0 中受 IGNORE_SPACE 设置影响并在 sql/lex.h 源文件中列为特殊的函数。您可能会发现,将无空格要求应用于所有函数调用是最简单的。
     
     ADDDATE
     
     BIT_AND
     
     BIT_OR
     
     BIT_XOR
     
     CAST
     
     COUNT
     
     CURDATE
     
     CURTIME
     
     DATE_ADD
     
     DATE_SUB
     
     EXTRACT
     
     GROUP_CONCAT
     
     MAX
     
     MID
     
     MIN
     
     NOW
     
     POSITION
     
     SESSION_USER
     
     STD
     
     STDDEV
     
     STDDEV_POP
     
     STDDEV_SAMP
     
     SUBDATE
     
     SUBSTR
     
     SUBSTRING
     
     SUM
     
     SYSDATE
     
     SYSTEM_USER
     
     TRIM
     
     VARIANCE
     
     VAR_POP
     
     VAR_SAMP
     
    对于 sql/lex.h 中没有列为特殊的函数,空格并不重要。它们只有在表达式上下文中使用时才被解释为函数调用,否则可以自由地用作标识符。ASCII 就是一例。但是,对于这些未受影响的函数名,在表达式上下文中的解释可能会有所不同:如果具有给定名称的内置函数,func_name () 被解释为内置函数;否则,func_name () 将被解释为可加载函数或存储函数(如果存在具有该名称的函数)。
     
    IGNORE_SPACE SQL 模式可用于调整解析器如何处理对空格敏感的函数名:
     
    ● 在禁用 IGNORE_SPACE 的情况下,当名称和后面的括号之间没有空格时,解析器将名称解释为函数调用。即使在非表达式上下文中使用函数名,也是这种处理:
     
      mysql> CREATE TABLE count(i INT);
      ERROR 1064 (42000): You have an error in your SQL syntax ...
      near 'count(i INT)'
      复制
       
      要消除错误并将名称视为标识符,请在名称后面增加空格或将其作为带引号的标识符(或两者都使用):
       
        CREATE TABLE count (i INT);
        CREATE TABLE `count`(i INT);
        CREATE TABLE `count` (i INT);
        复制
         
        ● 如果启用了 IGNORE_SPACE,解析器就会放松函数名和后面的括号之间没有空格的要求。这为编写函数调用提供了更大的灵活性。例如,以下函数调用都是合法的:
         
          SELECT COUNT(*) FROM mytable;
          SELECT COUNT (*) FROM mytable;
          复制
           
          但是,启用 IGNORE_SPACE 还有副作用,即解析器将受影响的函数名视为保留字。这意味着名称后面的空格不再表示其用作标识符。该名称在函数调用中可以带有或不带有空格,但在非表达式上下文中会导致语法错误,除非它被引号引用。例如,启用 IGNORE_SPACE 的情况下,以下两个语句都会因语法错误失败,因为解析器将 count 解释为保留字:
           
            CREATE TABLE count(i INT);
            CREATE TABLE count (i INT);
            复制
             
            要在非表达式上下文中使用函数名,请将其写为带引号的标识符:
             
              CREATE TABLE `count`(i INT);
              CREATE TABLE `count` (i INT);
              复制
               
              要启用 IGNORE_SPACE SQL 模式,请使用以下语句:
               
                SET sql_mode = 'IGNORE_SPACE';
                复制
                 
                IGNORE_SPACE 也可以由某些其他复合模式启用,如 ANSI,这些模式的值包含它:
                 
                  SET sql_mode = 'ANSI';
                  复制
                   
                  要最小化 SQL 代码对 IGNORE_SPACE 设置的依赖性,请使用以下准则:
                   
                  ● 避免创建与内置函数同名的可加载函数或存储函数。
                   
                  ● 避免在非表达式上下文中使用函数名。例如,这些语句使用 count(受 IGNORE_SPACE 影响的函数名),因此如果启用 IGNORE_SPACE,则它们会失败,不管名称后面有或没有空格:
                   
                    CREATE TABLE count(i INT);
                    CREATE TABLE count (i INT);
                    复制
                     
                    如果必须在非表达式上下文中使用函数名,请将其写成带引号的标识符:
                     
                      CREATE TABLE `count`(i INT);
                      CREATE TABLE `count` (i INT);
                      复制
                       
                      函数名解析(Resolution
                       
                      以下规则描述了服务器如何处理对函数名的引用以创建和调用函数:
                       
                       内置函数和可加载函数
                       
                      如果尝试创建与内置函数同名的可加载函数,则会发生错误。
                       
                       内置函数和存储函数
                       
                      可以使用与内置函数相同的名称创建存储函数,但要调用存储函数,必须使用模式名称限定它。例如,如果在 test 模式中创建名为 PI 的存储函数,调用方式为 test.PI(),因为服务器解析 PI() 时不使用限定符将作为对内置函数的引用。如果存储函数名与内置函数名冲突,服务器将生成警告。警告可以通过 SHOW WARNINGS 命令显示。
                       
                       可加载函数和存储函数
                       
                      可加载函数和存储函数共享相同命名空间,因此不能使用相同的名称创建可加载函数和存储函数。
                       
                      前面的函数名解析规则对升级到实现新内置函数的 MySQL 版本有影响:
                       
                       如果已经创建了一个具有给定名称的可加载函数,将 MySQL 升级到实现具有相同名称的新内置函数的版本,则可加载函数将变得不可访问。若要更正此问题,请使用 DROP FUNCTION 删除可加载函数,并使用 CREATE FUNCTION 重新创建一个名称不冲突的可加载函数。然后修改受影响的代码以使用新名称。
                       
                       如果新版本的 MySQL 实现了与现有存储函数同名的内置函数,则有两种选择:重命名存储函数以使用非冲突名称,或者更改对函数的调用,使用模式限定符(即,使用 schema_name.func_name() 语法)。在这两种情况下,请相应地修改任何受影响的代码。
                       
                       
                       
                      注: 限于水平有限,本文中的 Parsing Resolution,本人未找到更合适解释,请自行注意区分!
                       
                       
                      官方文档:
                      https://dev.mysql.com/doc/refman/8.0/en/function-resolution.html
                      文章转载自数据库杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                      评论