Материал: Using_MySql,_MS_SQL_Server_and_Oracle(1)

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Пример 37: контроль операций с данными с использованием хранимых функций

5.1.2.Пример 37: контроль операций с данными с использованием хранимых функций

Задача 5.1.2.a{370}: создать хранимую функцию, автоматизирующую проверку условий задачи 4.2.1.a{315}, т.е. возвращающую значение 1 (все условия выполнены) или -1, -2, -3 (если хотя бы одно условие нарушено, модуль числа соответствует номеру условия) в зависимости от того, выполняются ли следующие условия:

дата выдачи книги не может находиться в будущем;

дата возврата книги не может находиться в прошлом (только в случае вставки данных);

дата возврата книги не может быть меньше даты выдачи книги.

Задача 5.1.2.b{373}: создать хранимую функцию, автоматизирующую проверку условий задачи 4.2.2.a{338}, т.е. возвращающую 1, если имя читателя содержит хотя бы два слова и одну точку, и 0, если это условие нарушено.

Ожидаемый результат 5.1.2.a.

Функция возвращает 1, если все условия задачи выполнены, и 0, если хотя бы одно условие нарушено.

Ожидаемый результат 5.1.2.b.

Функция возвращает 1, если условие задачи выполнено, и 0, если оно нару-

шено.

Решение 5.1.2.a{370}.

Во всех трёх СУБД логика решения данной задачи будет одинакова: мы передадим в функцию три параметра (дату выдачи книги, дату возврата книги, признак обновления данных), проверим в теле функции выполнение условий и вернём соответствующее число.

MySQL

Решение 5.1.2.a (код функции)

1DELIMITER $$

2CREATE FUNCTION CHECK_SUBSCRIPTION_DATES(sb_start DATE,

3

 

sb_finish

DATE,

4

 

is_insert

INT)

 

 

 

 

5RETURNS INT

6DETERMINISTIC

7BEGIN

8DECLARE result INT DEFAULT 1;

9

10-- Блокировка выдач книг с датой выдачи в будущем

11IF (sb_start > CURDATE())

12THEN

13SET result = -1;

14END IF;

15

16-- Блокировка выдач книг с датой возврата в прошлом.

17IF ((sb_finish < CURDATE()) AND (is_insert = 1))

18THEN

19SET result = -2;

20END IF;

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 370/545

Пример 37: контроль операций с данными с использованием хранимых функций

MySQL

Решение 5.1.2.a (код функции) (продолжение)

21-- Блокировка выдач книг с датой возврата меньшей, чем дата выдачи.

22IF (sb_finish < sb_start)

23THEN

24SET result = -3;

25END IF;

26

27RETURN result;

28END;

29$$

30DELIMITER ;

MySQL

Решение 5.1.2.a (код для проверки работы функции)

1SELECT CHECK_SUBSCRIPTION_DATES('2025-01-01', '2026-01-01', 1);

2SELECT CHECK_SUBSCRIPTION_DATES('2025-01-01', '2026-01-01', 0);

3

4SELECT CHECK_SUBSCRIPTION_DATES('2005-01-01', '2006-01-01', 1);

5SELECT CHECK_SUBSCRIPTION_DATES('2005-01-01', '2006-01-01', 0);

6

7SELECT CHECK_SUBSCRIPTION_DATES('2005-01-01', '2004-01-01', 1);

8SELECT CHECK_SUBSCRIPTION_DATES('2005-01-01', '2004-01-01', 0);

MS SQL Решение 5.1.2.a (код функции)

1

 

CREATE FUNCTION CHECK_SUBSCRIPTION_DATES(@sb_start DATE,

2

 

@sb_finish

DATE,

3

 

@is_insert

INT)

 

 

 

 

4RETURNS INT

5WITH SCHEMABINDING

6AS

7BEGIN

8DECLARE @result INT = 1;

9

10-- Блокировка выдач книг с датой выдачи в будущем

11IF (@sb_start > CONVERT(date, GETDATE()))

12BEGIN

13SET @result = -1;

14END;

15

16-- Блокировка выдач книг с датой возврата в прошлом.

17IF ((@sb_finish < CONVERT(date, GETDATE())) AND (@is_insert = 1))

18BEGIN

