CREATE [DEFINER = { user | CURRENT_USER }]

PROCEDURE sp_name ([proc_parameter[,…]])

[characteristic …] routine_body

CREATE [DEFINER = { user | CURRENT_USER }]

FUNCTION sp_name ([func_parameter[,…]])

RETURNS type

[characteristic …] routine_body

proc_parameter:

[IN | OUT | INOUT] param_name type

func_parameter:

param_name type

type:

Любой допустимый тип данных MySQL

characteristic:

LANGUAGE SQL | [NOT] DETERMINISTIC

| {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}

| SQL SECURITY {DEFINER | INVOKER}

| COMMENT 'string'

routine_body:

Допустимая инструкция процедуры SQL

Эти инструкции создают сохраненные подпрограммы. С MySQL 5.0.3, чтобы использовать их, необходимо иметь привилегию CREATE ROUTINE. Если двоичная регистрация допускается, эти инструкции могут также требовать привилегии SUPER. MySQL автоматически предоставляет создателю привилегии ALTER ROUTINE и EXECUTE.

По умолчанию, подпрограмма связана с заданной по умолчанию базой данных. Чтобы сопоставить подпрограмму явно с другой базой данных, определите имя как db_name.sp_name, когда Вы создаете ее.

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

SQL-режим IGNORE_SPACE применяется к встроенным функциям, но не к сохраненным подпрограммам. Всегда допустимо иметь пробелы после стандартного имени, независимо от того, допускается ли IGNORE_SPACE.

Список параметров, включенный внутри круглых скобок, должен всегда присутствовать. Если не имеется никаких параметров, должен использоваться пустой список параметров ().

Каждый параметр может быть объявлен, чтобы использовать любой тип достоверных данных, за исключением того, что не может использоваться атрибут COLLATE.

Каждый параметр представляет собой по умолчанию параметр IN. Чтобы определять иное для параметра, используйте ключевое слово OUT или INOUT перед именем параметра.

Обратите внимание: определение параметра как IN, OUT или INOUT допустимо только для PROCEDURE! Параметры FUNCTION всегда расцениваются как параметры IN.

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

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

Предложение RETURNS может быть определено только для FUNCTION, для которой это является обязательным. Это указывает тип возврата функции, и функциональное тело должно содержать инструкцию RETURN value.

routine_body состоит из допустимой инструкции процедуры SQL. Это может быть простая инструкция типа SELECT или INSERT , либо это может быть составная инструкция, использующая BEGIN и END. Синтаксис составного оператора описан в разделе "". Составные инструкции могут содержать объявления, циклы и другие инструкции управляющей структуры. Синтаксис для этих инструкций описан позже в этой главе. Некоторые инструкции не позволяются в сохраненных подпрограммах.

Инструкция CREATE FUNCTION использовалась в более ранних версиях MySQL, чтобы поддерживать UDFs (user-defined functions). UDF продолжает обеспечиваться, даже с существованием сохраненных функций. UDF может быть расценен как внешняя сохраненная функция. Однако, обратите внимание, что сохраненные функции совместно используют их пространство имен с UDF.

Процедура или функция рассматривается как детерминированная (deterministic), если она всегда производит тот же самый результат для тех же самых входных параметров, или недетерминированная (not deterministic) в противном случае. Если при определении функции не задано DETERMINISTIC или NOT DETERMINISTIC, берется значение по умолчанию NOT DETERMINISTIC .

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

В настоящее время характеристика DETERMINISTIC принята, но еще не используется оптимизатором. Однако, если двоичная регистрация допускается, эта характеристика воздействует на то, которые стандартные определения MySQL принимает.

Несколько характеристик обеспечивают информацию относительно характера использования данных подпрограммой. CONTAINS SQL указывает, что подпрограмма не содержит инструкции, которые читают или записывают данные. NO SQL указывает, что подпрограмма не содержит никаких инструкций SQL. READS SQL DATA указывает, что подпрограмма содержит инструкции, которые читают данные, но не инструкции, чтобы те данные записывать. MODIFIES SQL DATA указывает, что подпрограмма содержит инструкции, которые могут записывать данные. CONTAINS SQL значение по умолчанию, если ни одна из этих характеристик не дана явно. Эти характеристики только консультативные. Сервер не использует их, чтобы ограничить то, какие виды инструкций подпрограмме позволено выполнить.

Характеристика SQL SECURITY может использоваться, чтобы определить, должна ли подпрограмма быть выполнена, используя разрешения пользователя, который создает подпрограмму, или пользователя, который ее вызывает. Значение по умолчанию: DEFINER. Это свойство ново в SQL:2003. Создатель или исполнитель должен иметь разрешение обратиться к базе данных, с которой подпрограмма связана. Начиная с MySQL 5.0.3, необходимо иметь привилегию EXECUTE, чтобы выполнить подпрограмму. Пользователь, который должен иметь эту привилегию, является создателем или исполнителем в зависимости от того, как установлена характеристика SQL SECURITY.

Факультативное предложение DEFINER определяет логин MySQL, который нужно использовать при проверке привилегий доступа в стандартном времени выполнения для подпрограмм, которые имеют характеристику SQL SECURITY DEFINER. Предложение DEFINER было добавлено в MySQL 5.0.20.

Если дано значение user, это должно быть логином MySQL в формате 'user_name'@'host_name' (тот же самый формат используется в инструкции GRANT). Параметры user_name и host_name обязательны. CURRENT_USER также может быть дан как CURRENT_USER(). Заданное по умолчанию для DEFINER: пользователь, который выполняет CREATE PROCEDURE, CREATE FUNCTION или инструкцию (аналогично DEFINER=CURRENT_USER).

