Материал: Using_MySql,_MS_SQL_Server_and_Oracle

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

Пример 32: обеспечение консистентности данных

 

Oracl

і

Решение 4.1.2.b (проверка работоспособности)

|

e

 

 

 

 

9

-- Изменение в добавленных связях значения идентификаторов книг,

10

-- без изменения значения идентификаторов жанров:

11

UPDATE "m2m books genres"

 

12

SET

 

"b id" = 3

 

13

WHERE

"b id" = 1

 

14

 

AND "g_id" = 4;

 

15

 

 

 

 

16

UPDATE "m2m books genres"

 

17

SET

 

"b id" = 4

 

18WHERE "b id" = 2

19AND "g_id" = 4;

21-- Изменение в добавленных связях значения идентификаторов жанров,

22-- без изменения значения идентификаторов книг:

23UPDATE "m2m books genres"

24

SET

"g id" = 5

25WHERE "b id" = 3

26AND "g_id" = 4;

28

UPDATE "m2m books

genres"

29

SET

"g id" = 5

 

30WHERE "b id" = 4

31AND "g_id" = 4;

33-- Изменение в добавленных связях значения идентификаторов жанров,

34-- и идентификаторов книг одновременно:

35UPDATE "m2m books genres"

36

SET

"b id" = 1,

37"g id" = 4

38WHERE "b id" = 3

39AND "g_id" = 5;

41

UPDATE "m2m books genres"

42

SET

"b id" = 2,

43"g id" = 4

44WHERE "b id" = 4

45AND "g_id" = 5;

47-- Удаление ранее созданных связей:

48DELETE FROM "m2m books genres"

49WHERE "b id" = 1

50AND "g_id" = 4;

51

52DELETE FROM "m2m books genres"

53WHERE "b id" = 2

54AND "g_id" = 4;

55

56-- Удаление книг с идентификаторами 1 и 2 (обе эти книги одновременно

57-- относятся к жанрам «Поэзия» и «Классика»):

58DELETE FROM "books"

59WHERE "b _id" IN (1,2);

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

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

Пример 32: обеспечение консистентности данных

{292}

{305}

&4.1.2. a{292} и 4.1.2.b{292} таким образом, чтобы ни при каких манипуляциях с данными значения полей s_books (в таблице subscribers) и g_books (в таблице genres) не могли оказаться отрицательными.

&Задание 4.1.2.TSK.B: модифицировать схему базы данных «Библиотека» таким образом, чтобы таблица subscribers хранила информацию о том,задачЗадание 4.1.2.TSK.A: доработать триггеры из решений ,

сколько раз читатель брал в библиотеке книги (этот счётчик должен инкрементироваться каждый раз, когда читателю выдаётся книга; уменьшение значения этого счётчика не предусмотрено).

& Задание 4.1.2.TSK.C: оптимизировать код UPDATE-триггера из решения{292} задачи 4.1.2.a{292} для MS SQL Server так, чтобы выполнялась одна операция обновления таблицы subscribers (а не две отдельных операции, как это

реализовано сейчас).

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

Пример 33: контроль операций модификации данных

4.2.Контроль операций с данными с использованием триггеров

4.2.1. Пример 33: контроль операций модификации данных

'. Задача 4.2.1.a{315}: создать триггер, не позволяющий добавить в базу данных информацию о выдаче книги, если выполняется хотя бы одно из условий:

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

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

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

;Задача 4.2.1.b{328}: создать триггер, не позволяющий выдать книгу читателю,

укоторого на руках находится десять и более книг.

'; Задача 4.2.1.c335: создать триггер, не позволяющий изменять значение поля sb_is_active таблицы subscriptions со значения N на значение Y.

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

При попытке внести в базу данных изменения, противоречащие условию задачи, операция (транзакция) должна быть отменена. Также должно быть выведено сообщение об ошибке, наглядно поясняющее суть проблемы, например:

“Date 2038.01.12 for subscription 145

activation isin the future”.

“Date 1983.01.12 for subscription 155

deactivationis in the past”.

“Date 2000.01.12 for subscription 165

deactivationis less than date for its activa

 

tion (2015.01.12)”.

 

 

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

 

При попытке внести в базу данных изменения, противоречащие условию задачи, операция (транзакция) должна быть отменена. Также должно быть выведено сообщение об ошибке, наглядно поясняющее суть проблемы, например: “Subscriber

Иванов И.И. (id = 1) already has 23 books out of 10 allowed.”

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

При попытке внести в базу данных изменения, противоречащие условию задачи, операция (транзакция) должна быть отменена. Также должно быть выведено сообщение об ошибке, наглядно поясняющее суть проблемы, например: “It is prohibited to activate previously deactivated subscriptions (rule violated for subscriptions 34,

89, 12).”

xA?

Решение 4.2.1 .a{315}.

Для решения данной задачи нам понадобятся только INSERT- и UPDATE -

триггеры, т.к. в процессе удаления данных невозможно нарушить ни одно из контролируемых условий.

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

Пример 33: контроль операций модификации данных

Код iNSERT-триггера для MySQL выглядит следующим образом.

 

MySQL і Решение 4.2.1.a (триггеры для таблицы subscriptions)

