9.2.5 Function Name Parsing and Resolution函数名称解析与解析

MySQL supports built-in (native) functions, loadable functions, and stored functions. This section describes how the server recognizes whether the name of a built-in function is used as a function call or as an identifier, and how the server determines which function to use in cases when functions of different types exist with a given name.MySQL支持内置(本机)函数、可加载函数和存储函数。本节介绍服务器如何识别内置函数的名称是用作函数调用还是用作标识符,以及在给定名称存在不同类型函数的情况下,服务器如何确定使用哪个函数。

Built-In Function Name Parsing内置函数名称解析

The parser uses default rules for parsing names of built-in functions. These rules can be changed by enabling the IGNORE_SPACE SQL mode.解析器使用默认规则来解析内置函数的名称。可以通过启用IGNORE_SPACE SQL模式来更改这些规则。

When the parser encounters a word that is the name of a built-in function, it must determine whether the name signifies a function call or is instead a nonexpression reference to an identifier such as a table or column name. For example, in the following statements, the first reference to count is a function call, whereas the second reference is a table name:当解析器遇到一个单词是内置函数的名称时,它必须确定该名称是表示函数调用,还是表示对标识符(如表或列名)的非压缩引用。例如,在以下语句中,对count的第一个引用是函数调用,而第二个引用是表名:

SELECT COUNT(*) FROM mytable;
CREATE TABLE count (i INT);

The parser should recognize the name of a built-in function as indicating a function call only when parsing what is expected to be an expression. That is, in nonexpression context, function names are permitted as identifiers.只有在解析预期的表达式时,解析器才应该将内置函数的名称识别为指示函数调用。也就是说,在非压缩上下文中,函数名被允许作为标识符。

