Вы находитесь на странице: 1из 28

SQL

функции и

процедуры
Содержание
1) Определения

2) Применение

3) Типы переменных

4) Процедуры

5) Функции

6) Практика
Определения
Хранимая процедура - это объект базы данных,
представляющий собой набор SQL-инструкций, который
компилируется один раз и хранится на сервере.

Позволяет:

- Выполнять DDL / DML команды

- Использовать циклы и ветвления

- Работать с переменными
Определения
Хранимая Функция – Объект БД содержащий
исполняемый код. Выполняет действия над данными и
возвращает некоторое значение/набор.
Выделяют:

- Табличные функции (не для MySQL)

- Скалярные

- Встроенные (LOG, REPLACE, MONTH и т.д.)


Процедура vs Функция
1. Функция ВСЕГДА возвращает что то...
2. Функция НЕ может изменять данные в таблицах
3. Разные способы вызова
4. Процедура может вызывать функцию, а функция
процедуру – НЕТ
5. Разный момент компиляции

https://blogs.msdn.microsoft.com/pradeepsvs/2014/10/08/di
fference-between-a-stored-procedure-and-function/
Применение
1. Реализация модульного подхода при работе
2. Функция НЕ может изменять данные в таблицах
3. Повышение производительности
Переменные
1. Пользовательские переменные (с префиксом
@)
Доступ без объявления или инициализации.

Инициализация:
SET @start = 10000, @finish = 10005;

SELECT * FROM employees WHERE emp_no BETWEEN


@start AND @finish;
Переменные
2. Локальные переменные (БЕЗ префиксов)
Должны быть объявлены с помощью DECLARE и
используются в функциях и процедурах, т.к. они
доступны ТОЛЬКО в рамках выполняемых действий.

CREATE PROCEDURE Test1()


BEGIN
DECLARE start INT DEFAULT 10005;
SELECT * FROM employees WHERE place < start;
……
Переменные
3. Системные переменные (С префиксом @@)
Не зависят от сеансов пользователей и влияют на
работу системы в целом.

Для просмотра можно использовать:


SHOW VARIABLES LIKE '%wait_timeout%';
SELECT @@sort_buffer_size;

http://qaru.site/questions/35885/how-to-declare-a-variable-
in-mysql
Хранимая процедура
delimiter //
CREATE [DEFINER = { user | CURRENT_USER }]
PROCEDURE pr_name ([proc_parameter[,...]])
[characteristic ...]
BEGIN
Valid SQL routine statement;
END//;
delimiter ;
Хранимая процедура
proc_parameter:
[ IN | OUT | INOUT ] param_name type

type:
Any valid MySQL data type
(CHAR(size), TEXT, INT(size), DOUBLE(size,d), DATE() ….)

characteristic:
COMMENT 'string' | LANGUAGE SQL | [NOT]
DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL
DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER |
INVOKER }
https://dev.mysql.com/doc/refman/8.0/en/create-
procedure.html
Хранимая процедура
Давайте создадим процедуру,
которая НЕ будет иметь
входящих параметров, а
просто будет увеличивать ЗП
на 10% всем работникам за
все месяцы .

Скрипт-помощник:
SELECT FLOOR(a + (RAND() * b))
as assistant
Хранимая процедура
CREATE PROCEDURE employees.proc_10per()
BEGIN
DECLARE per10 int DEFAULT 10;
UPDATE salaries set salary=salary+salary*Per10/100;
END;
Хранимая процедура
Выполнение:
CALL sp_name([parameter[,...]])
Например:
CALL proc_10per()

Удаление:
DROP PROCEDURE sp_name;
Например:
DROP PROCEDURE proc_10per
Хранимая процедура
А можно ли изменить процедуру?

MySQL
However, you cannot change the parameters or body of a stored
procedure using this statement; to make such changes, you must
drop and re-create the procedure
using DROP PROCEDURE and CREATE PROCEDURE
Хранимая процедура
А можно ли изменить процедуру?

