Тарифы Услуги Сим-карты

MySQL хранимой процедуры против функции, которую я буду использовать, когда? MySQL хранимые процедуры

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

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

Синтаксис для рутинного создания несколько отличается для процедур и функций:

  • Параметры процедуры могут быть определены как входные, выходные или оба. Это означает, что процедура может передавать значения обратно вызывающему, используя выходные параметры. Доступ к этим значениям можно получить в операторах, которые следуют за инструкцией CALL. Функции имеют только входные параметры. В результате, хотя обе процедуры и функции могут иметь параметры, определение параметра процедуры отличается от описания функций для функций.
  • Функция возвращает значение, поэтому в определении функции должно быть предложение RETURNS, чтобы указать тип данных возвращаемого значения. Кроме того, в теле функции должно быть хотя бы одно выражение RETURN, чтобы вернуть значение вызывающему. RETURNS и RETURN не отображаются в определениях процедур.

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

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

      Задание параметра IN, OUT или INOUT действительна только для ПРОЦЕДУРЫ. Для функции FUNCTION параметры всегда считаются параметрами IN.

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

Чтобы определить хранимую процедуру или функцию, используйте CREATE PROCEDURE или CREATE FUNCTION соответственно:

CREATE PROCEDURE proc_name () routine_body CREATE FUNCTION func_name () RETURNS data_type // diffrent routine_body

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

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

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

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

Готовые заявления SQL (PREPARE, EXECUTE, DEALLOCATE PREPARE) могут использоваться в хранимых процедурах, но не в хранимых функциях или триггерах. Таким образом, хранимые функции и триггеры не могут использовать Dynamic SQL (где вы строите операторы как строки, а затем выполняете их). (Динамический SQL в MySQL хранимых процедурах)

Еще несколько интересных отличий между FUNCTION и STORED PROCEDURE:

    Функции обычно используются для вычислений, где as процедуры обычно используются для выполнения бизнес-логики.

    Функции Не могут повлиять на состояние базы данных (Заявления, которые делают явное или неявное совершение или откат, запрещены в функции) В то время как Хранимые процедуры могут влиять на состояние базы данных, используя фиксацию и т.д.
    refrence: J.1. Ограничения на хранимые процедуры и триггеры

    Функции не могут использовать FLUSH , тогда как Хранимые процедуры могут выполнять.

    Внутри хранимой функции или триггера не разрешается изменять таблицу, которая уже используется (для чтения или записи) оператором, вызывающим функцию или триггер. Хороший пример: Как обновить ту же таблицу при удалении в MYSQL?

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

Теперь давайте узнаем, как можно посмотреть, какие хранимые процедуры имеются у нас на сервере, и как они выглядят. Для этого познакомимся с двумя операторами:

  • SHOW PROCEDURE STATUS - позволяет просмотреть список имеющихся хранимых процедур. Правда просматривать этот список не очень удобно, т.к. по каждой процедуре выдается информация об имени БД, к которой процедура принадлежит, ее типе, учетной записи, от имени которой была создана процедура, о дате создания и изменения процедуры и т.д. И все-таки, если вам необходимо посмотреть, какие процедуры у вас есть, то стоит воспользоваться этим оператором.

  • SHOW CREATE PROCEDURE имя_процедуры - позволяет получить информацию о конкретной процедуре, в частности просмотреть ее код. Вид для просмотра также не очень удобный, но разобраться можно.

Попробуйте оба оператора в действии, чтобы знать, как это выглядит. А теперь рассмотрим более удобный вариант получения подобной информации. В системной базе данных MySQL есть таблица proc, где и хранится информация о процедурах. Так вот мы может сделать SELECT-запрос к этой таблице. Причем, если мы создадим привычный запрос:

SELECT * FROM mysql.proc//

То получим нечто такое же нечитабельное, как и при использовании операторов SHOW. Поэтому мы будем создавать запросы с условиями. Например, если мы создадим вот такой запрос:

SELECT name FROM mysql.proc//

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

Вот теперь мы получили то, что хотели:

Если же мы хотим посмотреть только тело конкретной процедуры (т.е. от begin до end), то мы напишем такой запрос:

И увидим вполне читабельный вариант:

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

  • db - имя БД, в которую сохранена процедура.

  • name - имя процедуры.

  • param_list - список параметров процедуры.

  • body - тело процедуры.

  • comment - комментарий к хранимой процедуре.

Столбцы db, name и body мы уже использовали. Запрос, извлекающий параметры процедуры sum_vendor составьте самостоятельно. А вот про комментарии к хранимым процедурам мы сейчас поговорим подробнее.

Комментарии вещь крайне необходимая, ведь через какое-то время мы может забыть, что делает та или иная процедура. Конечно, по ее коду можно восстановить нашу память, но зачем? Гораздо проще сразу при создании процедуры указать, что она делает, и тогда, даже по прошествии долгого времени, обратившись к комментариям, мы сразу вспомним, зачем эта процедура создавалась.

Создавать комментарии крайне просто. Для этого сразу после списка параметров, но еще до начала тела хранимой процедуры указываем ключевое слово COMMENT "здесь комментарий" . Давайте удалим нашу процедуру sum_vendor и создадим новую, с комментарием:

CREATE PROCEDURE sum_vendor(i INT) COMMENT "Возвращает сумму товара по идентификатору поставщика." begin DROP VIEW IF EXISTS report_vendor; CREATE VIEW report_vendor AS SELECT incoming.id_vendor, magazine_incoming.id_product, magazine_incoming.quantity, prices.price, magazine_incoming.quantity*prices.price AS summa FROM incoming, magazine_incoming, prices WHERE magazine_incoming.id_product= prices.id_product AND magazine_incoming.id_incoming= incoming.id_incoming; SELECT SUM(summa) FROM report_vendor WHERE id_vendor=i; end //


А теперь сделаем запрос к комментарию процедуры:

Вообще-то, чтобы добавить комментарий, вовсе не обязательно было удалять старую процедуру. Можно было отредактировать имеющуюся хранимую процедуру с помощью оператора ALTER PROCEDURE . Давайте посмотрим, как это сделать, на примере процедуры ins_cust из прошлого урока. Эта процедура вводит информацию о новом покупателе в таблицу Покупатели (customers). Давайте добавим комментарий к этой процедуре:

ALTER PROCEDURE ins_cust COMMENT "Вводит информацию о новом покупателе в таблицу Покупатели."//

И сделаем запрос к комментарию, чтобы проверить:

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

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

MySQL хранимые процедуры

Stored procedures - что это?

Хранимые процедуры появились начиная с 5 версии MySQL. Они позволяют автоматизировать сложные процессы на уровне MySQL, нежели использовать для этого внешние скрипты. Это даёт нам наиболее высокую скорость выполнения, т.к. мы не гоняем большое количество запросов, а всего лишь один раз вызываем ту или иную процедуру (или функцию).

Что для этого нужно? Установите MySQL сервер версии 5 или выше (dev.mysql.com/downloads). Процедуры можно создавать как запросы, например через командную строку MySQL, но для удобства советую скачать MySQL GUI Tools (dev.mysql.com/downloads/gui-tools). Данный пакет включает в себя три программы - MySQL Administrator, MySQL Query Browser и MySQL Migration Toolkit. Нам понадобятся первые две. (Хотя можно обойтись одним MySQL Query Browser, но все эти $$ в хранимых процедурах иногда могут сбить с толку).

Первая хранимая процедура

Итак, открываем MySQL Administrator, подключаемся к серверу MySQL и создаем новую схему (базу данных): щелкните Catalogs, выберите Create New Schema в области Schemata (Ctrl+N). Назовите ее как-нибудь (например db). Откройте только что созданную схему, выберите вкладку Stored procedures и щелкните кнопку Create Stored Proc. Назовите свою процедуру procedure1. В тело процедуры (между BEGIN и END) впишите следующее:

SELECT "This is my stored procedure" ;

И нажмите Execute SQL - процедура создана. Откройте MySQL Query Browser, выберите свою схему (db) и впишите следующий запрос:

CALL procedure1() ;

Вуала! Поздравляю.

Переменные в MySQL

Для того, чтобы извлечь каку-то пользу от хранимых процедур в MySQL, вам придется поработать с переменными. Так как это не входи в рамки данной статьи, покажу лишь несколько примеров.

Простые переменные

DECLARE iVar INT DEFAULT 0; SELECT COUNT(* ) INTO iVar FROM `data` ;

Системные переменные

SET @iVar = 5 ; SELECT @iVar;

Разница между простыми и системными переменными в том, что системные переменные доступны из вне хранимой процедуры. То есть, чтобы извлечь какие-то данные нужно пользоваться системными, а переменные которые нужны только внутри процедуры должны быть простыми.

Параметры в хранимых процедурах

Здесь тоже всё достаточно просто. Изменяем первую строку, объявляющая саму процедуру:

CREATE PROCEDURE `procedure1` (IN iInput1 INT, IN iInput2 INT)

Здесь, ключевое слово IN указывает на то, что параметр указан только для чтения. Далее с этим параметром работаем как с обычной переменной внутри процедуры:

Условия, Циклы. IF THEN ELSE, WHILE

Условия и циклы вам обязательно понадобятся при написании комплексных хранимых процедур, но зацикливаться на этой теме не буду. Думаю хоть какие-то навыки программирования у вас есть, так что покажу всего лишь синтаксис.

IF условие THEN действие; ELSE действие; END IF ;

WHILE условие DO действие; END WHILE;

Простой пример

Один из хороших случаев применения хранимых процедур - тогда, когда вам нужно объединить несколько запросов в один, например добавление темы в форум и увеличение общего количества тем. Допустим таблица threads

CREATE TABLE `threads` ( `id` INT NOT NULL AUTO_INCREMENT , `title` VARCHAR(255 ) NOT NULL , `tag` VARCHAR(255 ) NOT NULL , PRIMARY KEY ( `id` ) ) ENGINE = MYISAM;

Здесь title у нас будет заголовком новой темы. Ну и таблица, например с различными статистическими переменными сайта, в том числе общее количество тем в форме.

CREATE TABLE `variables` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(255 ) NOT NULL , `value` INT NOT NULL DEFAULT 0, PRIMARY KEY ( `id` ) ) ENGINE = MYISAM;

Тут вроде всё понятно, допустим у нас там есть запись с name = threads и value = 0. Создадим новую хранимую процедуру procedure2.

Объяснять особо нечего, просто два запроса объединили в один. Теперь мы можем вызвать эту процедуру таким образом:

CALL procedure2("My new thread" ) ;

Таким образом, вместо того, чтобы передать два или больше запросов (например через php), мы можем передать один - оптимизация, чистый код и можно изменить в любой момент не затрагивая другие скрипты.

Курсоры (MySQL Cursors)

Курсоры позволяют пройтись по всем полученным результатам запроса. На теории объяснить сложно, покажу на практике. Добавим еще одну таблицу к нашей базе данных - hits:

CREATE TABLE `tags` ( `id` INT NOT NULL AUTO_INCREMENT , `tag` VARCHAR(255 ) NOT NULL , PRIMARY KEY ( `id` ) ) ENGINE = MYISAM