Если Вы определяете предложение DEFINER, Вы не можете устанавливать значение к любому логину (только к Вашему собственному), если Вы не имеете привилегию SUPER. Эти правила определяют допустимые значения пользователя DEFINER:

Если Вы не имеете привилегию SUPER, единственное допустимое значение user: Ваш собственный логин, определенный буквально или используя CURRENT_USER. Вы не можете устанавливать DEFINER к некоторому другому логину.

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

Хотя возможно создать подпрограммы с несуществующим значением DEFINER, ошибка происходит, если подпрограмма выполняется с привилегиями DEFINER, но сам DEFINER не существует во время выполнения.

MySQL сохраняет установку переменной системы sql_mode, которая была во время создания подпрограммы, и всегда выполняет подпрограмму именно с этой установкой.

Когда подпрограмма вызывается, выполняется неявное USE db_name (и отменяется по завершении). Инструкции USE внутри сохраненных подпрограмм отвергнуты.

Начиная с MySQL 5.0.18, сервер использует тип данных стандартного параметра или функционального возвращаемого значения следующим образом. Эти правила также относятся к локальным стандартным переменным, созданным инструкцией DECLARE.

Назначения проверены на предмет несоответствия типов данных и переполнение. Преобразование и проблемы переполнения приводит к предупреждениям или ошибкам в строгом режиме.

Для символьных типов данных, если имеется предложение CHARACTER SET в объявлении, используются определенный набор символов и заданное по умолчанию объединение. Если не имеется никакого такого предложения, используются наборы символов базы данных и объединение, которые были актуальными во время написания подпрограммы (они заданы значениями переменных системы character_set_database и collation_database). Атрибут COLLATE не обеспечивается. Это включает использование BINARY, потому что в этом контексте BINARY определяет двоичное объединение набора символов.

Только скалярные значения могут быть назначены к параметрам или переменным. Например, инструкция типа SET x=(SELECT 1,2) глубоко ошибочна.

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

Предложение COMMENT представляет собой очередное расширение MySQL и может использоваться, чтобы описать сохраненную подпрограмму. Эта информация отображается командами SHOW CREATE PROCEDURE и SHOW CREATE FUNCTION.

MySQL позволяет подпрограммам содержать инструкции DDL, например, CREATE и DROP. MySQL также позволяет сохраненным процедурам (но не сохраненным функциям) содержать SQL-инструкции транзакций, типа COMMIT. Сохраненные функции не могут содержать инструкции, которые делают явное или неявное завершение транзакции или обратную перемотку. Поддержка для этих инструкций не требуется стандартом SQL, который четко заявляет, что каждый поставщик СУБД может решать, позволять ли это.

Сохраненные подпрограммы не могут использовать LOAD DATA INFILE.

Инструкции, которые возвращают набор результатов, не могут использоваться внутри сохраненной функции. Это включает инструкции SELECT, которые не используют INTO, чтобы выбрать значения столбца в переменные, инструкции SHOW и другие инструкции, типа EXPLAIN. Для инструкций, которые могут быть заданы при функциональном определении, но возвращают набо результатов, произойдет ошибочка Not allowed to return a result set from a function (ER_SP_NO_RETSET_IN_FUNC). Для инструкций, которые могут быть определены только во время выполнения, происходит ошибка PROCEDURE %s can't return a result set in the given context (ER_SP_BADSELECT).

Обратите внимание: до MySQL 5.0.10 сохраненные функции, созданные с CREATE FUNCTION, не должны содержать ссылки к таблицам, с ограниченными исключительными ситуациями. Они могут включать некоторые инструкции SET, которые содержат ссылки на таблицы, например, SET a:= (SELECT MAX(id) FROM t), и инструкции SELECT, которые выбирают значения непосредственно в переменные, например, SELECT i INTO var1 FROM t.

Следующее показывает пример простой сохраненной процедуры, которая использует параметр OUT. Пример использует команду delimiter клиента mysql, чтобы изменить операторный разделитель с ; на // в то время как процедура определяется. Это позволяет использовать разделитель ; в теле процедуры, которое будет передано на сервер.mysql> delimiter //

mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)

– > BEGIN

– > SELECT COUNT(*) INTO param1 FROM t;

– > END;

– > //

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> CALL simpleproc(@a);

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @a;

+------+

| @a |

+------+

| 3 |

+------+

1 row in set (0.00 sec)

При использовании команды delimiter, Вы должны избежать использования наклонной черты влево (\), потому что это escape-символ для MySQL.

Следующее представляет собой пример функции, которая берет параметр, выполняет операцию, использующую функцию SQL, и возвращает результат. В этом случае, ненужно использовать разделитель, потому что функциональное определение не содержит никакой внутренней ;, значит точку с запятой можно использовать как операторный разделитель:mysql> CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)

– > RETURN CONCAT('Hello, ',s,'!');

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT hello('world');

+----------------+

| hello('world') |

+----------------+

| Hello, world! |

+----------------+

1 row in set (0.00 sec)

Сохраненная функция возвращает значение типа данных, определенного в предложении RETURNS. Если инструкция RETURN возвращает значение иного типа, значение приведено к соответствующему типу. Например, если функция возвращает значение ENUM или SET, но инструкция RETURN возвращает целое число, значение, возвращенное из функции: строка для соответствующего ENUM-члена набора элементов SET.