Пример 32: обеспечение консистентности данных |
|
|||||
Oracl |
і Решение 4.1.2.a (триггеры для таблицы subscriptions) |
| |
||||
e |
||||||
|
|
|
|
|
||
1 |
-- Реакция на обновление выдачи книги: |
|
||||
2 |
CREATE OR REPLACE TRIGGER "s has books on sbps upd" |
|||||
3 |
AFTER UPDATE |
|
|
|
||
4 |
ON "subscriptions" |
|
|
|
||
5 |
FOR EACH ROW |
|
|
|
||
6 |
BEGIN |
|
|
|
|
|
7 |
-- A) Читатель тот же, Y -> N |
|
||||
8 |
IF (( old "sb subscriber" = |
new "sb subscriber") AND |
||||
9 |
( old "sb is active" = 'Y') AND |
|
||||
10 |
( new "sb is active" = 'N')) THEN |
|
||||
11 |
UPDATE "subscribers" |
|
|
|||
12 |
SET |
"s books" = "s books" - 1 |
|
|||
13 |
WHERE |
"s id" = |
old "sb subscriber"; |
|||
14 |
END IF; |
|
|
|
|
|
15 |
|
|
|
|
|
|
16 |
-- B) Читатель тот же, N -> Y |
|
||||
17 |
IF (( old "sb subscriber" = |
new "sb subscriber") AND |
||||
18 |
( old "sb is active" = 'N') AND |
|
||||
19 |
( new "sb is active" = 'Y')) THEN |
|
||||
20 |
UPDATE "subscribers" |
|
|
|||
21 |
SET |
"s books" = "s books" + 1 |
|
|||
22 |
WHERE |
"s id" = |
old "sb subscriber"; |
|||
23 |
END IF; |
|
|
|
|
|
24 |
|
|
|
|
|
|
25-- C) Читатели разные, Y -> Y
26IF (( old "sb subscriber" != new "sb subscriber") AND
27( old "sb is active" = 'Y') AND
28( new "sb is active" = 'Y')) THEN
29UPDATE "subscribers"
30 |
SET |
"s books" = "s books" - 1 |
|
31 |
WHERE |
"s id" = |
old "sb subscriber"; |
32 |
UPDATE "subscribers" |
||
33 |
SET |
"s books" = "s books" + 1 |
|
34 |
WHERE |
"s id" = |
new "sb subscriber"; |
35 |
END IF; |
|
|
36 |
|
|
|
37-- D) Читатели разные, Y -> N
38IF (( old "sb subscriber" != new "sb subscriber") AND
39( old "sb is active" = 'Y') AND
40( new "sb is active" = 'N')) THEN
41UPDATE "subscribers"
42 |
SET |
"s books" = "s books" - 1 |
43 |
WHERE |
"s id" = old "sb subscriber"; |
44 |
END IF; |
|
45 |
|
|
46-- E) Читатели разные, N -> Y
47IF (( old "sb subscriber" != new "sb subscriber") AND
48( old "sb is active" = 'N') AND
49( new "sb is active" = 'Y')) THEN
50UPDATE "subscribers"
51 |
SET |
"s books" = "s books" + 1 |
52 |
WHERE |
"s id" = new "sb subscriber"; |
53END IF;
54END;
Витоге код триггеров для Oracle получился полностью идентичным коду триггеров для MySQL, потому и запросы для проверки работоспособности полученного решения также совпадают для обеих СУБД.
См. код самих запросов ниже, а логика их работы с пояснением и демонстрацией изменения содержимого таблицы subscribers представлена в решении для
MySQL.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 320/545
Пример 32: обеспечение консистентности данных
|
Oracl |
і |
Решение 4.1.2.a (проверка работоспособности) |
| |
e |
|
|||
|
|
|
|
|
1 |
|
ALTER TRIGGER "TRG_subscriptions_sb_id" DISABLE; |
||
2 |
|
|
|
|
3-- Добавим Иванову И.И. активную выдачу, а Петрову П.П. неактивную:
4INSERT INTO "subscriptions"
5 |
VALUES |
(200 |
6 |
|
1, |
7 |
|
1, |
8 |
|
TO DATE('2011-01-12', 'YYYY-MM-DD'), |
9 |
|
TO DATE('2011-02-12', 'YYYY-MM-DD'), |
10 |
|
'Y'); |
11 |
INSERT INTO "subscriptions" |
|
12 |
VALUES |
(201 |
13 |
|
2, |
14 |
|
1, |
15 |
|
TO DATE('2011-01-12', 'YYYY-MM-DD'), |
16 |
|
TO DATE('2011-02-12', 'YYYY-MM-DD'), |
17 |
|
'N'); |
18 |
|
|
19-- Удалим добавленные выдачи:
20DELETE FROM "subscriptions"
21 |
WHERE "sb_id" IN ( 200 201 ); |
22 |
|
23-- Проверим реакцию на обновление выдач книг. Сначала добавим выдачу:
24INSERT INTO "subscriptions"
25 |
VALUES |
(300 |
26 |
|
1, |
27 |
|
1, |
28 |
|
TO DATE('2011-01-12', 'YYYY-MM-DD'), |
29 |
|
TO DATE('2011-02-12', 'YYYY-MM-DD'), |
30 |
|
'Y'); |
31 |
|
|
32-- A) Не меняя идентификатор читателя сделаем выдачу неактивной:
33UPDATE "subscriptions"
34 |
SET |
"sb is active" = 'N' |
35 |
WHERE |
"sb_id" = 300 |
36 |
|
|
37-- B) Не меняя идентификатор читателя сделаем выдачу снова активной:
38UPDATE "subscriptions"
39 |
SET |
"sb is active" = 'Y' |
40 |
WHERE |
"sb_id" = 300 |
41 |
|
|
42-- C) Изменим идентификатор читателя, не меняя состояние активности выдачи:
43UPDATE "subscriptions"
44 |
SET |
"sb subscriber" = 2 |
45 |
WHERE |
"sb_id" = 300 |
46 |
|
|
47-- D) Изменим идентификатор читателя и сделаем выдачу неактивной:
48UPDATE "subscriptions"
49 |
SET |
"sb subscriber" = 1 |
50"sb is active" = 'N'
51WHERE "sb_id" = 300
52
53-- E) Изменим идентификатор читателя и сделаем выдачу активной:
54UPDATE "subscriptions"
55 |
SET |
"sb subscriber" = 2, |
56"sb is active" = 'Y'
57WHERE "sb_id" = 300
58
59-- Удалим книгу с id = 1 (выдана по одной штуке Петрову и обоим Сидоровым):
60DELETE FROM [books]
61WHERE [b_id] = 1
62
63 ALTER TRIGGER "TRG subscriptions sb id" ENABLE;
Итак, решение данной задачи получено и проверено для всех трёх СУБД.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 321/545
Пример 32: обеспечение консистентности данных
MySQL I |
Решение 4.1.2.b (триггеры для таблицы m2m books genres) (продолжение) |
| |
29-- Реакция на удаление связи между книгами и жанрами:
30CREATE TRIGGER 'g_has_books_on_m2m_b_g_del'
31AFTER DELETE
32ON 'm2m_books_genres'
33FOR EACH ROW
34BEGIN
35UPDATE 'genres'
36 |
SET |
'g books' = 'g books' - 1 |
37WHERE 'g id' = OLD.'g id';
38END;
39$$
40
41 DELIMITER ;
Поскольку в MySQL триггеры не активируются каскадными операциями, удаление книги (которое приведёт к удалению всех её связей со всеми жанрами) останется незаметным для триггеров на таблице m2m_books_genres. Потому мы должны создать триггер на таблице books, учитывающий соответствующую ситуацию.
Каждая книга связана с каждым жанром не более одного раза, потому при удалении любой книги нужно на единицу уменьшить счётчик книг у каждого из жанров, с которыми она связана.
MySQL Решение 4.1.2.b (триггер для таблицы books)
1 DELIMITER $$
2
3-- Реакция на удаление книги:
4CREATE TRIGGER 'g has books on books del'
5BEFORE DELETE
6ON 'books'
7FOR EACH ROW
8BEGIN
9UPDATE 'genres'
10 |
SET |
'g books' = 'g books' - 1 |
|
11 |
WHERE |
'g id' IN (SELECT 'g id' |
|
12 |
|
FROM |
'm2m books genres' |
13 |
|
WHERE |
'b id' = OLD.'b id'); |
14END;
15$$
16
17 DELIMITER ;
Проверим корректность полученного решения. Будем модифицировать данные в таблицах m2m_books_genres и books и проверять изменения в таблице genres.
Исходное состояние таблицы genres:
g_id |
g_name |
g books |
1 |
Поэзия |
2 |
2 |
Программирование |
3 |
3 |
Психология |
1 |
4 |
Наука |
0 |
5 |
Классика |
4 |
6 |
Фантастика |
1 |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 323/545
Пример 32: обеспечение консистентности данных
Добавим две связи к жанру «Наука» (идентификатор жанра равен 4):
MySQL I Решение 4.1.2.b (проверка работоспособности)
|
1 |
INSERT INTO 'm2m books genres' |
|||
|
2 |
|
('b id', |
|
|
|
3 |
|
'g id') |
|
|
|
4 |
VALUES |
(1, 4), |
|
|
|
5 |
|
(2, 4) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
g_id |
g_name |
g_books |
|
|
|
1 |
Поэзия |
|
2 |
|
|
2 |
Программирование |
3 |
|
|
|
3 |
Психология |
|
1 |
|
|
4 |
Наука |
|
2 |
|
|
5 |
Классика |
|
4 |
|
|
6 |
Фантастика |
|
1 |
|
Изменим в этих связях значения идентификаторов книг, не меняя значения идентификаторов жанров:
|
MySQL I |
Решение 4.1.2.b (проверка работоспособности) | |
|
1 |
UPDATE 'm2m books |
genres' |
|
2 |
SET |
'b id' = 3 |
|
3WHERE 'b id' = 1
4AND 'g id' = 4;
6 |
UPDATE 'm2m books genres' |
|||
7 |
SET |
'b id' = 4 |
|
|
8 |
WHERE |
'b id' = 2 |
|
|
9 |
AND 'g id' = 4; |
|
|
|
|
|
|
|
|
|
|
|
|
|
g_id |
|
g_name |
g_books |
|
1 |
Поэзия |
2 |
|
|
2 |
Программирование |
3 |
|
|
3 |
Психология |
1 |
|
|
4 |
Наука |
|
2 |
|
5 |
Классика |
4 |
|
|
6 |
Фантастика |
1 |
|
|
Изменим в этих связях значения идентификаторов жанров, не меняя значения идентификаторов книг:
MySQL і Решение 4.1.2.b (проверка работоспособности)
|
1 |
UPDATE |
'm2m books genres' |
|||
|
2 |
SET |
'g id' = |
5 |
|
|
|
3 |
WHERE |
'b id' = |
3 |
|
|
|
4 |
AND 'g id' = |
4; |
|
|
|
|
5 |
|
|
|
|
|
|
6 |
UPDATE 'm2m books genres' |
||||
|
7 |
SET |
'g id' = |
5 |
|
|
|
8 |
WHERE |
'b id' = |
4 |
|
|
|
9 |
AND 'g id' = |
4; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
g id |
|
g_name |
|
g books |
|
|
1 |
Поэзия |
|
2 |
|
|
|
2 |
Программирование |
3 |
|
||
|
3 |
Психология |
|
1 |
|
|
|
4 |
Наука |
|
|
0 |
|
|
5 |
Классика |
|
6 |
|
|
|
6 |
Фантастика |
|
1 |
|
|
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 324/545