19SET @result = -2;

20END;

21

22-- Блокировка выдач книг с датой возврата меньшей, чем дата выдачи.

23IF (@sb_finish < @sb_start)

24BEGIN

25SET @result = -3;

26END;

27

28RETURN @result;

29END;

MS SQL

Решение 5.1.2.a (код для проверки работы функции)

1SELECT dbo.CHECK_SUBSCRIPTION_DATES('2025-01-01', '2026-01-01', 1);

2SELECT dbo.CHECK_SUBSCRIPTION_DATES('2025-01-01', '2026-01-01', 0);

3

4SELECT dbo.CHECK_SUBSCRIPTION_DATES('2005-01-01', '2006-01-01', 1);

5SELECT dbo.CHECK_SUBSCRIPTION_DATES('2005-01-01', '2006-01-01', 0);

6

7SELECT dbo.CHECK_SUBSCRIPTION_DATES('2005-01-01', '2004-01-01', 1);

8SELECT dbo.CHECK_SUBSCRIPTION_DATES('2005-01-01', '2004-01-01', 0);

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 371/545

Пример 37: контроль операций с данными с использованием хранимых функций

 

Oracle

 

Решение 5.1.2.a (код функции)

 

1

 

CREATE OR REPLACE FUNCTION CHECK_SUBSCRIPTION_DATES (sb_start DATE,

 

2

 

 

sb_finish DATE,

 

3

 

 

is_insert INT)

4RETURN NUMBER DETERMINISTIC IS

5result_value NUMBER := 1;

6BEGIN

7-- Блокировка выдач книг с датой выдачи в будущем

8IF (sb_start > TRUNC(SYSDATE))

9THEN

10result_value := -1;

11END IF;

12

13-- Блокировка выдач книг с датой возврата в прошлом.

14IF ((sb_finish < TRUNC(SYSDATE)) AND (is_insert = 1))

15THEN

16result_value := -2;

17END IF;

18

19-- Блокировка выдач книг с датой возврата меньшей, чем дата выдачи.

20IF (sb_finish < sb_start)

21THEN

22result_value := -3;

23END IF;

24

25RETURN result_value;

26END;

Oracle

Решение 5.1.2.a (код для проверки работы функции)

1SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2025-01-01', 'YYYY-MM-DD'),

2TO_DATE('2026-01-01', 'YYYY-MM-DD'), 1) FROM dual;

3SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2025-01-01', 'YYYY-MM-DD'),

4TO_DATE('2026-01-01', 'YYYY-MM-DD'), 0) FROM dual;

5

6SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2005-01-01', 'YYYY-MM-DD'),

7TO_DATE('2006-01-01', 'YYYY-MM-DD'), 1) FROM dual;

8SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2005-01-01', 'YYYY-MM-DD'),

9TO_DATE('2006-01-01', 'YYYY-MM-DD'), 0) FROM dual;

10

11SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2005-01-01', 'YYYY-MM-DD'),

12TO_DATE('2004-01-01', 'YYYY-MM-DD'), 1) FROM dual;

13SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2005-01-01', 'YYYY-MM-DD'),

14TO_DATE('2004-01-01', 'YYYY-MM-DD'), 0) FROM dual;

Сам код функций примитивен и не нуждается в пояснениях, но стоит отметить отличие логики представленного здесь решения от логики решения{315} задачи

4.2.1.a{315}.

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

Здесь же мы в решениях для всех трёх СУБД возвращаем результат лишь в самом конце тела функции, потому провал каждой следующей проверки будет аннулировать признак провала предыдущей проверки.

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

На этом решение данной задачи завершено.

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 372/545

Пример 37: контроль операций с данными с использованием хранимых функций

Решение 5.1.2.b{370}.

По сравнению с предыдущей задачей здесь всё будет ещё проще: нужно просто «обернуть» в функцию две проверки, на основе результата которых возвратить

1 или 0.

Только в решении для MS SQL Server будет одна необычная деталь: мы вынуждены использовать промежуточную переменную и возвращать её значение в самом конце тела функции, т.к. данная СУБД требует, чтобы последним выражением внутри хранимой функции был оператор RETURN.

MySQL Решение 5.1.2.b (код функции)

