Хранимые процедуры — различия между версиями
Dmitriy (обсуждение | вклад) м (-- fix, links) |
м (rollbackEdits.php mass rollback) |
||
(не показаны 4 промежуточные версии 2 участников) | |||
Строка 32: | Строка 32: | ||
**Можно позволить пользователь работать с недоступными для него данными, но через предоставленный нами интерфейс. Для этого делаем процедуру, работающую с этими данными, даем ей права <font color = blue>definer</font> и разрешаем выполнять пользователю. | **Можно позволить пользователь работать с недоступными для него данными, но через предоставленный нами интерфейс. Для этого делаем процедуру, работающую с этими данными, даем ей права <font color = blue>definer</font> и разрешаем выполнять пользователю. | ||
**Права <font color = blue>definer</font> наследуются при вызове других функций (иначе может не хватить прав при вызове процедуры, объявленной с правами <font color = blue>invoker</font>). | **Права <font color = blue>definer</font> наследуются при вызове других функций (иначе может не хватить прав при вызове процедуры, объявленной с правами <font color = blue>invoker</font>). | ||
− | *Тело может быть как одним оператором (к примеру, <font color = blue>select</font> или <font color = blue>insert</font>), так и | + | *Тело может быть как одним оператором (к примеру, <font color = blue>select</font> или <font color = blue>insert</font>), так и [[Хранимые процедуры и функции: операторы#Составной оператор| составным оператором]]. См. также [[Хранимые процедуры#Разделители | разделители]]. |
=== Примеры === | === Примеры === | ||
Строка 61: | Строка 61: | ||
== Разделители == | == Разделители == | ||
− | Рассмотрим пример. Подробнее про содержимое <font color = blue>begin/end</font> см. [операторы]. | + | Рассмотрим пример. Подробнее про содержимое <font color = blue><font color = blue>begin</font>/<font color = blue>end</font></font> см. [[Хранимые процедуры и функции: операторы|операторы]]. |
− | create procedure foo() | + | <font color = blue>create procedure</font> foo() |
− | begin | + | <font color = blue>begin</font> |
− | declare x int; | + | <font color = blue>declare</font> x int; |
− | set x = 42; | + | <font color = blue>set</font> x = 42; |
− | end; | + | <font color = blue>end</font>; |
− | Жадный парсер прочитает до первого разделителя (а он по умолчанию ";") и получится синтаксическая ошибка, так как объявление функции уже закончилось и он встречает строку "set x = 42;". | + | Жадный парсер прочитает до первого разделителя (а он по умолчанию ";") и получится синтаксическая ошибка, так как объявление функции уже закончилось и он встречает строку "<font color = blue>set</font> x = 42;". |
− | create procedure foo() | + | <font color = blue>create procedure</font> foo() |
− | begin | + | <font color = blue>begin</font> |
− | declare x int; | + | <font color = blue>declare</font> x int; |
− | + | -------------- | |
− | set x = 42; | + | <font color = blue>set</font> x = 42; |
− | end; | + | <font color = blue>end</font>; |
− | Выход {{---}} объявить на время другой разделитель. Так мы не сможем "разорвать" содержимое <font color = blue>begin/end</font>. | + | Выход {{---}} объявить на время другой разделитель. Так мы не сможем "разорвать" содержимое <font color = blue><font color = blue>begin</font>/<font color = blue>end</font></font>. |
− | DELIMITER // | + | <font color = blue>DELIMITER</font> // |
− | create procedure foo() | + | <font color = blue>create procedure</font> foo() |
− | begin | + | <font color = blue>begin</font> |
− | declare x int; | + | <font color = blue>declare</font> x int; |
− | set x = 42; | + | <font color = blue>set</font> x = 42; |
− | end; | + | <font color = blue>end</font>; |
// | // | ||
− | DELIMITER ; | + | <font color = blue>DELIMITER</font> ; |
NB: Некоторые СУБД умеют парсить так, как нам хочется. | NB: Некоторые СУБД умеют парсить так, как нам хочется. | ||
Строка 90: | Строка 90: | ||
== См. также == | == См. также == | ||
*[[Хранимые функции]] | *[[Хранимые функции]] | ||
− | *[[ | + | *[[Хранимые процедуры и функции: операторы]] |
==Литература== | ==Литература== |
Текущая версия на 19:08, 4 сентября 2022
Определение: |
Хранимая процедура — фрагмент кода, хранящийся в БД. |
Содержание
Достоинства и мотивация
Чем отличаются от хранимых функций.
Достоинства кода, хранящегося в БД:
- Обработка данных производится непосредственно на стороне БД.
- БД много знает про код — можно скомпилировать, построить оптимальный план исполнения.
- Дает возможность работать с недоступными данными с помощью заданного нами интерфейса.
- Более удобная работа с изменением данных — предварительные проверки, изменение сразу в нескольких местах.
Объявление
Синтаксис
create procedure имя(параметры) [language {sql|...}] [[not] deterministic] {contains sql|reads sql data|modifies sql data|no sql} [{returns null|called} on null input] [sql security {definer|invoker}] тело
- Параметры — список параметров через запятую. Объявление параметра: {in | out | inout} имя тип.
- in (умолч.) — внешний мир не узнает об изменении параметра.
- out — запись результата, но читать изначальное значение нельзя.
- inout — запись результата, но читать изначальное значение можно.
- language — язык, на котором написала процедура. По умолчанию sql. Также поддерживаются Ada, C, COBOL, Fortran, MUMPS, Pascal, PLI.
- [not] deterministic — является ли процедура детерминированной. По умолчанию — нет.
- Отношение к данным. Соответственно: выполняет произвольные SQL операторы (умолч.), только читает, только изменяет, с данными не работает.
- Отношение к null-агрументам. Соответственно: процедура не вызовется и вернет null, процедура вызовется (умолч.).
- Управление доступом. Соответственно: запускается с правами того, кто создал процедуру, с правами того, кто процедуру вызвал (умолч.).
- Можно позволить пользователь работать с недоступными для него данными, но через предоставленный нами интерфейс. Для этого делаем процедуру, работающую с этими данными, даем ей права definer и разрешаем выполнять пользователю.
- Права definer наследуются при вызове других функций (иначе может не хватить прав при вызове процедуры, объявленной с правами invoker).
- Тело может быть как одним оператором (к примеру, select или insert), так и составным оператором. См. также разделители.
Примеры
create procedure s() language sql reads sql data select * from Students;
create procedure t(id int, in id1 int, inout i int, out ans int) language sql deterministic modifies sql data called on null input sql security invoker begin -- some operators end
Вызов
Синтаксис
exec имя(аргументы)
Доступ
Чтобы вызывать процедуру, нужно иметь привилегию execute. Может выполняться с разными правами доступа, указанными в объявлении.
Пример
exec ChangeName('Иванов', 'Петров');
Разделители
Рассмотрим пример. Подробнее про содержимое begin/end см. операторы.
create procedure foo() begin declare x int; set x = 42; end;
Жадный парсер прочитает до первого разделителя (а он по умолчанию ";") и получится синтаксическая ошибка, так как объявление функции уже закончилось и он встречает строку "set x = 42;".
create procedure foo() begin declare x int; -------------- set x = 42; end;
Выход — объявить на время другой разделитель. Так мы не сможем "разорвать" содержимое begin/end.
DELIMITER // create procedure foo() begin declare x int; set x = 42; end; // DELIMITER ;
NB: Некоторые СУБД умеют парсить так, как нам хочется.
См. также
Литература
- Дейт К. Введение в системы баз данных (главы 4 и 17)
- Уидом Д., Ульман Д. Основы реляционных баз данных (раздел 7.4)
- Gulutzan P., Pelzer T. SQL-99 complete, really