Сюда мы будем записывать все тэги из всех тем. Хранимая процедура будет выглядеть примерно так:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 CREATE PROCEDURE `procedure3` () BEGIN DECLARE done INT DEFAULT 0; DECLARE sTag VARCHAR(255 ) ; DECLARE iCount INT DEFAULT 0; DECLARE rCursor CURSOR FOR SELECT `tag` FROM `threads` WHERE 1 ; DECLARE CONTINUE HANDLER FOR SQLSTATE "02000" SET done= 1 ; OPEN rCursor; FETCH rCursor INTO sTag; WHILE done = 0 DO SELECT COUNT(* ) INTO iCount FROM `tags` WHERE `tag` = sTag; IF iCount = 0 THEN INSERT INTO `tags` (`tag` ) VALUES (sTag) ; END IF ; FETCH rCursor INTO sTag; END WHILE; CLOSE rCursor; END

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

Курсор для запроса SELECT, который выберет теги из всех тем (WHERE 1). После курсора объявляем что-то вроде исключения - что делать, когда результаты кончатся (SQLSTATE ‘02000′ означает это окончание). В этом случае мы в переменную done запишем 1, чтобы в последствии выйти из цикла.

Открываем курсор, и получаем первую запись. Дальше в цикле - Выбираем количество совпадений из таблицы тегов для текущего тега и помещаем результат в переменную iCount. Если результатов нет, то запросом INSERT вставляем новый тег.

В конце концов закрываем курсор и выходим из процедуры. Ну вот и всё.

Извлечение данных

Вспомним системные переменные и рассмотрим еще одну манипуляцию над нашими таблицами - получить общее количество тегов и тем. Перейдем сразу к процедуре:

1 2 3 4 5 6 7 8 9 10 CREATE PROCEDURE `procedure4` () BEGIN DECLARE iTags INT DEFAULT 0; DECLARE iThreads INT DEFAULT 0; SELECT COUNT(* ) INTO iTags FROM `tags` ; SELECT COUNT(* ) INTO iThreads FROM `threads` ; SET @tags = iTags, @threads = iThreads; END

Объявляем две переменных - iTags - количество тегов, и iThreads - общее количество тем.

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

CALL procedure4() ; SELECT @tags, @threads;

Определение 1

Хранимая процедура – это самостоятельная часть программного код, которую создают и хранят в БД MySQL.

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

Создание хранимой процедуры

Создадим процедуру с именем GetAllProducts() для получения списка всех продуктов из таблицы.

Для этого нужно загрузить mysql-клиент и выполнить следующие команды:

Команда DELIMITER // не входит в хранимые процедуры. DELIMITER – специальная команда, изменяющая стандартный разделитель запросов (по умолчанию «;») на указанный после нее. Этой командой изменим его на 2 слеша (//).

Если не изменить разделитель, то mysql ошибочно интерпретирует процедуру и выдаст ошибку. После END используется разделитель // и с помощью команды DELIMITER возвращается значение разделителя «;».

Зарезервированные слова CREATE PROCEDURE указывают mysql, что нужно СОЗДАТЬ ПРОЦЕДУРУ. После этих слов нужно указать название хранимой процедуры (в примере GetAllProducts). Пустые скобки «()» после названия процедуры означает, что процедура не принимает никаких переменных.

Команды BEGIN и END соответственно открывают и закрывают блок кода SQL.

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

В MySQL Workbench процедура создается нажатием правой кнопкой мыши на Routines и выбором в выпадающем меню пункта Create Procedure…

Можно просмотреть полный код, который отправится в MySQL, перед тем, как он запишется в базу данных. Если ошибок нет, нажимаем Apply .

После компиляции MySQL записывает процедуру в каталог. После завершения записи нажимаем кнопку Finish .

Можно увидеть созданную хранимую процедуру в списке Routines.

Вызов хранимой процедуры

Для вызова хранимой процедуры используется встроенная SQL команда CALL (ВЫЗВАТЬ):

Вместо STORED_PROCEDURE_NAME указывается имя хранимой процедуры, а в скобках указывается список переменных. Для вызова созданной процедуры без переменных будет использоваться код:

Т.к. процедура должна выполнять команду *SELECT FROM products;**, т.е. ВЫБРАТЬ все ИЗ таблицы ПРОДУКТЫ, то примером ее работы может быть следующий результат:

Переменные в хранимых процедурах

Определение 2

Переменная является именованным объектом данных, содержащим некоторое значение при выполнении хранимой процедуры.

Их используют для сохранения какого-либо результата запроса или выражения. Переменные в хранимых процедурах являются локальными, т.е. их нельзя вызвать извне.

Декларирование переменных

Определение 3

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

Для декларирования переменных используется оператор DECLARE :

DECLARE – зарезервированный оператор.

variable_name – название переменной, к которому применяют такие же правила, что и к названию столбца данных в MySQL.

datatype(size) – тип переменной, которая используется, и ее размер. Переменные в MySQL могут принимать значения любого типа данных, например DATETIME, VARCHAR, INT и др.

DEFAULT default_value – позволяет задавать начальное значение переменной. Если оно не задано, то будет установлено значение по умолчанию NULL.

Для создания переменной total_sale, в которой будет храниться список покупок типа INT, и которая по умолчанию будет равна 0, запишем код:

Для декларирования нескольких переменных одного типа можно записать код:

Присвоение значений переменной

Для присвоения значения переменной используют оператор SET .

К примеру, декларируем переменную total_count, а затем присвоим ей значение 10:

Помимо оператора SET может использоваться оператор SELECT INTO для передачи результата запроса в переменную. Обратим внимание, что запрос должен вернуть скалярное значение (т.е. одно).

В первой строке кода объявляется переменная total_products и устанавливается ее значение в 0.

Во второй и третьей строке используется оператор SELECT INTO для записи результата выполнения запроса SELECT COUNT(*) FROM products в созданную переменную.

Область видимости переменных

Каждая переменная имеет свою область видимости, определяющую время ее жизни.

Если создать переменную внутри хранимой процедуры, то она будет существовать, пока используется.

Если декларировать переменную внутри блока BEGIN END, то она будет существовать лишь в пределах этого блока.

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

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

Введение

Хранимая процедура - это способ инкапсуляции повторяющихся действий. В хранимых процедурах можно объявлять переменные, управлять потоками данных, а также применять другие техники программирования.

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

За

  • Разделение логики с другими приложениями. Хранимые процедуры инкапсулируют функциональность; это обеспечивает связность доступа к данным и управления ими между различными приложениями.
  • Изоляция пользователей от таблиц базы данных. Это позволяет давать доступ к хранимым процедурам, но не к самим данным таблиц.
  • Обеспечивает механизм защиты. В соответствии с предыдущим пунктом, если вы можете получить доступ к данным только через хранимые процедуры, никто другой не сможет стереть ваши данные через команду SQL DELETE.
  • Улучшение выполнения как следствие сокращения сетевого трафика. С помощью хранимых процедур множество запросов могут быть объединены.

Против

  • Повышение нагрузки на сервер баз данных в связи с тем, что большая часть работы выполняется на серверной части, а меньшая - на клиентской.
  • Придется много чего подучить. Вам понадобится выучить синтаксис MySQL выражений для написания своих хранимых процедур.
  • Вы дублируете логику своего приложения в двух местах: серверный код и код для хранимых процедур, тем самым усложняя процесс манипулирования данными.
  • Миграция с одной СУБД на другую (DB2, SQL Server и др.) может привести к проблемам.

Инструмент, в котором я работаю, называется MySQL Query Browser, он достаточно стандартен для взаимодействия с базами данных. Инструмент командной строки MySQL - это еще один превосходный выбор. Я рассказываю вам об этом по той причине, что всеми любимый phpMyAdmin не поддерживает выполнение хранимых процедур.

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

Шаг 1: Ставим ограничитель

Ограничитель - это символ или строка символов, который используется для указания клиенту MySQL, что вы завершили написание выражения SQL. Целую вечность ограничителем был символ точки с запятой. Тем не менее, могут возникнуть проблемы, так как в хранимой процедуре может быть несколько выражений, каждое из которых должно заканчиваться точкой с запятой. В этом уроке я использую строку “//” в качестве ограничителя.

