Бази даних-20210115T104840Z-001 / Реферат на тему _Современные СУБД_ / Using_MySql,_MS_SQL_Server_and_Oracle
.pdfПример 32: обеспечение консистентности данных
MySQL |
Решение 4.1.2.a (модификация таблицы и инициализация данных) |
|
1 |
-- Модификация таблицы: |
|
2 |
ALTER TABLE 'subscribers' |
|
3 |
|
ADD COLUMN 's_books' INT 11 NOT NULL DEFAULT 0 AFTER 's_name' |
5-- Инициализация данных:
6UPDATE 'subscribers'
|
|
JOIN (SELECT |
'sb_subscriber', |
8 |
|
|
COUNT('sb_id') AS 's_has_books' |
9 |
|
FROM |
'subscriptions' |
10 |
|
WHERE |
'sb_is_active' = 'Y' |
11 |
|
GROUP BY 'sb_subscriber') AS 'prepared_data' |
|
12 |
|
ON 's_id' = |
'sb_subscriber' |
13 |
SET |
's books' = 's has books'; |
Как видно из инициализирующего запроса, всю необходимую информацию для формирования значения поля s_books мы можем взять из таблицы subscriptions. На ней мы и будем создавать триггеры.
С INSERT- и DELETE-триггерами всё просто: если добавляется или удаляется «активная» выдача (поле sb_is_active равно Y), нужно увеличить или уменьшить на единицу значение счётчика выданных книг у соответствующего читателя.
MySQL I Решение 4.1.2.a (триггеры для таблицы subscriptions) |
1 DELIMITER $$
2
3-- Реакция на добавление выдачи книги:
4CREATE TRIGGER 's_has_books_on_subscriptions_ins'
5AFTER INSERT
6ON 'subscriptions'
7FOR EACH ROW
8BEGIN
9IF (NEW.'sb is active' = 'Y') THEN
10UPDATE 'subscribers'
11 |
SET |
's books' = 's books' + 1 |
12WHERE 's id' = NEW.'sb subscriber';
13END IF;
14END;
15$$
16
17-- Реакция на удаление выдачи книги:
18CREATE TRIGGER 's_has_books_on_subscriptions_del'
19AFTER DELETE
20ON 'subscriptions'
21FOR EACH ROW
22BEGIN
23IF (OLD.'sb is active' = 'Y') THEN
24UPDATE 'subscribers'
25 |
SET |
's books' = 's books' - 1 |
26WHERE 's id' = OLD.'sb subscriber';
27END IF;
28END;
29$$
30
31 DELIMITER ;
С UPDATE-триггером ситуация будет более сложной, т.к. у нас есть два пара-
метра, которые могут как измениться, так и остаться неизменными — идентификатор читателя и состояние выдачи.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 310/545
Пример 32: обеспечение консистентности данных
|
Старое значение |
Новое значение |
Действие |
Код действия |
|
|
sb_is_active |
sb_is_active |
|
|
|
|
|
|
|
|
|
Идентификатор |
Y |
Y |
- |
|
|
Y |
N |
OLD-1 |
A |
||
читателя остался |
|||||
N |
Y |
OLD+1 |
B |
||
неизменным |
|||||
N |
N |
- |
|
||
|
|
||||
Идентификатор |
Y |
Y |
OLD-1, NEW+1 |
C |
|
Y |
N |
OLD-1 |
D |
||
читателя изме- |
|||||
N |
Y |
NEW+1 |
E |
||
нился |
|||||
N |
N |
- |
|
||
|
|
И, наконец, здесь мы приведём решение проблемы, описанной в заданиях
3.2.1. TSK.D<24°}, 4.1.1.TSK.D<291\ 4.1.1.TSK.E<291J. Напомним, что MySQL не активирует триггеры каскадными операциями, потому удаление книг (которое приведёт к удалению всех записей о выдачах этих книг) активирует «незаметное» для DELETE - триггера на таблице subscriptions удаление данных.
Чтобы учесть этот эффект, мы создадим дополнительный триггер на таблице books, реагирующий на удаление книг (вставка или обновление данных в таблице books не влияет на распределение уже имеющихся выдач книг по тем или иным читателям, потому здесь достаточно создать только DELETE-триггер).
Обратите внимание: здесь мы создаём BEFORE-триггер, т.к. в момент активации AFTER-триггера искомая информация в таблице subscriptions уже будет удалена.
MySQL і Решение 4.1.2.a (триггер для таблицы books)
1 DELIMITER $$
2
3-- Реакция на удаление книги:
4CREATE TRIGGER 's has books on books del'
5BEFORE DELETE
6ON 'books'
7FOR EACH ROW
8BEGIN
9UPDATE 'subscribers'
10 |
JOIN (SELECT |
'sb subscriber', |
11 |
|
COUNT('sb book') AS 'delta' |
12 |
FROM |
'subscriptions' |
13 |
WHERE |
'sb book' = OLD 'b id' |
14 |
AND 'sb is active' = 'Y' |
15GROUP BY 'sb subscriber') AS 'prepared data'
16ON 's id' = 'sb subscriber'
17 |
SET |
's books' = 's books' - 'delta'; |
18 |
END; |
|
19 |
$$ |
|
20 |
|
|
21 |
DELIMITER ; |
Проверим работоспособность полученного решения. Будем изменять данные в таблицах books и subscriptions и отслеживать изменения данных в таблице subscribers.
Исходное состояние таблицы subscribers таково:
s_id |
s_name |
s_books |
1 |
Иванов И.И. |
0 |
2 |
Петров П.П. |
0 |
3 |
Сидоров С.С. |
3 |
4 |
Сидоров С.С. |
2 |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 312/545
Пример 32: обеспечение консистентности данных
Проверим реакцию на добавление и удаление выдач книг. Добавим Иванову И.И. активную выдачу, а Петрову П.П. неактивную:
|
MySQL |
|
і |
Решение 4.1.2.a (проверка работоспособности) |
| |
|||
|
|
INSERT INTO 'subscriptions' |
|
|||||
|
2 |
VALUES |
(200 |
|
|
|
||
|
3 |
|
|
|
1, |
|
|
|
|
4 |
|
|
|
1, |
|
|
|
|
5 |
|
|
|
'2011-01-12', |
|
|
|
|
6 |
|
|
|
'2011-02-12', |
|
|
|
|
7 |
|
|
|
'Y'), |
|
||
|
8 |
|
|
|
(201 |
|
|
|
|
9 |
|
|
|
2, |
|
|
|
|
10 |
|
|
|
1, |
|
|
|
|
11 |
|
|
|
'2011-01-12', |
|
|
|
|
12 |
|
|
|
'2011-02-12', |
|
|
|
|
13 |
|
|
|
'N') |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_id |
|
|
s_name |
s_books |
|
|
|
|
1 |
|
Иванов И.И. |
1 |
|
|
||
|
2 |
|
Петров П.П. |
0 |
|
|
||
|
3 |
|
Сидоров С.С. |
3 |
|
|
||
|
4 |
|
Сидоров С.С. |
2 |
|
|
||
|
|
Удалим добавленные выдачи: |
|
|||||
|
|
|
|
|
|
|||
|
MySQL |
|
і |
Решение 4.1.2.a (проверка работоспособности) |
і |
1DELETE FROM 'subscriptions'
2WHERE 'sb id' IN ( 200 201 )
s_id |
s_name |
s_books |
1 |
Иванов И.И. |
0 |
2 |
Петров П.П. |
0 |
3 |
Сидоров С.С. |
3 |
4 |
Сидоров С.С. |
2 |
Проверим реакцию на обновление выдач книг. Сначала добавим выдачу:
MySQL |
|
і Решение 4.1.2.a (проверка работоспособности) | |
|||
|
INSERT INTO 'subscriptions' |
||||
2 |
VALUES |
(300 |
|
|
|
3 |
|
|
1, |
|
|
4 |
|
|
1, |
|
|
5 |
|
|
'2011-01-12', |
|
|
6 |
|
|
'2011-02-12', |
|
|
7 |
|
|
'Y') |
||
|
|
|
|
|
|
|
|
|
|
|
|
s_id |
|
s_name |
s_books |
|
|
1 |
|
Иванов И.И. |
1 |
|
|
2 |
|
Петров П.П. |
0 |
|
|
3 |
|
Сидоров С.С. |
3 |
|
|
4 |
|
Сидоров С.С. |
2 |
|
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 313/545
Пример 32: обеспечение консистентности данных
Не меняя идентификатор читателя сделаем выдачу неактивной:
MySQL I Решение 4.1.2.a (проверка работоспособности)
1— A
2UPDATE 'subscriptions'
3 |
SET |
'sb is active' = 'N' |
||
4 |
WHERE |
'sb id' = 300 |
||
|
|
|
|
|
|
|
|
|
|
s_id |
s_name |
s_books |
|
|
1 |
Иванов И.И. |
0 |
|
|
2 |
Петров П.П. |
0 |
|
|
3 |
Сидоров С.С. |
3 |
|
|
4 |
Сидоров С.С. |
2 |
|
Не меняя идентификатор читателя сделаем выдачу снова активной:
MySQL Решение 4.1.2.a (проверка работоспособности)
1— B
2UPDATE 'subscriptions'
3 |
SET |
'sb is active' = 'Y' |
||
4 |
WHERE |
'sb id' = 300 |
||
|
|
|
|
|
|
|
|
|
|
s_id |
s_name |
s_books |
|
|
1 |
Иванов И.И. |
1 |
|
|
2 |
Петров П.П. |
0 |
|
|
3 |
Сидоров С.С. |
3 |
|
|
4 |
Сидоров С.С. |
2 |
|
Изменим идентификатор читателя, не меняя состояние активности выдачи:
Решение 4.1.2.a
1— C
2UPDATE 'subscriptions'
3 |
SET |
'sb_subscriber' = 2 |
|
||
4 |
WHERE |
'sb id' = 300 |
|
||
|
|
|
|
|
|
s_id |
|
s_name |
s_books |
|
|
1 |
|
Иванов И.И. |
0 |
|
|
2 |
|
Петров П.П. |
1 |
|
|
3 |
|
Сидоров С.С. |
3 |
|
|
4 |
|
Сидоров С.С. |
2 |
|
Изменим идентификатор читателя и сделаем выдачу неактивной:
MySQL Решение 4.1.2.a (проверка работоспособности)
1— D
2UPDATE 'subscriptions'
3 |
SET |
'sb subscriber' = 1 |
4'sb is active' = N'
5WHERE 'sb id' = 300
s_id |
s_name |
s_books |
1 |
Иванов И.И. |
0 |
2 |
Петров П.П. |
0 |
3 |
Сидоров С.С. |
3 |
4 |
Сидоров С.С. |
2 |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 314/545
Пример 32: обеспечение консистентности данных
Изменим идентификатор читателя и сделаем выдачу активной:
MySQL I |
Решение 4.1.2.a (проверка работоспособности) | |
1-- E
2UPDATE 'subscriptions'
3 |
SET |
'sb_subscriber' = 2, |
4'sb_is_active' = 'Y'
5WHERE 'sb id' = 300
s_id |
s_name |
s_books |
1 |
Иванов И.И. |
0 |
2 |
Петров П.П. |
1 |
3 |
Сидоров С.С. |
3 |
4 |
Сидоров С.С. |
2 |
Удалим книгу с идентификатором 1 (такая книга сейчас выдана Петрову и обоим Сидоровым по одному экземпляру):
MySQL і Решение 4.1.2.a (проверка работоспособности) |
1DELETE FROM 'books'
2WHERE 'b id' = 1
s_id |
s_name s_books |
1Иванов И.И. 0
2Петров П.П. 0
3Сидоров С.С. 2
4Сидоров С.С. 1
Как показало исследование, все операции выполняются корректно и приводят к верным изменениям значений поля s_books.
Переходим к решению поставленной задачи для MS SQL Server. Модифицируем таблицу subscribers и проинициализируем добавленное поле данными.
MS SQL Решение 4.1.2.a (модификация таблицы и инициализация данных)
1-- Модификация таблицы:
2ALTER TABLE [subscribers]
34 ADD [s_books] INT NOT NULL DEFAULT 0;
|
-- Инициализация данных: |
||
6 |
UPDAT |
[subscribers] |
|
7 |
SET |
[s books] = [s has books] |
|
8 |
FROM |
[subscribers] |
|
9 |
|
JOIN (SELECT [sb_subscriber], |
|
10 |
|
|
COUNT([sb_id]) AS [s_has_books] |
11 |
|
FROM |
[subscriptions] |
12 |
|
WHERE |
[sb_is_active] = 'Y' |
13 |
|
GROUP |
BY [sb_subscriber]) AS [prepared_data] |
14 |
|
ON [s id] = [sb subscriber]; |
Логика работы триггеров в MS SQL Server будет иной, т.к. эта СУБД не поддерживает триггеры уровня записи, и нам придётся за один раз обрабатывать все произведённые изменения.
С INSERT- и DELETE-триггерами, как и в случае с MySQL, будет более-менее
просто — нужно выяснить идентификаторы читателей, получивших (или вернувших) книги, количество таких книг по каждому читателю, а затем увеличить или уменьшить счётчики выданных книг соответствующим читателям на соответствующие величины.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 315/545
Пример 32: обеспечение консистентности данных
MS SQL Решение 4.1.2.a |
для |
1-- Реакция на добавление выдачи книги:
2CREATE TRIGGER [s has books on subscriptions ins]
3ON [subscriptions]
4AFTER INSERT
5AS
6UPDATE [subscribers]
7 |
SET |
[s books] = [s books] + [s new books] |
8 |
FROM |
[subscribers] |
9 |
|
JOIN (SELECT [sb subscriber], |
10 |
|
COUNT |
[sb id]) AS [s new books] |
11 |
FROM |
[inserted] |
|
12 |
|
WHERE |
[sb is active] = 'Y' |
13 |
GROUP |
BY [sb subscriber] AS [prepared data] |
14ON [s id] = [sb subscriber]
15GO
16
17-- Реакция на удаление выдачи книги:
18CREATE TRIGGER [s has books on subscriptions del]
19ON [subscriptions]
20AFTER DELETE
21AS
22UPDATE [subscribers]
23 |
SET |
[s books] = [s books] - [s old books] |
|
24 |
FROM |
[subscribers] |
|
25 |
|
JOIN (SELECT [sb subscriber], |
|
26 |
|
|
COUNT [sb id]) AS [s old books] |
27 |
|
FROM |
[deleted] |
28 |
|
|
WHERE [sb is active] = 'Y' |
29 |
|
GROUP |
BY [sb subscriber] AS [prepared data] |
30 |
|
ON [s id] = [sb subscriber] |
|
31 |
|
|
|
32 |
GO |
|
|
UPDATE-триггер получится чуть более сложным, но не настолько, как в
MySQL: здесь мы можем посчитать количество сданных и возвращённых книг на основе информации из псевдотаблиц deleted и inserted, и при этом нам не важно изменение состояния выдач книг — мы лишь считаем (независимо) количество сданных и полученных книг для каждого читателя и изменяем его счётчик книг на эти две величины.
Иными словами, нам не важно, из какого в какое состояние (и от какого к какому читателю) переключается выдача — нас интересует только «у кого удалились активные выдачи», и «кому добавились активные выдачи».
Потому UPDATE-триггер будет просто содержать в себе код из INSERT- триггера и DELETE-триггера. Чуть более элегантным решением была бы реализация
в теле триггера такой логики, при которой было бы достаточно выполнить только одну операцию обновления таблицы subscribers — в этом и будет состоять задание 4.1.2.TSK.C{314}.
Для проверки работоспособности полученного решения можно использовать запросы, представленные после кода UPDATE-триггера (их общая логика и ожидае-
мая реакция СУБД пояснены в решении для MySQL, но обратите внимание, что здесь мы оперируем чуть большим количеством данных в каждом запросе).
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 316/545
Пример 32: обеспечение консистентности данных
MS SQL I Решение 4.1.2.a (триггеры для таблицы subscriptions) |
1-- Реакция на обновление выдачи книги:
2CREATE TRIGGER [s has books on subscriptions upd]
3ON [subscriptions]
4AFTER UPDATE
5AS
6-- , фактически, -- код DELETE-триггера):
7UPDATE [subscribers]
8 |
SET |
[s books] = [s books] - [s old books] |
9FROM [subscribers]
10JOIN (SELECT [sb subscriber],
11 |
|
COUNT([sb id] AS [s old books] |
12 |
FROM |
[deleted] |
13 |
|
WHERE [sb is active] = 'Y' |
14 |
GROUP |
BY [sb subscriber]) AS [prepared data] |
15ON [s id] = [sb subscriber];
16-- , фактически, -- код INSERT-триггера):
17UPDATE [subscribers]
18 |
SET |
[s books] = [s books] + [s new books] |
19FROM [subscribers]
20JOIN (SELECT [sb subscriber],
21 |
|
COUNT([sb id] AS [s new books] |
22 |
FROM |
[inserted] |
23 |
|
WHERE [sb is active] = 'Y' |
24 |
GROUP |
BY [sb subscriber]) AS [prepared data] |
25ON [s id] = [sb subscriber];
26GO
MS SQL I Решение 4.1.2.a (проверка работоспособности) |
1 SET IDENTITY INSERT [subscriptions] ON;
2
3-- Добавим Иванову И.И. две активных выдачи,
4-- а Петрову П.П. одну активную и одну неактивную:
5INSERT INTO [subscriptions]
6 |
|
([sb id], |
7 |
|
[sb subscriber], |
8 |
|
[sb book] |
9 |
|
[sb start], |
10 |
|
[sb finish], |
11 |
|
[sb is active]) |
12 |
VALUES |
200, |
13 |
|
1 |
14 |
|
3 |
15 |
|
'2011-01-12', |
16 |
|
'2011-02-12', |
17 |
|
'Y'), |
18 |
|
201, |
19 |
|
1 |
20 |
|
4 |
21 |
|
'2011-01-12', |
22 |
|
'2011-02-12', |
23 |
|
'Y'), |
24 |
|
202, |
25 |
|
2 |
26 |
|
3 |
27 |
|
'2011-01-12', |
28 |
|
'2011-02-12', |
29 |
|
'Y'), |
30 |
|
203, |
31 |
|
2 |
32 |
|
4 |
33 |
|
'2011-01-12', |
34 |
|
'2011-02-12', |
35 |
|
'N'); |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 317/545
Пример 32: обеспечение консистентности данных
MS |
SQL |
Решение 4.1.2.a (проверка работоспособности) (продолжение) |
|
|
||||
36 |
-- Удалим добавленные выдачи: |
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
37 |
|
DELETE FROM [subscriptions] |
|
|
|
|||
|
|
|
|
|
|
|
|
|
38 |
|
WHERE [sb_id] |
IN (200, 201 |
202, 203); |
|
|
||
|
|
|
|
|
|
|
|
|
39 |
|
-- |
|
|
Проверим реакцию на обновление |
выдач |
||
40 |
|
|
|
|||||
книг. |
|
|
|
|
|
|
||
41 |
|
|
|
|
|
|
||
42 |
|
-- |
|
Сначала добавим две выдачи: |
|
|
||
|
INSERT INTO [subscriptions] |
|
|
|
||||
43 |
|
|
|
|
||||
|
|
([sb_id], |
|
|
|
|
|
|
44 |
|
|
|
|
|
|
|
|
|
|
[sb_subscriber], |
|
|
|
|
||
45 |
|
|
|
|
|
|
||
|
|
[sb_book], |
|
|
|
|
|
|
46 |
|
|
|
|
|
|
|
|
|
|
[sb_start] |
|
|
|
|
|
|
47 |
|
|
|
|
|
|
|
|
|
|
[sb_finish], |
|
|
|
|
||
48 |
|
|
|
|
|
|
||
|
|
[sb_is_active]) |
|
|
|
|
||
49 |
|
|
|
|
|
|
||
|
VALUES (300, |
|
|
|
|
|
||
50 |
|
|
|
|
|
|
||
|
|
1, |
|
|
|
|
|
|
51 |
|
|
|
|
|
|
|
|
|
|
3, |
|
|
|
|
|
|
52 |
|
|
|
|
|
|
|
|
|
|
'2011-01-12', |
|
|
|
|
||
53 |
|
|
|
|
|
|
||
|
|
'2011-02-12', |
|
|
|
|
||
54 |
|
|
|
|
|
|
||
|
|
'Y'), |
|
|
|
|
|
|
55 |
|
|
|
|
|
|
|
|
|
|
(301, |
|
|
|
|
|
|
56 |
|
|
|
|
|
|
|
|
|
|
1, |
|
|
|
|
|
|
57 |
|
|
|
|
|
|
|
|
|
|
4, |
|
|
|
|
|
|
58 |
|
|
|
|
|
|
|
|
|
|
'2011-01-12', |
|
|
|
|
||
59 |
|
|
|
|
|
|
||
|
|
'2011-02-12', 'Y'); |
|
|
|
|||
60 |
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
61 |
|
-- Не |
меняя |
идентификатор |
читателя |
сделаем |
выдачи |
|
62 |
|
|||||||
|
неактивными: |
|
|
|
|
|
||
63 |
|
|
|
|
|
|
||
|
UPDATE |
[subscriptions] |
|
|
|
|
||
64 |
|
|
|
|
|
|||
|
SET |
[sb_is_active] = |
'N' |
|
|
|
||
65 |
|
|
|
|
||||
66 |
|
WHERE |
[sb_id] IN (300, |
301); |
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
|
— Не |
меняя |
идентификатор |
читателя |
сделаем |
выдачи |
|
68 |
|
|||||||
|
снова активными: |
|
|
|
|
|
||
69 |
|
|
|
|
|
|
||
|
UPDATE |
[subscriptions] |
|
|
|
|
||
70 |
|
|
|
|
|
|||
|
SET |
[sb_is_active] = |
'Y' |
|
|
|
||
71 |
|
|
|
|
||||
|
WHERE |
[sb_id] IN (300, |
301); |
|
|
|
||
72 |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
73 |
|
— |
Изменим |
идентификатор |
читателя, не меняя |
состояние |
||
74 |
|
|||||||
активности |
выдач: |
|
|
|
|
|
||
75 |
|
|
|
|
|
|||
76 |
|
UPDATE |
[subscriptions] |
|
|
|
|
|
|
SET |
[sb_subscriber] = 2 |
|
|
|
|||
77 |
|
|
|
|
||||
|
WHERE |
[sb_id] IN (300, |
301); |
|
|
|
||
78 |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
79 |
|
— |
Изменим |
идентификатор |
читателя |
и сделаем |
выдачи |
|
80 |
|
|||||||
неактивными: |
|
|
|
|
|
|
||
81 |
|
UPDATE |
[subscriptions] |
|
|
|
|
|
82 |
|
|
|
|
|
|||
|
SET |
[sb_subscriber] |
= 1, |
|
|
|
||
83 |
|
|
|
|
||||
|
[sb_is_active] = 'N' |
|
|
|
|
|||
84 |
|
|
|
|
|
|||
|
WHERE |
[sb_id] IN (300, |
301); |
|
|
|
||
85 |
|
|
|
|
||||
|
|
|
|
|
|
|
|
86— Изменим идентификатор читателя и сделаем выдачи активными:
87UPDATE [subscriptions]
88SET [sb_subscriber] = 2,
89 |
[sb_is_active] = 'Y' |
|
|
90 |
|
||
WHERE [sb_id] IN (300, |
301); |
||
91 |
|||
|
|
92— Удаление книги с идентификатором 1 (выдана по одному экземпляру
93-- Петрову и обоим Сидоровым):
94DELETE FROM [books]
WHERE [b_id] = 1
SET IDENTITY INSERT [subscriptions] OFF;
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 318/545
Пример 32: обеспечение консистентности данных
Переходим к решению поставленной задачи для Oracle. Модифицируем таблицу subscribers и проинициализируем добавленное поле данными.
MS SQL Решение 4.1.2.a (модификация таблицы и инициализация данных)
1-- Модификация таблицы:
2ALTER TABLE "subscribers"
3 |
ADD "s_books" INT DEFAULT 0 NOT NULL); |
4 |
|
5-- Инициализация данных:
6UPDATE "subscribers"
SET |
"s_books" = NVL( |
|
8 |
(SELECT |
COUNT "sb_id") AS "s_has_books" |
9 |
FROM |
"subscriptions" |
10 |
WHERE |
"sb_is_active" = 'Y' |
11 |
AND |
"sb_subscriber" = "s_id" |
12 |
GROUP BY |
"sb subscriber" , 0); |
Обратите внимание: из-за синтаксических особенностей Oracle, вынуждающих нас писать такой запрос на обновление, приходится применять функцию NVL, потому что коррелирующий подзапрос в строках 7-16 выполнится для каждого ряда таблицы subscribers, и в некоторых случаях вернёт NULL.
Несмотря на то, что Oracle (как и MS SQL Server) поддерживает триггеры уровня выражения, мы не можем использовать представленную в решении для MS SQL логику, т.к. в Oracle нет псевдотаблиц inserted и updated. Нам придётся идти по пути решения для MySQL и использовать триггеры уровня записи.
Oracle |
Решение 4.1.2.a |
для |
1-- Реакция на добавление выдачи книги:
2CREATE OR REPLACE TRIGGER "s_has_books_on_sbps_ins"
3AFTER INSERT
4ON "subscriptions"
5FOR EACH ROW
6BEGIN
7IF (:new "sb is active" = 'Y') THEN
8UPDATE "subscribers"
9 |
SET |
"s books" |
= "s books" + 1 |
10 |
WHERE |
"s id" = |
new "sb subscriber"; |
11END IF;
12END;
13
14-- Реакция на удаление выдачи книги:
15CREATE OR REPLACE TRIGGER "s_has_books_on_sbps_del"
16AFTER DELETE
17ON "subscriptions"
18FOR EACH ROW
19BEGIN
20IF (:old "sb is active" = 'Y') THEN
21UPDATE "subscribers"
22 |
SET |
"s books" = "s books" - 1 |
23 |
WHERE |
"s id" = old "sb subscriber"; |
24END IF;
25END;
В UPDATE-триггере мы также используем один в один тот же самый код, ко-
торый был использован в решении для MySQL (там же были рассмотрены и показаны графически все ситуации, которые должен учитывать данный триггер).
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 319/545