MySQL
However, you cannot change the parameters or body of a stored
procedure using this statement; to make such changes, you must
drop and re-create the procedure
using DROP PROCEDURE and CREATE PROCEDURE
Пользовательская
delimiter //
CREATE [DEFINERфункция
= { user | CURRENT_USER }]
FUNCTION sp_name ([func_parameter[,...]])
[characteristic ...]
RETURNS type
[characteristic ...] routine_body
BEGIN
Valid SQL routine statement;
RETURN ХХ;
END//;
delimiter ;
https://dev.mysql.com/doc/refman/8.0/en/create-
procedure.html
Пользовательская
Давайте создадим функцию
функция
БЕЗ входящих параметров,
которая просто вернет
значение средней зарплаты
по всем выплатам компании.
Пользовательская
функция
CREATE FUNCTION AVG_Salary()
RETURNS int(5)
BEGIN
SELECT avg(salary) INTO @cq from
employees.salaries;
RETURN @cq;
END;
Пользовательская
функция
Выполнение (1 - SET):
SET @cq=AVG_Salary()
SELECT @cq;
Выполнение (2 - SELECT):
SELECT AVG_Salary()
SELECT @cq;
Удаление:
DROP FUNCTION f_name;
Например:
DROP FUNCTION AVG_Salary;
Практика
Давайте доработаем нашу процедуру с увеличением ЗП
на 10% и добавим входной параметр для определения
процента увеличения.
CREATE PROCEDURE
employees.proc_10per()
BEGIN
DECLARE per10 int DEFAULT 10;
UPDATE salaries set
salary=salary+salary*Per10/100;CREATE PROCEDURE employees.proc_per_user
END; (in Per int(5))
BEGIN
UPDATE salaries set
salary=salary+salary*Per/100;
END;
Практика
Необходимо написать функцию, которая будет
возвращать возраст сотрудника на основании его даты
рождения + его дату рождения, фамилию, имя.

Для определения был ли День рождения в текущем году,


используем выражение:

( (YEAR(CURRENT_DATE) - YEAR(Date)) –
(DATE_FORMAT(CURRENT_DATE, '%m%d') < DATE_FORMAT(Date, '%m
%d')) )
Практика
CREATE FUNCTION birthday (EmplNo INT(5))
returns INT(5)
BEGIN
DECLARE EmplDa DATE;
SET EmplDa =
(SELECT birth_date from employees where
emp_no=EmplNo);
SELECT
( (YEAR(CURRENT_DATE) - YEAR(EmplDa)) -

(DATE_FORMAT(CURRENT_DATE, '%m%d') <


DATE_FORMAT(EmplDa, '%m%d')) )
INTO @cq;
RETURN @cq;
Практика
SELECT birthday(emp_no) as age, birth_date, first_name,
last_name FROM employees;
Практика
Необходимо создать функцию, которая будет
возвращать Фамилию + Имя + Пол в формате (Male /
Female / No gender) в списке сотрудников. Входной
параметр – ID пользователя
Практика
CREATE function FIO_Gender (EmplNo int(5))
RETURNS VARCHAR(50)
BEGIN
DECLARE FIRSTNAME VARCHAR(20);
DECLARE LASTTNAME VARCHAR(20);
DECLARE GENDERr VARCHAR(10);
SET GENDERr = (SELECT gender from employees where emp_no=EmplNo);
SET FIRSTNAME = (SELECT first_name from employees where emp_no=EmplNo);
SET LASTTNAME = (SELECT last_name from employees where emp_no=EmplNo);
IF GENDERr ='M' THEN set GENDERr='Male';
ELSEIF GENDERr ='F' THEN set GENDERr='FeMale';
ELSE set GENDERr ='No gender';
END IF;
RETURN CONCAT(FIRSTNAME, ' ', LASTTNAME, ' is ', GENDERr);
END;
Вопросы ?