[

I

DELIMITER. $$ ..............................

‘ ..............................

2

 

 

CREATE TRIGGER 'subscriptions_control_ins'

4AFTER INSERT

5ON 'subscriptions'

6FOR EACH ROW

7BEGIN 8

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

10IF NEW.'sb_start' > CURDATE()

II

THEN

12

SET @msg = CONCAT('Date ', NEW.'sb_start', ' for subscription ',

13

NEW.'sb_id', ' activation is in the future.');

14SIGNAL SQLSTATE '45001' SET MESSAGE_TEXT = @msg MYSQL_ERRNO = 1001

15END IF; 16

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

18IF NEW.'sb_finish' < CURDATE()

19THEN

20SET @msg = CONCAT('Date ', NEW.'sb_finish', ' for subscription ',

21

NEW.'sb_id', ' deactivation is in the past.');

22SIGNAL SQLSTATE '45002' SET MESSAGE_TEXT = @msg MYSQL_ERRNO = 1002

23END IF;

24

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

26IF NEW.'sb_finish' < NEW.'sb_start'

27THEN

28SET @msg = CONCAT('Date ', NEW.'sb_finish', ' for subscription ',

29

NEW.'sb_id',

30

' deactivation is less than the date for its activation (',

31

NEW.'sb_start', ').');

32SIGNAL SQLSTATE '45003' SET MESSAGE_TEXT = @msg MYSQL_ERRNO = 1003

33END IF; 34

35END;

36$$ 37

38DELIMITER ;

Сточки зрения функциональности в данном случае можно было бы использовать и BEFORE-триггер, но в случае с AFTER-триггером сообщение об ошибке по-

лучается более информативным, т.к. уже содержит в себе корректное значение автоинкрементируемого первичного ключа (в BEFORE-триггере это значение не опре-

делено, и потому в сообщении об ошибке превращается в 0).

Код в строках 25-33 в настоящий момент не нужен — две предшествующих проверки не допустят возникновения проверяемой этим кодом ситуации. Но если в будущем эти проверки будут модифицированы или убраны, код в строках 25-33 будет срабатывать.

Поскольку в MySQL триггер не может явно отменить транзакцию, мы порождаем исключительную ситуацию (строки 14, 22, 23), при возникновении которой отменяется транзакция, активировавшая срабатывание триггера.

Код UPDATE-триггера будет даже чуть более простым, т.к. в нём по условию

задачи нет необходимости проверять, находится ли дата возврата в прошлом. При этом код в строках 17-25 (ранее отмеченный как бесполезный для IN-

SERT-триггера) здесь будет срабатывать, т.к. по условию задачи при выполнении операции обновления допускается установка в поле sb_finish даты из прошлого, что позволяет нарушить третье условие задачи.

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

Пример 33: контроль операций модификации данных

MySQL I

Решение 4.2.1.a (триггеры для таблицы subscriptions) |

1 DELIMITER $$

2

3CREATE TRIGGER 'subscriptions_control_upd'

4AFTER UPDATE

5ON 'subscriptions'

6FOR EACH ROW

7BEGIN

8

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

10IF NEW.'sb start' > CURDATE()

11THEN

12SET @msg = CONCAT('Date ', NEW.'sb start', ' for subscription ',

13

NEW.'sb id', ' activation is in the future.');

14SIGNAL SQLSTATE '45001' SET MESSAGE TEXT = @msg, MYSQL ERRNO = 1001;

15END IF;

16

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

18IF NEW.'sb finish' < NEW.'sb start'

19THEN

20SET @msg = CONCAT('Date ', NEW.'sb finish', ' for subscription ',

21

NEW. 'sb id',

22

' deactivation is less than the date for its activation (',

23

NEW.'sb start', ').');

24SIGNAL SQLSTATE '45003' SET MESSAGE TEXT = @msg, MYSQL ERRNO = 1003;

25END IF;

26

27END;

28$$

29

30 DELIMITER ;

Проверим работоспособность полученного решения. Будем выполнять следующие запросы и следить за реакцией СУБД.

Попытаемся добавить выдачу книги с датой активации в будущем:

 

MySQL

Решение 4.2.1 .а (проверка

 

 

 

1

 

работоспособности)

INSERT INTO

 

2

VALUES

(500,

3

 

 

1,

4

 

 

1,

5

 

 

'2020-01-12',

6

 

 

'2020-02-12',

7

 

 

'N')

 

 

 

 

СУБД запретит эту операцию, вернув следующее сообщение об ошибке:

Error Code: 1001. Date 2020-01-12 for subscription 500 activation is in the future.

Попытаемся добавить выдачу книги с датой активации в будущем, при этом не указав значение первичного ключа:

MySQL I

’ешение 4.2.1 .a (проверка работоспособности)

і

1

INSERT

INTO 'subscriptions'

 

2

 

('sb id',

 

3

 

'sb subscriber',

 

4

 

'sb book'

 

5

 

'sb start',

 

6

 

'sb finish',

 

7

 

'sb is active')

 

8

VALUES

(NULL,

 

9

 

3,

 

10

 

3,

 

11

 

'2020-01-12',

 

12

 

'2020-02-12',

 

13

 

'N');

 

 

 

 

 

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

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