函数名称解析和解析
MySQL支持内置(本机)函数,用户定义函数(UDF)和存储函数。本节描述服务器如何识别内置函数的名称是用作函数调用还是用作标识符,以及在给定名称存在不同类型的函数的情况下,服务器如何确定使用哪个函数。
- 内置函数名称解析
- 功能名称解析
内置函数名称解析
解析器使用默认规则来解析内置函数的名称。可以通过启用IGNORE_SPACE
SQL模式来更改这些规则。
当解析器遇到一个单词,它是内置函数的名称时,它必须确定该名称是表示函数调用还是作为对表或列名之类的标识符的非表达式引用。例如,在以下语句中,对的第一个引用count
是函数调用,而第二个引用是表名称:
SELECT COUNT(*)FROM mytable;CREATE TABLE count (i INT);
解析器仅在解析预期为表达式的内容时,才应将内置函数的名称识别为指示函数调用。也就是说,在非表达式上下文中,允许使用函数名作为标识符。
但是,某些内置函数具有特殊的解析或实现注意事项,因此解析器默认情况下使用以下规则来区分其名称是在非表达式上下文中用作函数调用还是用作标识符:
- 要将名称用作表达式中的函数调用,名称和后面的
(
括号字符之间必须没有空格。 - 相反,要将函数名称用作标识符,切勿在其后立即加上括号。
名称和括号之间不得包含空格的函数调用要求仅适用于具有特殊注意事项的内置函数。COUNT
是这样的名字之一。所述sql/lex.h
源文件列出的针对以下空白决定了它们的解释这些特殊功能的名称:通过定义的名称SYM_FN()
中的宏symbols[]
阵列。
下表列出了受IGNORE_SPACE
设置影响的MySQL 8.0中的功能,并在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
是这样的名字之一。但是,对于这些不受影响的函数名称,在表达式上下文中的解释可能会有所不同: unc_name()
如果有给定名称的函数,则解释为内置函数;否则,将其解释为内置函数。如果不是, unc_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
。
为了最大程度地减少对IGNORE_SPACE
设置的SQL代码依赖性,请遵循以下准则:
- 避免创建与内置函数同名的UDF或存储函数。
避免在非表达式上下文中使用函数名称。例如,这些语句使用
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);
功能名称解析
以下规则描述了服务器如何将对函数名称的引用解析为函数创建和调用:
内置功能和用户定义功能
如果您尝试创建与内置函数同名的UDF,则会发生错误。
内置功能和存储功能
可以使用与内置函数相同的名称来创建存储函数,但是要调用该存储函数,必须使用架构名称对其进行限定。例如,如果您创建一个
PI
在test
模式中命名的存储函数,则调用它的test.PI()
原因是因为服务器在PI()
不使用限定符的情况下进行解析,以此作为对内置函数的引用。如果存储的函数名与内置函数名冲突,则服务器会生成警告。可以使用显示警告SHOW WARNINGS
。用户定义的函数和存储的函数
用户定义的函数和存储的函数共享相同的名称空间,因此无法创建UDF和具有相同名称的存储函数。
前面的函数名称解析规则对升级到实现新的内置函数的MySQL版本有影响:
- 如果您已经使用给定的名称创建了用户定义的函数,并将MySQL升级到实现具有相同名称的新内置函数的版本,则UDF变得不可访问。要更正此问题,请使用
DROP FUNCTION
拖放的UDF并CREATE FUNCTION
使用其他不冲突的名称重新创建UDF。然后修改任何受影响的代码以使用新名称。 - 如果新版本的MySQL实现的内置函数的名称与现有存储函数的名称相同,则有两种选择:重命名存储函数以使用不冲突的名称,或更改对该函数的调用以使它们使用模式限定符(即使用语法)。在任何一种情况下,请相应地修改任何受影响的代码。
schema_name. unc_name()