Шаг 2: Как работать с хранимыми процедурами

Создание хранимой процедуры

DELIMITER // CREATE PROCEDURE `p2` () LANGUAGE SQL DETERMINISTIC SQL SECURITY DEFINER COMMENT "A procedure" BEGIN SELECT "Hello World !"; END//

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

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

4 характеристики хранимой процедуры:

  • Language: в целях обеспечения переносимости, по умолчанию указан SQL.
  • Deterministic: если процедура все время возвращает один и тот же результат, и принимает одни и те же входящие параметры. Это для репликации и процесса регистрации. Значение по умолчанию - NOT DETERMINISTIC.
  • SQL Security: во время вызова идет проверка прав пользователя. INVOKER - это пользователь, вызывающий хранимую процедуру. DEFINER - это “создатель” процедуры. Значение по умолчанию - DEFINER.
  • Comment: в целях документирования, значение по умолчанию - ""

Вызов хранимой процедуры

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

CALL stored_procedure_name (param1, param2, ....) CALL procedure1(10 , "string parameter" , @parameter_var);

Изменение хранимой процедуры

В MySQL есть выражение ALTER PROCEDURE для изменения процедур, но оно подходит для изменения лишь некоторых характеристик. Если вам нужно изменить параметры или тело процедуры, вам следует удалить и создать ее заново.

Удаление хранимой процедуры

DROP PROCEDURE IF EXISTS p2;

Это простая команда. Выражение IF EXISTS отлавливает ошибку в случае, если такой процедуры не существует.

Шаг 3: Параметры

Давайте посмотрим, как можно передавать в хранимую процедуру параметры.

  • CREATE PROCEDURE proc1 (): пустой список параметров
  • CREATE PROCEDURE proc1 (IN varname DATA-TYPE): один входящий параметр. Слово IN необязательно, потому что параметры по умолчанию - IN (входящие).
  • CREATE PROCEDURE proc1 (OUT varname DATA-TYPE): один возвращаемый параметр.
  • CREATE PROCEDURE proc1 (INOUT varname DATA-TYPE): один параметр, одновременно входящий и возвращаемый.

Естественно, вы можете задавать несколько параметров разных типов.

Пример параметра IN

DELIMITER // CREATE PROCEDURE `proc_IN` (IN var1 INT) BEGIN SELECT var1 + 2 AS result; END//

Пример параметра OUT

DELIMITER // CREATE PROCEDURE `proc_OUT` (OUT var1 VARCHAR(100)) BEGIN SET var1 = "This is a test"; END //

Пример параметра INOUT

DELIMITER // CREATE PROCEDURE `proc_INOUT` (OUT var1 INT) BEGIN SET var1 = var1 * 2; END //

Шаг 4: Переменные

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

Синтаксис объявления переменной выглядит так:

DECLARE varname DATA-TYPE DEFAULT defaultvalue;

Давайте объявим несколько переменных:

DECLARE a, b INT DEFAULT 5; DECLARE str VARCHAR(50); DECLARE today TIMESTAMP DEFAULT CURRENT_DATE; DECLARE v1, v2, v3 TINYINT;

Работа с переменными

Как только вы объявили переменную, вы можете задать ей значение с помощью команд SET или SELECT:

DELIMITER // CREATE PROCEDURE `var_proc` (IN paramstr VARCHAR(20)) BEGIN DECLARE a, b INT DEFAULT 5; DECLARE str VARCHAR(50); DECLARE today TIMESTAMP DEFAULT CURRENT_DATE; DECLARE v1, v2, v3 TINYINT; INSERT INTO table1 VALUES (a); SET str = "I am a string"; SELECT CONCAT(str,paramstr), today FROM table2 WHERE b >=5; END //

Шаг 5: Структуры управления потоками

