Spec-Zone.ru › MySQL 9.2

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 9.2, на которые влияет параметр 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.18, «CREATE PROCEDURE и CREATE FUNCTION Statements».

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

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

    MySQL 9.2 поддерживает 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-9.2-en/function-resolution.html

Spec-Zone.ru

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