Хранимые процедуры — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(init)
 
м (rollbackEdits.php mass rollback)
 
(не показано 5 промежуточных версий 2 участников)
Строка 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>), так и [[Хранимые процедуры и функции: операторы#Составной оператор| составным оператором]]. См. также [[Хранимые процедуры#Разделители | разделители]].
  
 
=== Примеры ===  
 
=== Примеры ===  
Строка 56: Строка 55:
 
===Доступ===
 
===Доступ===
 
Чтобы вызывать процедуру, нужно иметь привилегию <font color = blue>execute</font>.
 
Чтобы вызывать процедуру, нужно иметь привилегию <font color = blue>execute</font>.
Может выполняться с разными правами доступа, указанными в [объявлении].
+
Может выполняться с разными правами доступа, указанными в [[Хранимые процедуры#Объявление | объявлении]].
  
 
=== Пример ===
 
=== Пример ===
Строка 62: Строка 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: Некоторые СУБД умеют парсить так, как нам хочется.
Строка 91: Строка 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: Некоторые СУБД умеют парсить так, как нам хочется.

См. также

Литература