Бази даних-20210115T104840Z-001 / Реферат на тему _Современные СУБД_ / Using_MySql,_MS_SQL_Server_and_Oracle
.pdfПример 31: обновление кэширующих таблиц и полей
.i.a
11-- Создание триггера, реагирующего на добавление выдачи книг:
12CREATE TRIGGER 'last_visit_on_subscriptions_ins'
13AFTER INSERT
14ON 'subscriptions'
15FOR EACH ROW
16BEGIN
17IF (SELECT IFNULL('s_last_visit', '1970-01-01')
18 FROM 'subscribers'
19WHERE 's_id' = NEW.'sb_subscriber') < NEW.'sb_start'
20THEN
21UPDATE 'subscribers'
22 |
SET |
's_last_visit' = NEW.'sb_start' |
23WHERE 's_id' = NEW.'sb_subscriber';
24END IF;
25END;
26$$
27
28-- Создание триггера, реагирующего на обновление выдачи книг:
29CREATE TRIGGER 'last_visit_on_subscriptions_upd'
30AFTER UPDATE
31ON 'subscriptions'
32FOR EACH ROW
33BEGIN
34UPDATE 'subscribers'
35LEFT JOIN (SELECT 'sb_subscriber',
36 |
|
MAX('sb_start') AS 'last_visit' |
37 |
|
FROM 'subscriptions' |
38 |
|
GROUP BY 'sb_subscriber') AS 'prepared_data' |
39 |
|
ON 's_id' = 'sb_subscriber' |
40 |
SET |
's_last_visit' = 'last_visit' |
41WHERE 's_id' IN (OLD.'sb_subscriber', NEW.'sb_subscriber');
42END;
43$$
44
45-- Создание триггера, реагирующего на удаление выдачи книг:
46CREATE TRIGGER 'last_visit_on_subscriptions_del'
47AFTER DELETE
48ON 'subscriptions'
49FOR EACH ROW
50BEGIN
51UPDATE 'subscribers'
52LEFT JOIN (SELECT 'sb_subscriber',
53 |
|
MAX('sb_start') AS 'last_visit' |
54 |
|
FROM 'subscriptions' |
55 |
|
GROUP BY 'sb_subscriber') AS 'prepared_data' |
56 |
|
ON 's_id' = 'sb_subscriber' |
57 |
SET |
's_last_visit' = 'last_visit' |
58WHERE 's_id' = OLD.'sb_subscriber';
59END;
60$$
61
62-- Восстановление разделителя завершения запросов:
63DELIMITER ;
Проверим работоспособность полученного решения. Будем изменять данные в таблице subscriptions и отслеживать изменения данных в таблице subscribers.
Для начала добавим выдачу книги читателю с идентификатором 2 (ранее он никогда не был в библиотеке):
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 290/545
Пример 31: обновление кэширующих таблиц и полей
|
MySQL I Решение |
.1.a (проверка работоспособности) | |
|||
|
4.1 |
|
|||
|
1 |
INSERT INTO |
'subscriptions' |
||
|
2 |
VALUES |
200, |
|
|
|
3 |
|
2 |
|
|
|
4 |
|
1 |
|
|
|
5 |
|
'2019-01-12', |
|
|
|
6 |
|
'2019-02-12', |
|
|
|
7 |
|
'N' ) |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
s_id |
s_name |
|
s_last_visit |
|
|
1 |
Иванов И.И. |
|
2015-10-07 |
|
|
2 |
Петров П.П. |
|
2019-01-12 |
|
|
3 |
Сидоров С.С. |
2014-08-03 |
|
|
|
4 |
Сидоров С.С. |
2015-10-08 |
|
Теперь эмулируем ситуацию «книга ошибочно записана на другого читателя» и изменим идентификатор читателя в только что добавленной выдаче с 2 на 1. NULL-значение даты последнего визита Петрова П.П. корректно восстановилось:
MySQL I Решение 4.1.1.a (проверка работоспособности)
1 |
UPDATE |
'subscriptions' |
||
2 |
SET |
'sb_subscriber' = 1 |
||
3 |
WHERE |
'sb id' = 200 |
||
|
|
|
|
|
s_id |
|
|
s_name |
s_last_visit |
1 |
|
Иванов И.И. |
2019-01-12 |
|
2 |
|
Петров П.П. |
NULL |
|
3 |
|
Сидоров С.С. |
2014-08-03 |
|
4 |
|
Сидоров С.С. |
2015-10-08 |
Снова добавим выдачу книги Петрову П.П.:
|
MySQL І Решение |
.1.a (проверка работоспособности) | |
|||
|
4.1 |
|
|||
|
1 |
INSERT INTO |
'subscriptions' |
||
|
2 |
VALUES |
201, |
|
|
|
3 |
|
2 |
|
|
|
4 |
|
1 |
|
|
|
5 |
|
'2020-01-12', |
|
|
|
6 |
|
'2020-02-12', |
|
|
|
7 |
|
'N' ) |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
s_id |
s_name |
|
s_last_visit |
|
|
1 |
Иванов И.И. |
|
2019-01-12 |
|
|
2 |
Петров П.П. |
|
2020-01-12 |
|
|
3 |
Сидоров С.С. |
2014-08-03 |
|
|
|
4 |
Сидоров С.С. |
2015-10-08 |
|
Изменим значение даты ранее откорректированной выдачи книги (которую мы переписали с Петрова П.П. на Иванова И.И.):
|
|
Решение 4.1.1.a |
|
|
|
1 |
UPDATE |
'subscriptions' |
|||
2 |
SET |
'sb start' = '2018-01-12' |
|||
3 |
WHERE 'sb id' = 200 |
||||
|
|
|
|
|
|
s_id |
|
s_name |
s_last_visit |
|
|
1 |
|
Иванов И.И. |
2018-01-12 |
|
|
2 |
|
Петров П.П. |
2020-01-12 |
|
|
3 |
|
Сидоров С.С. |
2014-08-03 |
|
|
4 |
|
Сидоров С.С. |
2015-10-08 |
|
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 291/545
Пример 31: обновление кэширующих таблиц и полей
Удалим эту выдачу:
MySQL |
Решение 4.1.1.a (проверка работоспособности) |
||||
|
1 |
DELETE FROM 'subscriptions' |
|||
2 |
WHERE 'sb id' = 200 |
||||
|
|
|
|
|
|
s_id |
|
|
s_name |
s_last_visit |
|
1 |
|
Иванов И.И. |
2015-10-07 |
|
|
2 |
|
Петров П.П. |
2020-01-12 |
|
|
3 |
|
Сидоров С.С. |
2014-08-03 |
|
|
4 |
|
Сидоров С.С. |
2015-10-08 |
|
Удалим единственную выдачу книги Петрову П.П.:
Решение 4.1.1.a
1DELETE FROM 'subscriptions'
2WHERE 'sb id' = 201
s_id |
s_name |
s_last_visit |
1 |
Иванов И.И. |
2015-10-07 |
2 |
Петров П.П. |
NULL |
3 |
Сидоров С.С. |
2014-08-03 |
4 |
Сидоров С.С. |
2015-10-08 |
Итак, решение для MySQL полностью готово и корректно работает. Но прежде, чем перейти к решению для MS SQL Server проведём небольшое исследование, наглядно демонстрирующее ответ на вопрос о том, «отменяется ли действие BEFORE-триггера в случае ошибки в процессе выполнения операции».
Исследование 4.4.1.EXP.A. Будут ли аннулированы изменения данных, вызванные работой BEFORE-триггера, если операция, активировавшая этот триггер, не сможет завершиться успешно?
Изменим вид iNSERT-триггера с AFTER на BEFORE:
Исследование 4.1.1.a |
типа |
1 DROP TRIGGER 'last_visit_on_subscriptions_ins';
2
3 DELIMITER $$
4
5CREATE TRIGGER 'last visit on subscriptions ins'
6BEFORE INSERT
7ON 'subscriptions'
8FOR EACH ROW
9BEGIN
10IF (SELECT IFNULL('s last visit', '1970-01-01')
11 FROM 'subscribers'
12WHERE 's id' = NEW.'sb subscriber') < NEW.'sb start'
13THEN
14UPDATE 'subscribers'
15 |
SET |
's last visit' = NEW.'sb start' |
16WHERE 's id' = NEW.'sb subscriber';
17END IF;
18END;
19$$
20
21 DELIMITER ;
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 292/545
Пример 31: обновление кэширующих таблиц и полей
Выполним последовательно добавление двух выдач книг с разными датами, но одинаковыми значениями первичных ключей:
MySQL | |
Исследование 4.1.1.a (вставка данных) |
| |
|
1 |
INSERT |
INTO 'subscriptions' |
|
2 |
VALUES |
500, |
|
3 |
|
2 , |
|
4 |
|
1 . |
|
5 |
|
'2020-01-12', |
|
6 |
|
'2020-02-12', |
|
7 |
|
'N'); |
|
8 |
|
|
|
9 |
INSERT |
INTO 'subscriptions' |
|
10 |
VALUES |
500, |
|
11 |
|
2 , |
|
12 |
|
1 . |
|
13 |
|
'2021-01-12', |
|
14 |
|
'2021-02-12', |
|
15 |
|
'N'); |
|
|
|
|
|
Проверим данные в таблице subscribers:
s_id |
s_name |
s_last_visit |
1 |
Иванов И.И. |
2015-10-07 |
2 |
Петров П.П. |
2020-01-12 |
3 |
Сидоров С.С. |
2014-08-03 |
4 |
Сидоров С.С. |
2015-10-08 |
Итак, изменения аннулируются, если операция не может быть завершена успешно. В противном случае значением даты последнего визита Петрова П.П.
было бы 2021-01-12.
Переходим к решению поставленной задачи для MS SQL Server. Модифицируем таблицу subscribers и проинициализируем добавленное поле данными.
MS SQL І |
Решение 4.1.1.a (модификация таблицы и инициализация данных) |
| |
1-- Модификация таблицы:
2ALTER TABLE [subscribers]
3ADD [s_last_visit] DATE NULL DEFAULT NULL;
5-- Инициализация данных:
6 |
UPDATE |
[subscribers] |
7 |
SET |
[s_last_visit] = [last_visit] |
8 |
FROM |
[subscribers] |
9 |
LEFT JOIN (SELECT [sb_subscriber], MAX [sb |
|
|
10 |
|
start]) AS |
[last visit] |
11 |
FROM |
[subscriptions] |
|
12 |
GROUP |
BY [sb subscriber]) AS [prepared_data] |
|
13 |
ON [s id] = [sb subscriber]; |
|
MS SQL Server поддерживает очень удобный синтаксис создания триггера сразу на нескольких операциях, потому (в отличие от решения для MySQL) мы используем одинаковый код тела триггера для всех трёх случаев (INSERT, UPDATE,
DELETE):
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 293/545
Пример 31: обновление кэширующих таблиц и полей
MS SQL |
|
|
Решение 4.1.1.a (создание триггеров) |
| |
|
|
1 |
CREAT TRIGGER [last visit on subscriptions |
insupd del] |
||||
2 |
ON [subscriptions] |
|
|
|
||
3 |
AFTER INSERT, UPDATE, DELETE |
|
|
|||
4 |
AS |
|
|
|
|
|
5 |
UPDATE |
[subscribers] |
|
|
|
|
6 |
SET |
[s_last_visit] = [last_visit] |
|
|
||
7 |
FROM |
[subscribers] |
|
|
|
|
8 |
|
LEFT JOIN (SELECT [sb_subscriber], |
|
|
||
9 |
|
|
|
MAX [sb_start]) AS |
|
|
10 |
|
|
FROM |
[subscriptions] |
|
[last_visit] |
11 |
|
|
GROUP |
BY |
|
|
12 |
|
|
|
[sb_subscriber]) |
|
AS [prepared_data] |
|
|
|
|
|
|
|
В корректности работы полученного решения вы можете убедиться, выполнив следующие запросы (они выполнены пошагово с пояснениями и показом результатов в решении для MySQL):
MS SQL I Решение 4.1.1.a (запросы для проверки работоспособности) |
1 SET IDENTITY_INSERT [subscriptions] ON;
2
3-- Добавление выдачи книги читателю с идентификатором 2
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 |
|
2 , |
|
14 |
|
1 ■ |
|
15 |
|
'2019-01-12', |
|
16 |
|
'2019-02-12', |
|
17 |
|
'N'); |
|
18 |
|
|
|
19-- Изменение идентификатора читателя в только что
20-- добавленной выдаче с 2 на 1:
21UPDATE [subscriptions]
22 |
SET |
[sb subscriber] = 1 |
23 |
WHERE |
[sb_id] = 200; |
24 |
|
|
25-- Ещё одна выдача книги Петрову П.П.
26-- (идентификатор читателя = 2):
27INSERT INTO [subscriptions]
28 |
|
([sb id], |
|
29 |
|
[sb |
subscriber], |
30 |
|
[sb |
book] |
31 |
|
[sb |
start], |
32 |
|
[sb |
finish], |
33 |
|
[sb |
is active]) |
34 |
VALUES |
201, |
|
35 |
|
2 , |
|
36 |
|
1 ■ |
|
37 |
|
'2020-01-12', |
|
38 |
|
'2020-02-12', |
|
39 |
|
'N'); |
|
40 |
|
|
|
41-- Изменение значения даты ранее откорректированной
42-- выдачи книги (которую переписали с Петрова П.П.
43-- на Иванова И.И.):
44UPDATE [subscriptions]
45 |
SET |
[sb start] = '2018-01-12' |
46 |
WHERE |
[sb_id] = 200; |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 294/545
Пример 31: обновление кэширующих таблиц и полей
MS S QL 1 Решение 4.1.1 .a (запросы для проверки работоспособности) (продолжение)
47 |
-- Удаление этой откорректированной выдачи: DELETE FROM |
|
48 |
[subscriptions] WHERE [sb_id] |
= 200; |
49 |
|
|
50-- Удаление единственной выдачи Петрову П.П.: DELETE
51FROM [subscriptions]
52WHERE [sb_id] = 201;
53
54
55 SET IDENTITY INSERT [subscriptions] OFF;
Переходим к решению для Oracle, которое отличается от решения для MS SQL Server только синтаксическими особенностями реализации той же логики:
|
Oracle |
Решение 4.1.1.a (модификация таблицы и инициализация данных) |
|
|
1 |
-- Модификация таблицы: |
|
2 |
ALTER TABLE "subscribers" |
|
|
3 |
ADD |
("s_last_visit" |
DATE DEFAULT NULL NULL); |
4 |
|
|
|
5-- Инициализация данных:
6UPDATE "subscribers" "outer"
7 |
SET |
"s_last_visit" = |
|
|
|
8 |
|
( |
|
|
|
9 |
|
SELECT |
"last_visit" |
|
|
10 |
|
FROM |
"subscribers" |
|
|
11 |
|
LEFT JOIN (SELECT |
"sb_subscriber", |
|
|
12 |
|
|
|
MAX "sb_start") |
AS "last_visit" |
13 |
|
|
FROM |
"subscriptions" |
|
14 |
|
|
GROUP BY "sb_subscriber"l |
"prepared_data" |
|
15 |
|
ON |
"s_id" |
= "sb_subscriber" |
|
16 |
|
WHERE "outer" "s id" = "sb subscriber"); |
Oracl |
і |
Решение 4.1.1.a (создание триггеров) |
| |
|
||
e |
|
|||||
|
|
|
|
|
|
|
1 |
CREATE TRIGGER "last visit on scs ins upd del" |
|||||
2 |
AFTER INSERT OR UPDATE OR DELETE |
|
|
|||
3 |
ON "subscriptions" |
|
|
|
|
|
4 |
BEGIN |
|
|
|
|
|
5 |
UPDATE "subscribers" "outer" |
|
|
|||
6 |
SET |
"s last visit" = |
|
|
|
|
7 |
|
( |
|
|
|
|
8 |
|
SELECT |
"last visit" |
|
|
|
9 |
|
FROM |
"subscribers" |
|
|
|
10 |
|
LEFT JOIN (SELECT |
"sb subscriber", |
|||
11 |
|
|
|
MAX "sb start" |
AS "last visit" |
|
12 |
|
|
FROM |
"subscriptions" |
|
|
13 |
|
|
GROUP BY "sb subscriber") "prepared data" |
|||
14 |
|
ON |
"s id" = "sb subscriber" |
|
15WHERE "outer" "s id" = "sb subscriber");
16END;
Вданном решении мы использовали возможность Oracle создавать т.н. «триггеры уровня выражения» (statement level triggers), работающие аналогично триггерам MS SQL Server: такой триггер активируется после выполнения всей операции один раз, а не для каждого модифицируемого ряда отдельно, как это происходит, например, в MySQL, где поддерживаются только «триггеры уровня записи» (row level triggers), активирующиеся отдельно для каждого модифицируемого ряда.
Вкорректности работы полученного решения вы можете убедиться, выполнив следующие запросы (они выполнены пошагово с пояснениями и показом результатов в решении для MySQL):
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 295/545
Пример 31: обновление кэширующих таблиц и полей
'ЙАЙ'
Решение 4.1.1. b{272}.
Во многом решение данной задачи похоже на решение{216} задачи 3.1.2.a{215}, которое рекомендуется повторить перед тем, как продолжить чтение.
Как обычно, начнём с MySQL. Создадим агрегирующую таблицу:
MySQL і Решение 4.1.1.b (создание агрегирующей таблицы)
1CREATE. TABLE 'averages' ..............
2(
3'books_taken' DOUBLE NOT NULL,
4'days_to_read' DOUBLE NOT NULL,
5'books_returned' DOUBLE NOT NULL
6)
Проинициализируем данные в созданной таблице:
MyS |
QL | решение 4.1.1 .b (очистка таолицы и инициализация данных) І |
|
|||
|
|
||||
1 |
-- Очистка таблицы: |
|
|
||
2 |
TRUNCATE TABLE 'averages'; |
|
|
||
3 |
|
|
|
|
|
4 |
-- Инициализация данных: |
|
|
||
5 |
INSERT INTO 'averages' |
|
|
||
6 |
|
('books_taken', |
|
|
|
7 |
|
'days_to_read', |
|
|
|
8 |
|
'books_returned') |
|
|
|
9 |
SELECT ( 'active_count' / 'subscribers_count' ) |
AS 'books_taken', |
|||
10 |
|
( 'days_sum' / 'inactive_count' ) |
AS 'days_to_read', |
||
11 |
|
( 'inactive_count' / 'subscribers_count' ) AS 'books_returned' |
|||
12 |
FROM |
(SELECT COUNT('s_id') AS |
'subscribers_count' |
||
13 |
|
FROM |
'subscribers') AS 'tmp_subscribers_count', |
||
14 |
|
(SELECT COUNT('sb_id') AS 'active_count' |
|
||
15 |
|
FROM |
'subscriptions' |
|
|
16 |
|
WHERE |
'sb_is_active' = |
'Y') AS 'tmp_active_count', |
|
17 |
|
(SELECT COUNT('sb_id') AS 'inactive_count' |
|
||
18 |
|
FROM |
'subscriptions' |
|
|
19 |
|
WHERE |
'sb_is_active' = |
'N') AS 'tmp_inactive_count', |
|
20 |
|
(SELECT SUM(DATEDIFF('sb_finish', 'sb_start')) AS 'days_sum' |
|||
21 |
|
FROM |
'subscriptions' |
|
|
22 |
|
WHERE |
'sb is active' = 'N') AS 'tmp days sum'; |
Напишем триггеры, модифицирующие данные в агрегирующей таблице. Агрегация происходит на основе информации, представленной в таблицах subscribers и subscriptions, потому придётся создавать триггеры для обеих этих таблиц.
Чтобы не усложнять решение, мы будем использовать один и тот же код для всех пяти триггеров (на таблице subscribers должны быть только INSERT- и DE- LETE-триггеры, т.к. обновление этой таблицы не влияет на результаты вычислений, а на таблице subscriptions должны быть все три триггера: INSERT, UPDATE, DE-
LETE).
(В Важно! В MySQL триггеры не активируются каскадными операциями, потому изменения в таблице subscriptions, вызванные удалением книг, останутся «незаметными» для триггеров на этой таблице. В задании 4.1.1. TSK.E{291} вам предлагается доработать данное решение, устранив эту проблему.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 297/545
Пример 31: обновление кэширующих таблиц и полей
для
1 -- Удаление старых версий триггеров 2 -- (удобно в процессе разработки и отладки):
DROP TRIGGER 'upd_avgs_on_subscribers_ins'; 4 DROP TRIGGER 'upd_avgs_on_subscribers_del'; 5
6-- Переключение разделителя завершения запроса,
7-- т.к. сейчас запросом будет создание триггера,
8-- внутри которого есть свои, классические запросы:
9DELIMITER $$
10
11-- Создание триггера, реагирующего на добавление читателей:
12CREATE TRIGGER 'upd_avgs_on_subscribers_ins'
13AFTER INSERT
14ON 'subscribers'
15FOR EACH ROW
16BEGIN
17UPDATE 'averages',
18(SELECT COUNT('s_id') AS 'subscribers_count'
19 |
|
FROM |
'subscribers') AS 'tmp_subscribers_count', |
|
20 |
|
(SELECT COUNT('sb_id') AS 'active_count' |
||
21 |
|
FROM |
'subscriptions' |
|
22 |
|
WHERE |
'sb_is_active' = |
'Y') AS 'tmp_active_count', |
23 |
|
(SELECT COUNT('sb_id') AS |
'inactive_count' |
|
24 |
|
FROM |
'subscriptions' |
|
25 |
|
WHERE |
'sb_is_active' = |
'N') AS 'tmp_inactive_count', |
26 |
|
(SELECT SUM(DATEDIFF('sb_finish', 'sb_start')) AS 'days_sum' |
||
27 |
|
FROM |
'subscriptions' |
|
28 |
|
WHERE |
'sb_is_active' = |
'N') AS 'tmp_days_sum' |
29 |
SET |
'books_taken' = 'active_count' / 'subscribers_count', |
30'days_to_read' = 'days_sum' / 'inactive_count',
31'books_returned' = 'inactive_count' / 'subscribers_count';
32END;
33$$
34
35-- Создание триггера, реагирующего на удаление читателей:
36CREATE TRIGGER 'upd_avgs_on_subscribers_del'
37AFTER DELETE
38ON 'subscribers'
39FOR EACH ROW
40BEGIN
41UPDATE 'averages',
42(SELECT COUNT('s_id') AS 'subscribers_count'
43 |
|
FROM |
'subscribers') AS 'tmp_subscribers_count', |
|
44 |
|
(SELECT COUNT('sb_id') AS 'active_count' |
||
45 |
|
FROM |
'subscriptions' |
|
46 |
|
WHERE |
'sb_is_active' = 'Y') AS 'tmp_active_count', |
|
47 |
|
(SELECT COUNT('sb_id') AS |
'inactive_count' |
|
48 |
|
FROM |
'subscriptions' |
|
49 |
|
WHERE |
'sb_is_active' = |
'N') AS 'tmp_inactive_count', |
50 |
|
(SELECT SUM(DATEDIFF('sb_finish', 'sb_start')) AS |
||
51 |
|
FROM |
'subscriptions' |
|
52 |
|
WHERE |
'sb_is_active' = 'N') AS 'tmp_days_sum' |
|
53 |
SET |
'books_taken' = 'active_count' / 'subscribers_count', |
||
45 |
|
'days_to_read' = 'days_sum' / 'inactive_count', |
55'books_returned' = 'inactive_count' / 'subscribers_count';
56END;
57$$
58
59-- Восстановление разделителя завершения запросов:
60DELIMITER ;
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 298/545
Пример 31: обновление кэширующих таблиц и полей
Создадим триггеры на таблице subscriptions.
для
1 -- Удаление старых версий триггеров
2-- (удобно в процессе разработки и отладки):
DROP TRIGGER 'upd_avgs_on_subscriptions_ins';
4DROP TRIGGER 'upd_avgs_on_subscriptions_upd';
5DROP TRIGGER 'upd_avgs_on_subscriptions_del';
7-- Переключение разделителя завершения запроса,
8-- т.к. сейчас запросом будет создание триггера,
9-- внутри которого есть свои, классические запросы:
10DELIMITER $$
12-- Создание триггера, реагирующего на добавление выдачи книги:
13CREATE TRIGGER 'upd_avgs_on_subscriptions_ins'
14AFTER INSERT
15 ON 'subscriptions'
16FOR EACH ROW
17BEGIN
18UPDATE 'averages',
19(SELECT COUNT('s_id') AS 'subscribers_count'
20 |
|
FROM |
'subscribers') AS 'tmp_subscribers_count', |
|
21 |
|
(SELECT COUNT('sb_id') AS 'active_count' |
||
22 |
|
FROM |
'subscriptions' |
|
23 |
|
WHERE |
'sb_is_active' = |
'Y') AS 'tmp_active_count', |
24 |
|
(SELECT COUNT('sb_id') AS |
'inactive_count' |
|
25 |
|
FROM |
'subscriptions' |
|
26 |
|
WHERE |
'sb_is_active' = |
'N') AS 'tmp_inactive_count', |
27 |
|
(SELECT SUM(DATEDIFF('sb_finish', 'sb_start')) AS 'days_sum' |
||
28 |
|
FROM |
'subscriptions' |
|
29 |
|
WHERE |
'sb_is_active' = |
'N') AS 'tmp_days_sum' |
30 |
SET |
'books_taken' = 'active_count' / 'subscribers_count', |
31'days_to_read' = 'days_sum' / 'inactive_count',
32'books_returned' = 'inactive_count' / 'subscribers_count';
33END;
34$$
35
36-- Создание триггера, реагирующего на обновление выдачи книги:
37CREATE TRIGGER 'upd_avgs_on_subscriptions_upd'
38AFTER UPDATE
39ON 'subscriptions'
40FOR EACH ROW
41BEGIN
42UPDATE 'averages',
43(SELECT COUNT('s_id') AS 'subscribers_count'
44 |
|
FROM |
'subscribers') AS 'tmp_subscribers_count', |
45 |
|
(SELECT COUNT('sb_id') AS 'active_count' |
|
46 |
|
FROM |
'subscriptions' |
47 |
|
WHERE |
'sb_is_active' = 'Y') AS 'tmp_active_count', |
48 |
|
(SELECT COUNT('sb_id') AS 'inactive_count' |
|
49 |
|
FROM |
'subscriptions' |
50 |
|
WHERE |
'sb_is_active' = 'N') AS 'tmp_inactive_count', |
51 |
|
(SELECT SUM(DATEDIFF('sb_finish', 'sb_start')) AS 'days_sum' |
|
52 |
|
FROM |
'subscriptions' |
53 |
|
WHERE |
'sb_is_active' = 'N') AS 'tmp_days_sum' |
45 |
SET |
'books_taken' = 'active_count' / 'subscribers_count', |
55'days_to_read' = 'days_sum' / 'inactive_count',
56'books_returned' = 'inactive_count' / 'subscribers_count';
57END;
58$$
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 299/545