Spec-Zone.ru › MySQL 8.4

11.2.5 Разбор и разрешение имён функций

MySQL поддерживает встроенные (нативные) функции, загружаемые функции и хранимые функции. В этом разделе описывается, как сервер распознаёт, используется ли имя встроенной функции в качестве вызова функции или как идентификатор, и как сервер определяет, какую функцию использовать в случаях, когда функции разных типов существуют с данным именем.

  • Разбор имён встроенных функций

  • Разрешение имён функций

Разбор имён встроенных функций

Парсер использует стандартные правила для разбора имён встроенных функций. Эти правила можно изменить, включив режим SQL IGNORE_SPACE.

Когда парсер сталкивается со словом, являющимся именем встроенной функции, он должен определить, обозначает ли это имя вызов функции или же это ссылка на идентификатор, например, имя таблицы или столбца. Например, в следующих операторах первая ссылка на count является вызовом функции, в то время как вторая ссылка — именем таблицы:

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

Парсер должен распознавать имя встроенной функции как указание на вызов функции только при разборе того, что ожидается как выражение. То есть, в контексте, не являющемся выражением, имена функций допускаются как идентификаторы.

Однако некоторые встроенные функции имеют особые соображения по разбору или реализации, поэтому парсер по умолчанию использует следующие правила, чтобы отличить, используются ли их имена в качестве вызовов функций или в качестве идентификаторов в контексте, не являющемся выражением:

  • Чтобы использовать имя как вызов функции в выражении, между именем и последующей ( скобкой не должно быть пробелов.

  • И наоборот, чтобы использовать имя функции как идентификатор, за ним не должно сразу следовать скобка.

Требование, чтобы вызовы функций записывались без пробелов между именем и скобкой, применяется только к встроенным функциям, которые имеют особые соображения. COUNT — одно из таких имён. Список имён этих специальных функций, для которых последующий пробел определяет их интерпретацию, содержится в файле sql/lex.h и определяется макросом SYM_FN() в массиве symbols[].

В следующем списке перечислены функции в MySQL 8.4, которые зависят от настроек 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 () интерпретируется как загружаемая или хранимая функция, если такая существует.

Режим SQL IGNORE_SPACE может использоваться для изменения того, как парсер обрабатывает имена функций, чувствительные к пробелам:

  • При отключённом 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 также приводит к тому, что парсер рассматривает имена указанных функций как зарезервированные слова (см. Раздел 11.3, «Ключевые слова и зарезервированные слова»). Это означает, что пробел после имени больше не указывает на его использование в качестве идентификатора. Имя можно использовать в вызовах функций с или без последующего пробела, но это вызывает синтаксическую ошибку в контексте, не являющемся выражением, если оно не заключено в кавычки. Например, при включённом IGNORE_SPACE оба следующих оператора завершаются синтаксической ошибкой, потому что парсер интерпретирует count как зарезервированное слово:

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

    Чтобы использовать имя функции в контексте, не являющемся выражением, запишите его как цитируемый идентификатор:

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

Чтобы включить режим SQL IGNORE_SPACE, используйте этот оператор:

SET sql_mode = 'IGNORE_SPACE';

IGNORE_SPACE также включается некоторыми другими составными режимами, такими как ANSI, которые включают его в своё значение:

SET sql_mode = 'ANSI';

Проверьте Раздел 7.1.11, «Режимы 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);
    

Разрешение имен функций

Следующие правила описывают, как сервер разрешает ссылки на имена функций для создания и вызова функций:

  • Встроенные функции и загружаемые функции

    Возникает ошибка, если вы пытаетесь создать загружаемую функцию с тем же именем, что и встроенная функция.

    IF NOT EXISTS не имеет эффекта в таких случаях. См. Раздел 15.7.4.1, «CREATE FUNCTION Statement for Loadable Functions» для получения дополнительной информации.

  • Встроенные функции и хранимые функции

    Возможна ситуация, когда вы создаете хранимую функцию с тем же именем, что и встроенная функция, но для вызова хранимой функции необходимо указать имя схемы. Например, если вы создаете хранимую функцию с именем PI в схеме test, вызывайте ее как test.PI(), поскольку сервер разрешает PI() без квалификатора как ссылку на встроенную функцию. Сервер генерирует предупреждение, если имя хранимой функции совпадает с именем встроенной функции. Предупреждение можно отобразить с помощью SHOW WARNINGS.

    IF NOT EXISTS не оказывает влияния в таких случаях; см. Раздел 15.1.17, «CREATE PROCEDURE и CREATE FUNCTION Statements».

  • Загружаемые функции и хранимые функции

    Возможна ситуация, когда вы создаете хранимую функцию с тем же именем, что и существующая загружаемая функция, или наоборот. Сервер генерирует предупреждение, если предлагаемое имя хранимой функции совпадает с именем существующей загружаемой функции, или если предлагаемое имя загружаемой функции совпадает с именем существующей хранимой функции. В любом случае, после существования обеих функций, при вызове хранимой функции необходимо указывать имя схемы; в таких случаях сервер предполагает, что неквалифицированное имя относится к загружаемой функции.

    MySQL 8.4 поддерживает IF NOT EXISTS с помощью CREATE FUNCTION операторов, но это не влияет на такие случаи.

Предыдущие правила разрешения имен функций имеют последствия для обновления до версий MySQL, которые реализуют новые встроенные функции:

  • Если вы уже создали загружаемую функцию с заданным именем и обновили MySQL до версии, которая реализует новую встроенную функцию с тем же именем, загружаемая функция станет недоступной. Для исправления этого используйте DROP FUNCTION для удаления загружаемой функции и CREATE FUNCTION для повторного создания загружаемой функции с другим несовпадающим именем. Затем измените любой затронутый код, чтобы использовать новое имя.

  • Если новая версия MySQL реализует встроенную функцию или загружаемую функцию с тем же именем, что и существующая хранимая функция, у вас есть два варианта: переименуйте хранимую функцию, чтобы использовать несовпадающее имя, или измените все вызовы функции, которые еще этого не делают, используя квалификатор схемы (синтаксис schema_name.func_name()). В любом случае, измените любой затронутый код соответствующим образом.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/function-resolution.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API