1DROP FUNCTION IF EXISTS CHECK_SUBSCRIBER_NAME;

2DELIMITER $$

3CREATE FUNCTION CHECK_SUBSCRIBER_NAME(subscriber_name VARCHAR(150)) RETURNS

4INT DETERMINISTIC

5BEGIN

6IF ((CAST(subscriber_name AS CHAR CHARACTER SET cp1251) REGEXP

7CAST('^[a-zA-Zа-яА-ЯёЁ\'-]+([^a-zA-Zа-яА-ЯёЁ\'-]+[a-zA-Zа-яА-

8ЯёЁ\'.-]+){1,}$' AS CHAR CHARACTER SET cp1251)) = 0)

9OR (LOCATE('.', subscriber_name) = 0)

10THEN

11RETURN 0;

12ELSE

13RETURN 1;

14END IF;

15END;

16$$

17DELIMITER ;

MySQL

Решение 5.1.2.b (код для проверки работы функции)

1SELECT CHECK_SUBSCRIBER_NAME(

2SELECT CHECK_SUBSCRIBER_NAME(

3SELECT CHECK_SUBSCRIBER_NAME(

'Иванов'); 'Иванов И'); 'Иванов И.');

MS SQL Решение 5.1.2.b (код функции)

1CREATE FUNCTION CHECK_SUBSCRIBER_NAME(@subscriber_name NVARCHAR(150))

2RETURNS INT

3WITH SCHEMABINDING

4AS

5BEGIN

6DECLARE @result INT = -1;

7

8IF ((CHARINDEX(' ', LTRIM(RTRIM(@subscriber_name))) = 0) OR

9(CHARINDEX('.', @subscriber_name) = 0))

10BEGIN

11SET @result = 0;

12END

13ELSE

14BEGIN

15SET @result = 1;

16END;

17

18RETURN @result;

19END;

20GO

MS SQL

Решение 5.1.2.b (код для проверки работы функции)

1SELECT dbo.CHECK_SUBSCRIBER_NAME(

2SELECT dbo.CHECK_SUBSCRIBER_NAME(

3SELECT dbo.CHECK_SUBSCRIBER_NAME(

'Иванов'); 'Иванов И'); 'Иванов И.');

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 373/545

Пример 37: контроль операций с данными с использованием хранимых функций

Oracle Решение 5.1.2.b (код функции)

1CREATE OR REPLACE

2FUNCTION CHECK_SUBSCRIBER_NAME (subscriber_name NVARCHAR2)

3RETURN NUMBER DETERMINISTIC IS

4BEGIN

5IF ((NOT REGEXP_LIKE(subscriber_name, '^[a-zA-Zа-яА-ЯёЁ''-]+([^a-zA-Zа-яА-

6ЯёЁ''-]+[a-zA-Zа-яА-ЯёЁ''.-]+){1,}$'))

7OR (INSTRC(subscriber_name, '.', 1, 1) = 0))

8THEN

9RETURN 0;

10ELSE

11RETURN 1;

12END IF;

13END;

Oracle

Решение 5.1.2.b (код для проверки работы функции)

1SELECT CHECK_SUBSCRIBER_NAME(N'Иванов') FROM dual;

2SELECT CHECK_SUBSCRIBER_NAME(N'Иванов И') FROM dual;

3SELECT CHECK_SUBSCRIBER_NAME(N'Иванов И.') FROM dual;

На этом решение данной задачи завершено.

Задание 5.1.2.TSK.A: переписать решения{315}, {338} задач 4.2.1.a{315} и 4.2.2.a{338} с использованием хранимых функций, созданных в решениях{370}, {373} задач 5.1.2.a{370} и 5.1.2.b{370} соответственно.

Задание 5.1.2.TSK.B: создать хранимую функцию, автоматизирующую проверку условий задачи 4.2.1.b{315}, т.е. возвращающую 1, если у читателя на руках сейчас менее десяти книг, и 0 в противном случае.

Задание 5.1.2.TSK.C: создать хранимую функцию, автоматизирующую проверку условий задачи 4.2.2.b{338}, т.е. возвращающую 1, если книга издана менее ста лет назад, и 0 в противном случае.

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 374/545

Источник: https://studfile.net/preview/16418462/