Хранимые процедуры — различия между версиями
Dmitriy (обсуждение | вклад) (init) |
Dmitriy (обсуждение | вклад) м (-- fix, links) |
||
Строка 1: | Строка 1: | ||
− | {{Определение|definition = '''Хранимая процедура''' | + | {{Определение|definition = '''Хранимая процедура''' {{---}} фрагмент кода, хранящийся в БД.}} |
− | + | == Достоинства и мотивация == | |
+ | Чем отличаются от [[Хранимые функции#Отличие от хранимых процедур | хранимых функций]]. | ||
Достоинства кода, хранящегося в БД: | Достоинства кода, хранящегося в БД: | ||
*Обработка данных производится непосредственно на стороне БД. | *Обработка данных производится непосредственно на стороне БД. | ||
− | *БД много знает про код -- можно скомпилировать, построить оптимальный план исполнения. | + | *БД много знает про код {{---}} можно скомпилировать, построить оптимальный план исполнения. |
*Дает возможность работать с недоступными данными с помощью заданного нами интерфейса. | *Дает возможность работать с недоступными данными с помощью заданного нами интерфейса. | ||
− | *Более удобная работа с изменением данных -- предварительные проверки, изменение сразу в нескольких местах. | + | *Более удобная работа с изменением данных {{---}} предварительные проверки, изменение сразу в нескольких местах. |
− | |||
− | |||
== Объявление == | == Объявление == | ||
Строка 22: | Строка 21: | ||
<font color = red>тело</font> | <font color = red>тело</font> | ||
− | *<font color = red>Параметры</font> -- список параметров через запятую. Объявление параметра: {<font color = blue>in</font> | <font color = blue>out</font> | <font color = blue>inout</font>} имя тип. | + | *<font color = red>Параметры</font> {{---}} список параметров через запятую. Объявление параметра: {<font color = blue>in</font> | <font color = blue>out</font> | <font color = blue>inout</font>} имя тип. |
− | **<font color = blue>in</font> (умолч.) -- внешний мир не узнает об изменении параметра. | + | **<font color = blue>in</font> (умолч.) {{---}} внешний мир не узнает об изменении параметра. |
− | **<font color = blue>out</font> -- запись результата, но читать изначальное значение нельзя. | + | **<font color = blue>out</font> {{---}} запись результата, но читать изначальное значение нельзя. |
− | **<font color = blue>inout</font> -- запись результата, но читать изначальное значение можно. | + | **<font color = blue>inout</font> {{---}} запись результата, но читать изначальное значение можно. |
− | *<font color = blue>language</font> -- язык, на котором написала процедура. По умолчанию <font color = blue>sql</font>. Также поддерживаются <font color = blue>Ada</font>, <font color = blue>C</font>, <font color = blue>COBOL</font>, <font color = blue>Fortran</font>, <font color = blue>MUMPS</font>, <font color = blue>Pascal</font>, <font color = blue>PLI</font>. | + | *<font color = blue>language</font> {{---}} язык, на котором написала процедура. По умолчанию <font color = blue>sql</font>. Также поддерживаются <font color = blue>Ada</font>, <font color = blue>C</font>, <font color = blue>COBOL</font>, <font color = blue>Fortran</font>, <font color = blue>MUMPS</font>, <font color = blue>Pascal</font>, <font color = blue>PLI</font>. |
− | *[<font color = blue>not</font>] <font color = blue>deterministic</font> -- является ли процедура детерминированной. По умолчанию -- нет. | + | *[<font color = blue>not</font>] <font color = blue>deterministic</font> {{---}} является ли процедура детерминированной. По умолчанию {{---}} нет. |
*Отношение к данным. Соответственно: выполняет произвольные SQL операторы (умолч.), только читает, только изменяет, с данными не работает. | *Отношение к данным. Соответственно: выполняет произвольные SQL операторы (умолч.), только читает, только изменяет, с данными не работает. | ||
*Отношение к null-агрументам. Соответственно: процедура не вызовется и вернет <font color = red>null</font>, процедура вызовется (умолч.). | *Отношение к null-агрументам. Соответственно: процедура не вызовется и вернет <font color = red>null</font>, процедура вызовется (умолч.). | ||
Строка 33: | Строка 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>begin</font>/<font color = blue>end</font>. См [разделители] | + | *Тело может быть как одним оператором (к примеру, <font color = blue>select</font> или <font color = blue>insert</font>), так и произвольным количеством операторов, заключенных в <font color = blue>begin</font>/<font color = blue>end</font>. См. [[Хранимые процедуры#Разделители | разделители]]. |
=== Примеры === | === Примеры === | ||
Строка 56: | Строка 55: | ||
===Доступ=== | ===Доступ=== | ||
Чтобы вызывать процедуру, нужно иметь привилегию <font color = blue>execute</font>. | Чтобы вызывать процедуру, нужно иметь привилегию <font color = blue>execute</font>. | ||
− | Может выполняться с разными правами доступа, указанными в [объявлении]. | + | Может выполняться с разными правами доступа, указанными в [[Хранимые процедуры#Объявление | объявлении]]. |
=== Пример === | === Пример === | ||
Строка 73: | Строка 72: | ||
begin | begin | ||
declare x int; | declare x int; | ||
− | --------------- | + | {{---}}{{---}}{{---}}{{---}}{{---}}{{---}}{{---}}- |
set x = 42; | set x = 42; | ||
end; | end; | ||
− | Выход -- объявить на время другой разделитель. Так мы не сможем "разорвать" содержимое <font color = blue>begin/end</font>. | + | Выход {{---}} объявить на время другой разделитель. Так мы не сможем "разорвать" содержимое <font color = blue>begin/end</font>. |
DELIMITER // | DELIMITER // | ||
create procedure foo() | create procedure foo() |
Версия 03:09, 20 декабря 2021
Определение: |
Хранимая процедура — фрагмент кода, хранящийся в БД. |
Содержание
Достоинства и мотивация
Чем отличаются от хранимых функций.
Достоинства кода, хранящегося в БД:
- Обработка данных производится непосредственно на стороне БД.
- БД много знает про код — можно скомпилировать, построить оптимальный план исполнения.
- Дает возможность работать с недоступными данными с помощью заданного нами интерфейса.
- Более удобная работа с изменением данных — предварительные проверки, изменение сразу в нескольких местах.
Объявление
Синтаксис
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), так и произвольным количеством операторов, заключенных в begin/end. См. разделители.
Примеры
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