However, some built-in functions have special parsing or implementation considerations, so the parser uses the following rules by default to distinguish whether their names are being used as function calls or as identifiers in nonexpression context:然而,一些内置函数有特殊的解析或实现注意事项,因此解析器默认情况下使用以下规则来区分它们的名称是用作函数调用还是用作非压缩上下文中的标识符:

  • To use the name as a function call in an expression, there must be no whitespace between the name and the following ( parenthesis character.要将名称用作表达式中的函数调用,名称和后面跟着的(括号字符之间不能有空格。

  • Conversely, to use the function name as an identifier, it must not be followed immediately by a parenthesis.相反,要将函数名用作标识符,它后面不能紧跟括号。

The requirement that function calls be written with no whitespace between the name and the parenthesis applies only to the built-in functions that have special considerations. 函数调用必须在名称和括号之间不留空格,这一要求仅适用于有特殊注意事项的内置函数。COUNT is one such name. The sql/lex.h source file lists the names of these special functions for which following whitespace determines their interpretation: names defined by the SYM_FN() macro in the symbols[] array.COUNT就是这样一个名字。sql/xs.h源文件列出了这些特殊函数的名称,下面的空格决定了它们的解释:由symbols[]数组中的SYM_FN()宏定义的名称。

The following list names the functions in MySQL 8.0 that are affected by the IGNORE_SPACE setting and listed as special in the sql/lex.h source file. 以下列表列出了MySQL 8.0中受IGNORE_SPACE设置影响的函数,这些函数在sql/lex.h源文件中列为特殊函数。You may find it easiest to treat the no-whitespace requirement as applying to all function calls.您可能会发现,将无空格要求视为适用于所有函数调用是最简单的。

  • 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

For functions not listed as special in sql/lex.h, whitespace does not matter. They are interpreted as function calls only when used in expression context and may be used freely as identifiers otherwise. 对于sql/lex.h中未列为特殊函数的函数,空白并不重要。它们仅在表达式上下文中使用时被解释为函数调用,否则可以自由用作标识符。ASCII is one such name. However, for these nonaffected function names, interpretation may vary in expression context: func_name () is interpreted as a built-in function if there is one with the given name; if not, func_name () is interpreted as a loadable function or stored function if one exists with that name.ASCII就是这样一个名称。然而,对于这些不受影响的函数名,在表达式上下文中的解释可能会有所不同:如果存在具有给定名称的内置函数,则将func_name()解释为内置函数;否则,func_name()将被解释为可加载函数或存储函数(如果存在)。

The IGNORE_SPACE SQL mode can be used to modify how the parser treats function names that are whitespace-sensitive:IGNORE_SPACE SQL模式可用于修改解析器处理区分空格的函数名的方式:

  • With IGNORE_SPACE disabled, the parser interprets the name as a function call when there is no whitespace between the name and the following parenthesis. This occurs even when the function name is used in nonexpression context:IGNORE_SPACE被禁用的情况下,当名称和下面的括号之间没有空格时,解析器将名称解释为函数调用。即使在非压缩上下文中使用函数名,也会出现这种情况:

    mysql> CREATE TABLE count(i INT);
    ERROR 1064 (42000): You have an error in your SQL syntax ...
    near 'count(i INT)'

    To eliminate the error and cause the name to be treated as an identifier, either use whitespace following the name or write it as a quoted identifier (or both):为了消除错误并使名称被视为标识符,可以在名称后面使用空格,也可以将其写成带引号的标识符(或两者兼有):

    CREATE TABLE count (i INT);
    CREATE TABLE `count`(i INT);
    CREATE TABLE `count` (i INT);
  • With IGNORE_SPACE enabled, the parser loosens the requirement that there be no whitespace between the function name and the following parenthesis. 在启用IGNORE_SPACE的情况下,解析器取消了函数名和下面的括号之间不能有空格的要求。This provides more flexibility in writing function calls. For example, either of the following function calls are legal:这在编写函数调用时提供了更大的灵活性。例如,以下任一函数调用都是合法的:

    SELECT COUNT(*) FROM mytable;
    SELECT COUNT (*) FROM mytable;

    However, enabling IGNORE_SPACE also has the side effect that the parser treats the affected function names as reserved words (see Section 9.3, “Keywords and Reserved Words”). This means that a space following the name no longer signifies its use as an identifier. The name can be used in function calls with or without following whitespace, but causes a syntax error in nonexpression context unless it is quoted. 然而,启用IGNORE_SPACE也有副作用,即解析器将受影响的函数名视为保留字(请参阅第9.3节,“关键字和保留字”)。这意味着名称后面的空格不再表示其用作标识符。该名称可以在带有或不带有空格的函数调用中使用,但在非压缩上下文中会导致语法错误,除非它被引用。For example, with IGNORE_SPACE enabled, both of the following statements fail with a syntax error because the parser interprets count as a reserved word:例如,在启用IGNORE_SPACE的情况下,以下两个语句都会因语法错误而失败,因为解析器将count解释为保留字:

    CREATE TABLE count(i INT);
    CREATE TABLE count (i INT);

    To use the function name in nonexpression context, write it as a quoted identifier:要在非压缩上下文中使用函数名,请将其写成带引号的标识符:

    CREATE TABLE `count`(i INT);
    CREATE TABLE `count` (i INT);

To enable the IGNORE_SPACE SQL mode, use this statement:要启用IGNORE_SPACE SQL模式,请使用以下语句:

SET sql_mode = 'IGNORE_SPACE';

IGNORE_SPACE is also enabled by certain other composite modes such as ANSI that include it in their value:IGNORE_SPACE也由某些其他复合模式(如ANSI)启用,这些模式将其包含在值中:

SET sql_mode = 'ANSI';

Check Section 5.1.11, “Server SQL Modes”, to see which composite modes enable IGNORE_SPACE.检查第5.1.11节,“服务器SQL模式”,查看哪些复合模式启用IGNORE_SPACE。

To minimize the dependency of SQL code on the IGNORE_SPACE setting, use these guidelines:要最大限度地减少SQL代码对IGNORE_SPACE设置的依赖性,请使用以下准则:

  • Avoid creating loadable functions or stored functions that have the same name as a built-in function.避免创建与内置函数同名的可加载函数或存储函数。

  • Avoid using function names in nonexpression context. For example, these statements use count (one of the affected function names affected by IGNORE_SPACE), so they fail with or without whitespace following the name if IGNORE_SPACE is enabled:避免在非压缩上下文中使用函数名。例如,这些语句使用count(受IGNORE_SPACE影响的受影响函数名之一),因此如果启用IGNORE_SPACE,则在名称后面有空格或没有空格的情况下都会失败:

    CREATE TABLE count(i INT);
    CREATE TABLE count (i INT);

    If you must use a function name in nonexpression context, write it as a quoted identifier:如果必须在非压缩上下文中使用函数名,请将其写成带引号的标识符:

    CREATE TABLE `count`(i INT);
    CREATE TABLE `count` (i INT);

Function Name Resolution函数名称解析

The following rules describe how the server resolves references to function names for function creation and invocation:以下规则描述了服务器如何解析对函数名称的引用以进行函数创建和调用:

  • Built-in functions and loadable functions内置功能和可加载功能

    An error occurs if you try to create a loadable function with the same name as a built-in function.如果试图创建与内置函数同名的可加载函数,则会发生错误。

  • Built-in functions and stored functions内置功能和存储功能

    It is possible to create a stored function with the same name as a built-in function, but to invoke the stored function it is necessary to qualify it with a schema name. 可以创建与内置函数同名的存储函数,但要调用存储函数,必须使用模式名称对其进行限定。For example, if you create a stored function named PI in the test schema, invoke it as test.PI() because the server resolves PI() without a qualifier as a reference to the built-in function. The server generates a warning if the stored function name collides with a built-in function name. 例如,如果您在测试模式中创建了一个名为PI的存储函数,请将其调用为test.PI(),因为服务器解析PI()时不使用限定符作为对内置函数的引用。如果存储的函数名称与内置函数名称冲突,服务器将生成警告。The warning can be displayed with SHOW WARNINGS.警告可以显示为SHOW WARNINGS

  • Loadable functions and stored functions可加载函数和存储函数

    Loadable functions and stored functions share the same namespace, so you cannot create a loadable function and a stored function with the same name.可加载函数和存储函数共享相同的命名空间,因此不能创建具有相同名称的可加载函数与存储函数。

The preceding function name resolution rules have implications for upgrading to versions of MySQL that implement new built-in functions:前面的函数名解析规则对升级到实现新内置函数的MySQL版本有影响:

  • If you have already created a loadable function with a given name and upgrade MySQL to a version that implements a new built-in function with the same name, the loadable function becomes inaccessible. 如果您已经创建了一个具有给定名称的可加载函数,并将MySQL升级到实现具有相同名称的新内置函数的版本,则可加载函数将无法访问。To correct this, use DROP FUNCTION to drop the loadable function and CREATE FUNCTION to re-create the loadable function with a different nonconflicting name. Then modify any affected code to use the new name.要更正此问题,请使用DROP FUNCTION删除可加载函数,并使用CREATE FUNCTION使用不同的非冲突名称重新创建可加载函数。然后修改任何受影响的代码以使用新名称。

  • If a new version of MySQL implements a built-in function with the same name as an existing stored function, you have two choices: Rename the stored function to use a nonconflicting name, or change calls to the function so that they use a schema qualifier (that is, use schema_name.func_name() syntax). 如果新版本的MySQL实现了与现有存储函数同名的内置函数,则有两种选择:重命名存储函数以使用不冲突的名称,或者更改对该函数的调用以使用架构限定符(即,使用schema_name.func_name()语法)。In either case, modify any affected code accordingly.无论哪种情况,都要相应地修改任何受影响的代码。