MySQL поддерживает конструкции IF, CASE, ITERATE, LEAVE LOOP, WHILE и REPEAT для управления потоками в пределах хранимой процедуры. Мы рассмотрим, как использовать IF, CASE и WHILE, так как они наиболее часто используются.

Конструкция IF

С помощью конструкции IF, мы можем выполнять задачи, содержащие условия:

DELIMITER // CREATE PROCEDURE `proc_IF` (IN param1 INT) BEGIN DECLARE variable1 INT; SET variable1 = param1 + 1; IF variable1 = 0 THEN SELECT variable1; END IF; IF param1 = 0 THEN SELECT "Parameter value = 0"; ELSE SELECT "Parameter value <> 0"; END IF; END //

Конструкция CASE

CASE - это еще один метод проверки условий и выбора подходящего решения. Это отличный способ замены множества конструкций IF. Конструкцию можно описать двумя способами, предоставляя гибкость в управлении множеством условных выражений.

DELIMITER // CREATE PROCEDURE `proc_CASE` (IN param1 INT) BEGIN DECLARE variable1 INT; SET variable1 = param1 + 1; CASE variable1 WHEN 0 THEN INSERT INTO table1 VALUES (param1); WHEN 1 THEN INSERT INTO table1 VALUES (variable1); ELSE INSERT INTO table1 VALUES (99); END CASE; END //

DELIMITER // CREATE PROCEDURE `proc_CASE` (IN param1 INT) BEGIN DECLARE variable1 INT; SET variable1 = param1 + 1; CASE WHEN variable1 = 0 THEN INSERT INTO table1 VALUES (param1); WHEN variable1 = 1 THEN INSERT INTO table1 VALUES (variable1); ELSE INSERT INTO table1 VALUES (99); END CASE; END //

Конструкция WHILE

Технически, существует три вида циклов: цикл WHILE, цикл LOOP и цикл REPEAT. Вы также можете организовать цикл с помощью техники программирования “Дарта Вейдера”: выражения GOTO. Вот пример цикла:

DELIMITER // CREATE PROCEDURE `proc_WHILE` (IN param1 INT) BEGIN DECLARE variable1, variable2 INT; SET variable1 = 0; WHILE variable1 < param1 DO INSERT INTO table1 VALUES (param1); SELECT COUNT(*) INTO variable2 FROM table1; SET variable1 = variable1 + 1; END WHILE; END //

Шаг 6: Курсоры

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

MySQL поддерживает курсоры в хранимых процедурах. Вот краткий синтаксис создания и использования курсора.

DECLARE cursor-name CURSOR FOR SELECT ...; /*Объявление курсора и его заполнение */ DECLARE CONTINUE HANDLER FOR NOT FOUND /*Что делать, когда больше нет записей*/ OPEN cursor-name; /*Открыть курсор*/ FETCH cursor-name INTO variable [, variable]; /*Назначить значение переменной, равной текущему значению столбца*/ CLOSE cursor-name; /*Закрыть курсор*/

В этом примере мы проведем кое-какие простые операции с использованием курсора:

DELIMITER // CREATE PROCEDURE `proc_CURSOR` (OUT param1 INT) BEGIN DECLARE a, b, c INT; DECLARE cur1 CURSOR FOR SELECT col1 FROM table1; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur1; SET b = 0; SET c = 0; WHILE b = 0 DO FETCH cur1 INTO a; IF b = 0 THEN SET c = c + a; END IF; END WHILE; CLOSE cur1; SET param1 = c; END //

У курсоров есть три свойства, которые вам необходимо понять, чтобы избежать получения неожиданных результатов:

  • Не чувствительный: открывшийся однажды курсор не будет отображать изменения в таблице, происшедшие позже. В действительности, MySQL не гарантирует то, что курсор обновится, так что не надейтесь на это.
  • Доступен только для чтения: курсоры нельзя изменять.
  • Без перемотки: курсор способен проходить только в одном направлении - вперед, вы не сможете пропускать строки, не выбирая их.

Заключение

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

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