MySQL 支持内置(本地)函数、可加载函数和存储函数。本节介绍服务器如何识别内置函数名称是作为函数调用使用还是作为标识符使用,以及当具有相同名称的不同类型函数存在时,服务器如何确定使用哪个函数。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.
解析器使用默认规则解析内置函数的名称。通过启用 IGNORE_SPACE SQL 模式,可以更改这些规则。The parser uses default rules for parsing names of built-in
functions. These rules can be changed by enabling the
IGNORE_SPACE SQL mode.
当解析器遇到一个是内置函数名称的单词时,它必须确定该名称是表示函数调用,还是表示对标识符(例如表或列名)的非表达式引用。例如,在下列语句中,第一个对 count 的引用是函数调用,而第二个引用是表名: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:
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.
函数调用要求在名称和括号之间不得有空格,这一要求仅适用于具有特殊考虑的内置函数。COUNT 就是其中之一。sql/lex.h 源文件列出了这些特殊函数的名称,其解释是否有空格取决于后续空格:这些名称由 symbols[] 数组中的 SYM_FN() 宏定义。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.
以下列表列出了 MySQL 8.4 中受 IGNORE_SPACE 设置影响,并在 sql/lex.h 源文件中列为特殊的函数。你可能会发现将“禁止空格”的要求应用于所有函数调用会更容易处理。The following list names the functions in MySQL
8.4 that are affected by the
IGNORE_SPACE setting and
listed as special in the sql/lex.h source
file. You may find it easiest to treat the no-whitespace
requirement as applying to all function calls.
ADDDATEBIT_ANDBIT_ANDBIT_ORBIT_ORBIT_XORBIT_XORCASTCASTCOUNTCOUNTCURDATECURDATECURTIMECURTIMEDATE_ADDDATE_ADDDATE_SUBDATE_SUBEXTRACTEXTRACTGROUP_CONCATGROUP_CONCATMAXMAXMIDMIDMINMINNOWPOSITIONSESSION_USERSTDSTDDEVSTDDEV_POPSTDDEV_SAMPSUBDATESUBSTRSUBSTRINGSUMSYSDATESYSTEM_USERTRIMTRIMVARIANCEVARIANCEVAR_POPVAR_POPVAR_SAMPVAR_SAMP
对于未在 sql/lex.h 中列为特殊的函数,空格无关紧要。它们仅在表达式上下文中被解释为函数调用,否则可自由用作标识符。ASCII 就是这样一个名称。然而,对于这些不受影响的函数名,在表达式上下文中的解释可能会有所不同:如果存在具有给定名称的内置函数,则 被解释为内置函数;否则,如果存在具有该名称的可加载函数或存储函数,则 func_name () 被解释为可加载函数或存储函数。For functions not listed as special in
func_name ()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. ASCII is one such name. However,
for these nonaffected function names, interpretation may vary
in expression context:
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.func_name ()
IGNORE_SPACE SQL 模式可用于修改解析器对对空格敏感的函数名的处理方式:The IGNORE_SPACE SQL mode
can be used to modify how the parser treats function names
that are whitespace-sensitive:
当
IGNORE_SPACE被禁用时,当函数名与后续括号之间没有空格时,解析器会将该名称解释为函数调用。即使函数名在非表达式上下文中使用,也会发生这种情况:WithIGNORE_SPACEdisabled, 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: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);
启用
IGNORE_SPACE后,解析器会放宽对函数名与随后的括号之间不能有空格的要求。这为编写函数调用提供了更多的灵活性。例如,以下任意一个函数调用都是合法的:WithIGNORE_SPACEenabled, the parser loosens the requirement that there be no whitespace between the function name and the following parenthesis. 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;
然而,启用
IGNORE_SPACE也有副作用,即解析器将受影响的函数名称视为保留字(参见 第 11.3 节,“关键字和保留字”)。这意味着名称后跟空格不再表示其用作标识符。该名称可以在函数调用中使用,无论后面是否有空格,但在非表达式上下文中会导致语法错误,除非加上引号。例如,在启用IGNORE_SPACE的情况下,以下两个语句都会因语法错误而失败,因为解析器将count解释为保留字:However, enablingIGNORE_SPACEalso has the side effect that the parser treats the affected function names as reserved words (see Section 11.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. For example, withIGNORE_SPACEenabled, both of the following statements fail with a syntax error because the parser interpretscountas a reserved word: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);
要启用 IGNORE_SPACE SQL 模式,请使用以下语句:To enable the IGNORE_SPACE
SQL mode, use this statement:
SET sql_mode = 'IGNORE_SPACE';
IGNORE_SPACE 也被某些包含它的复合模式启用,例如 ANSI:IGNORE_SPACE is also enabled
by certain other composite modes such as
ANSI that include it in
their value:
SET sql_mode = 'ANSI';
请参阅 第 7.1.11 节,“服务器 SQL 模式”,查看哪些复合模式启用了 IGNORE_SPACE。Check Section 7.1.11, “Server SQL Modes”, to see which composite modes
enable IGNORE_SPACE.
为了减少 SQL 代码对 IGNORE_SPACE 设置的依赖,请遵循以下指导:To minimize the dependency of SQL code on the
IGNORE_SPACE setting, use
these guidelines:
避免创建与内置函数同名的可加载函数或存储函数。Avoid creating loadable functions or stored functions that have the same name as a built-in function.
避免在非表达式上下文中使用函数名称。例如,这些语句使用了
count(这是受IGNORE_SPACE影响的函数名称之一),因此如果启用了IGNORE_SPACE,无论名称后是否有空格,它们都会失败:Avoid using function names in nonexpression context. For example, these statements usecount(one of the affected function names affected byIGNORE_SPACE), so they fail with or without whitespace following the name ifIGNORE_SPACEis enabled: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);
以下规则描述了服务器如何解析函数创建和调用时对函数名称的引用: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.
IF NOT EXISTS在这种情况下不起作用。更多信息请参见 第 15.7.4.1 节,“可加载函数的 CREATE FUNCTION 语句”。IF NOT EXISTShas no effect in such cases. See Section 15.7.4.1, “CREATE FUNCTION Statement for Loadable Functions”, for more information.内置函数和存储函数Built-in functions and stored functions
可以创建与内置函数同名的存储函数,但要调用该存储函数,必须使用模式名称进行限定。例如,如果在
test模式中创建一个名为PI的存储函数,则调用时应使用test.PI(),因为服务器会将未限定的PI()解析为对内置函数的引用。如果存储函数名称与内置函数名称冲突,服务器会生成警告。这些警告可以通过SHOW WARNINGS来显示。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 namedPIin thetestschema, invoke it astest.PI()because the server resolvesPI()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. The warning can be displayed withSHOW WARNINGS.IF NOT EXISTS在这种情况下没有效果;请参见 第 15.1.17 节,“CREATE PROCEDURE 和 CREATE FUNCTION 语句”。IF NOT EXISTShas no effect in such cases; see Section 15.1.17, “CREATE PROCEDURE and CREATE FUNCTION Statements”.可加载函数和存储函数Loadable functions and stored functions
可以创建与现有可加载函数同名的存储函数,反之亦然。如果拟议的存储函数名称与现有可加载函数名称冲突,或者拟议的可加载函数名称与现有存储函数名称相同,服务器将生成警告。在任何一种情况下,一旦两个函数都存在,以后在调用存储函数时必须使用模式名称来限定它;在这种情况下,服务器假定未限定的名称指的是可加载函数。It is possible to create a stored function with the same name as an existing loadable function, or the other way around. The server generates a warning if a proposed stored function name collides with an existing loadable function name, or if a proposed loadable function name would be the same as that of an existing stored function. In either case, once both functions exist, it is necessary thereafter to qualify the stored function with a schema name when invoking it; the server assumes in such cases that the unqualified name refers to the loadable function.
MySQL 8.4 支持在
IF NOT EXISTS语句中使用CREATE FUNCTION,但在这种情况下没有效果。MySQL 8.4 supportsIF NOT EXISTSwithCREATE FUNCTIONstatements, but it has no effect in such cases.
上述函数名称解析规则对于升级到实现新内置函数的 MySQL 版本具有影响:The preceding function name resolution rules have implications for upgrading to versions of MySQL that implement new built-in functions:
如果您已经创建了具有给定名称的可加载函数,并且将 MySQL 升级到一个实现了具有相同名称的新内置函数的版本,则该可加载函数将无法访问。要纠正此情况,请使用
DROP FUNCTION删除可加载函数,然后使用CREATE FUNCTION以不同的、不冲突的名称重新创建可加载函数。然后修改任何受影响的代码以使用新名称。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. To correct this, useDROP FUNCTIONto drop the loadable function andCREATE FUNCTIONto re-create the loadable function with a different nonconflicting name. Then modify any affected code to use the new name.如果 MySQL 的新版本实现了一个与现有存储函数同名的内置函数或可加载函数,你有两个选择:将存储函数重命名为一个不冲突的名称,或者将所有尚未使用模式限定符调用的函数调用更改为使用模式限定符(
语法)。在任何情况下,相应地修改受影响的代码。If a new version of MySQL implements a built-in function or loadable 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 any calls to the function that do not do so already to use a schema qualifier (schema_name.func_name()syntax). In either case, modify any affected code accordingly.schema_name.func_name()