9.2.5 Парсинг и разрешение имён функций
MySQL поддерживает встроенные (нативные) функции, загружаемые функции и хранимые функции. В этом разделе описывается, как сервер определяет, используется ли имя встроенной функции в качестве вызова функции или в качестве идентификатора, и как сервер определяет, какую функцию использовать в случаях, когда функции разных типов существуют с заданным именем.
Парсинг имён встроенных функций
Парсер использует стандартные правила для парсинга имён встроенных функций. Эти правила могут быть изменены путём включения режима IGNORE_SPACE SQL.
Когда парсер встречает слово, являющееся именем встроенной функции, он должен определить, обозначает ли это имя вызов функции или же это ссылка на идентификатор, такой как имя таблицы или столбца. Например, в следующих операциях первая ссылка на count является вызовом функции, в то время как вторая ссылка — это имя таблицы:
SELECT COUNT(*) FROM mytable;
CREATE TABLE count (i INT);
Парсер должен распознавать имя встроенной функции как указание на вызов функции только при парсинге того, что ожидается как выражение. То есть в контексте, не являющемся выражением, имена функций допускаются в качестве идентификаторов.
Однако некоторые встроенные функции имеют особые соображения по парсингу или реализации, поэтому парсер по умолчанию использует следующие правила для различения, используются ли их имена как вызовы функций или как идентификаторы в контексте, не являющемся выражением:
Для использования имени в качестве вызова функции в выражении не должно быть пробелов между именем и последующей
(скобкой.Обратно, для использования имени функции как идентификатора, оно не должно сразу следовать за скобкой.
Требование о том, что вызовы функций должны быть записаны без пробелов между именем и скобкой, относится только к встроенным функциям, имеющим особые соображения. COUNT — одно из таких имён. Файл sql/lex.h содержит список имён этих специальных функций, для которых пробелы после имени определяют их интерпретацию: имена, определённые макросом SYM_FN() в массиве symbols[].
В следующем списке перечислены функции в MySQL 5.7, которые зависят от настройки IGNORE_SPACE и указаны как специальные в файле sql/lex.h. Возможно, проще всего считать, что требование отсутствия пробелов относится ко всем вызовам функций.
ADDDATEBIT_ANDBIT_ORBIT_XORCASTCOUNTCURDATECURTIMEDATE_ADDDATE_SUBEXTRACTGROUP_CONCATMAXMIDMINNOWPOSITIONSESSION_USERSTDSTDDEVSTDDEV_POPSTDDEV_SAMPSUBDATESUBSTRSUBSTRINGSUMSYSDATESYSTEM_USERTRIMVARIANCEVAR_POPVAR_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также имеет побочный эффект, заключающийся в том, что парсер обрабатывает затронутые имена функций как ключевые слова (см. Раздел 9.3, “Ключевые слова и зарезервированные слова”). Это означает, что пробел после имени больше не означает его использование как идентификатора. Имя может использоваться в вызовах функций с или без последующего пробела, но вызывает синтаксическую ошибку в контексте, не являющимся выражением, если оно не заключено в кавычки. Например, при включённом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';
См. Раздел 5.1.10, “Режимы SQL сервера”, чтобы узнать, какие составные режимы включают IGNORE_SPACE.
Чтобы свести к минимуму зависимость кода 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);
Разрешение имен функций
Следующие правила описывают, как сервер разрешает ссылки на имена функций для создания и вызова функций:
-
Встроенные функции и загружаемые функции
Возникает ошибка, если вы пытаетесь создать загружаемую функцию с тем же именем, что и встроенная функция.
-
Встроенные функции и хранимые функции
Можно создать хранимую функцию с тем же именем, что и встроенная функция, но для вызова хранимой функции необходимо указать имя схемы. Например, если вы создали хранимую функцию с именем
PIв схемеtest, вызовите её какtest.PI(), поскольку сервер разрешаетPI()без квалификатора как ссылку на встроенную функцию. Сервер генерирует предупреждение, если имя хранимой функции совпадает с именем встроенной функции. Предупреждение можно отобразить с помощьюSHOW WARNINGS. -
Загружаемые функции и хранимые функции
Загружаемые и хранимые функции используют один и тот же пространство имён, поэтому нельзя создать загружаемую и хранимую функции с одинаковым именем.
Представленные правила разрешения имён функций имеют последствия для обновления до версий MySQL, которые реализуют новые встроенные функции:
Если вы уже создали загружаемую функцию с заданным именем и обновили MySQL до версии, которая реализует новую встроенную функцию с тем же именем, загружаемая функция станет недоступной. Для исправления этого используйте
DROP FUNCTIONдля удаления загружаемой функции иCREATE FUNCTIONдля повторного создания загружаемой функции с другим неконфликтующим именем. Затем измените любой затронутый код, чтобы использовать новое имя.Если новая версия MySQL реализует встроенную функцию с тем же именем, что и существующая хранимая функция, у вас есть два варианта: переименовать хранимую функцию на неконфликтное имя или изменить вызовы функции, чтобы они использовали квалификатор схемы (то есть, используйте синтаксис
). В любом случае измените любой затронутый код соответственно.schema_name.func_name()
© 2025 Oracle
Licensed under the GPLv2 License.