Бази даних-20210115T104840Z-001 / Реферат на тему _Современные СУБД_ / Using_MySql,_MS_SQL_Server_and_Oracle
.pdfПример 31: обновление кэширующих таблиц и полей
MySQL I |
Решение 4.1.1.b (триггеры для таблицы subscriptions) (продолжение) |
| |
59-- Создание триггера, реагирующего на удаление выдачи книги:
60CREATE TRIGGER 'upd_avgs_on_subscriptions_del'
61AFTER DELETE
62ON 'subscriptions'
63FOR EACH ROW
64BEGIN
65UPDATE 'averages',
66 |
|
(SELECT COUNT('s id') AS 'subscribers count' |
|
67 |
|
FROM |
'subscribers') AS 'tmp subscribers count', |
68 |
|
(SELECT COUNT('sb id') AS 'active count' |
|
69 |
|
FROM |
'subscriptions' |
70 |
|
WHERE |
'sb is active' = 'Y') AS 'tmp active count', |
71 |
|
(SELECT COUNT('sb id') AS 'inactive count' |
|
72 |
|
FROM |
'subscriptions' |
73 |
|
WHERE |
'sb is active' = 'N') AS 'tmp inactive count', |
74 |
|
(SELECT SUM(DATEDIFF('sb finish', 'sb start')) AS 'days sum' |
|
75 |
|
FROM |
'subscriptions' |
76 |
|
WHERE |
'sb is active' = 'N') AS 'tmp days sum' |
77 |
SET |
'books taken' = 'active count' / 'subscribers count', |
|
78 |
|
'days to read' = 'days sum' / 'inactive count', |
|
79 |
|
'books returned' = 'inactive count' / 'subscribers count'; |
80END;
81$$
82
83-- Восстановление разделителя завершения запросов:
84DELIMITER ;
Проверим работоспособность полученного решения. Будем изменять данные в таблицах subscribers и subscriptions и отслеживать изменения данных в таблице averages.
Исходное состояние таблицы averages таково:
books_taken |
days_to_read |
books_returned |
||||
1.25 |
|
|
|
46 |
1.5 |
|
|
Добавим читателя: |
|
|
|||
|
|
|
|
|||
1 |
INSERT INTO 'subscribers' |
|
|
|||
2 |
|
|
|
('s_id', |
|
|
3 |
|
|
|
's name') |
|
|
4 |
VALUES |
(500, |
|
|
||
5 |
|
|
|
'Читателев |
|
|
|
|
|||||
books_taken |
days_to_read |
books_returned |
||||
1 |
|
|
|
46 |
1.2 |
|
|
Теперь удалим его: |
|
|
|||
MySQL |
Решение 4.1.1.b (проверка работоспособности) |
|||||
|
1 |
|
DELETE FROM 'subscribers' |
|||
2 |
WHERE 's id' = 500 |
|
|
books_taken days_to_read books_returned |
||
1.25 |
46 |
1.5 |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 300/545
Пример 31: обновление кэширующих таблиц и полей
Добавим две выдачи книги:
MySQL I Решение 4.1.1.b (проверка работоспособности)
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 |
200, |
9 |
|
1 |
10 |
|
1 |
11 |
|
'2019-01-12', |
12 |
|
'2019-02-12', |
13 |
|
'N'), |
14 |
|
201, |
15 |
|
2 |
16 |
|
1 |
17 |
|
'2020-01-12', |
18 |
|
'2020-02-12', |
19 |
|
'N' ) |
|
|
|
books_taken days_to_read books_returned |
||
1.25 |
42.25 |
2 |
Изменим состояние добавленных выдач с «книга возвращена» на «книга не возвращена»:
Решение 4.1.1.b
1 UPDATE 'subscriptions'
2 SET 'sb_is_active' = 'Y
3 WHERE 'sb id' >= 200
books_taken |
days_to_read |
books_returned |
||||
1.75 |
|
|
46 |
|
1.5 |
|
|
Удалим эти две выдачи книг: |
|||||
|
|
|
|
|||
books_taken |
days_to_read |
books_returned |
|
|||
1.25 |
|
46 |
1.5 |
|
Итак, триггеры для MySQL работают корректно. Переходим к решению для
MS SQL Server.
MS SQL Решение 4.1.1 .b (создание агрегирующей
1таблицы)
2CREATE TABLE. [aVerages] ..............
3[books_taken] DOUBLE PRECISION NOT NULL,
4 |
[days_to_read] DOUBLE PRECISION NOT NULL, |
5 |
[books returned] DOUBLE PRECISION NOT NULL |
6 |
|
Проинициализируем данные в созданной таблице. Обратите внимание: здесь снова актуальна проблема преобразования типов данных, т.к. результат деления окажется целочисленным (с потерей части данных), если предварительно не преобразовать полученные значения COUNT и SUM к дроби.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 301/545
Пример 31: обновление кэширующих таблиц и полей
MS SQL Решение 4.1.1 |
и |
|
||
1 |
.b |
|
|
|
-- Очистка таблицы: |
|
|||
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 CAST(COUNT>[s id]) AS DOUBLE PRECISION) |
||
13 |
|
AS [subscribers count] |
|
|
14 |
|
FROM |
[subscribers]) AS [tmp subscribers count], |
|
15 |
|
(SELECT CAST(COUNT( [sb id] AS DOUBLE PRECISION) |
||
16 |
|
AS [active count] |
|
|
17 |
|
FROM |
[subscriptions] |
|
18 |
|
WHERE |
[sb is active] = 'Y') AS [tmp active count], |
|
19 |
|
(SELECT CAST(COUNT( [sb id] AS DOUBLE PRECISION) |
||
20 |
|
AS [inactive count] |
|
|
21 |
|
FROM |
[subscriptions] |
|
22 |
|
WHERE |
[sb is active] = 'N') AS [tmp inactive count], |
|
23 |
|
(SELECT CAST(SUM(DATEDIFF(day, [sb start], [sb finish] ) |
||
24 |
|
AS DOUBLE PRECISION) AS [days sum] |
|
|
25 |
|
FROM |
[subscriptions] |
|
26 |
|
WHERE |
[sb is active] = 'N') AS [tmp days sum]; |
|
|
|
|
|
|
Создадим на таблицах subscribers и subscriptions триггеры, модифицирующие данные в агрегирующей таблице averages. Напомним, что MS SQL Server позволяет указывать в триггере сразу несколько активирующих событий, что позволяет нам немного сократить количество написанного кода.
MS SQL Решение 4.1.1 .b (триггеры для таблицы subscribers) |
1CREATE TRIGGER [upd avgs on subscribers ins del]
2ON [subscribers]
3AFTER INSERT, DELETE
4AS
5UPDATE [averages]
6 |
SET |
[books taken] = [active count] / [subscribers count] |
|
7 |
|
[days to read] = [days sum] / [inactive count], |
|
8 |
|
[books returned] = [inactive count] / [subscribers count] |
|
9 |
FROM |
(SELECT CAST(COUNT([s id] AS DOUBLE PRECISION) |
|
10 |
|
AS [subscribers count] |
|
11 |
|
FROM |
[subscribers] AS [tmp subscribers count], |
12 |
|
(SELECT CAST(COUNT([sb id]) AS DOUBLE PRECISION) |
|
13 |
|
AS [active count] |
|
14 |
|
FROM |
[subscriptions] |
15 |
|
WHERE |
[sb is active] = 'Y') AS [tmp active count], |
16 |
|
(SELECT CAST(COUNT([sb id]) AS DOUBLE PRECISION) |
|
17 |
|
AS [inactive count] |
|
18 |
|
FROM |
[subscriptions] |
19 |
|
WHERE |
[sb is active] = 'N') AS [tmp inactive count], |
20 |
|
(SELECT CAST(SUM(DATEDIFF(day, [sb start], [sb finish])) |
|
21 |
|
AS DOUBLE PRECISION) AS [days sum] |
|
22 |
|
FROM |
[subscriptions] |
23 |
|
WHERE |
[sb is active] = 'N') AS [tmp days sum]; |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 302/545
Пример 31: обновление кэширующих таблиц и полей
MS SQL Решение 4.1.1.b (триггеры для таблицы subscriptions)
1CREATE TRIGGER [upd_avgs_on_subscriptions_ins_upd_del]
2ON [subscriptions]
3AFTER INSERT, UPDATE, DELETE
4AS
5UPDATE [averages]
6 |
SET |
[books_taken] = [active_count] / [subscribers_count] |
|||
|
|
[days_to_read] = |
[days_sum] / [inactive_count], |
||
8 |
|
[books_returned] = |
[inactive_count] / [subscribers_count] |
||
9 |
FROM |
(SELECT CAST(COUNT([s_id] |
AS DOUBLE PRECISION) |
||
10 |
|
AS [subscribers_count] |
|
||
11 |
|
FROM |
[subscribers] AS [tmp_subscribers_count], |
||
12 |
|
(SELECT CAST(COUNT([sb_id]) AS DOUBLE PRECISION) |
|||
13 |
|
AS [active_count] |
|
|
|
14 |
|
FROM |
[subscriptions] |
|
|
15 |
|
WHERE |
[sb_is_active] = |
'Y') AS [tmp_active_count], |
|
16 |
|
(SELECT CAST(COUNT([sb_id]) AS DOUBLE PRECISION) |
|||
17 |
|
AS [inactive_count] |
|
||
18 |
|
FROM |
[subscriptions] |
|
|
19 |
|
WHERE |
[sb_is_active] = |
'N') AS [tmp_inactive_count], |
|
20 |
|
(SELECT CAST(SUM(DATEDIFF(day, [sb_start], [sb_finish])) |
|||
21 |
|
AS DOUBLE PRECISION) AS |
[days_sum] |
||
22 |
|
FROM |
[subscriptions] |
|
|
23 |
|
WHERE |
[sb is_ active] |
= 'N') AS [tmp days sum]; |
В корректности работы полученного решения вы можете убедиться, выполнив следующие запросы (они выполнены пошагово с пояснениями и показом результатов в решении для MySQL):
MS SQL I Решение 4.1.1.b (запросы для проверки работоспособности) |
1 SET IDENTITY INSERT [subscribers] ON;
2
3-- Добавление читателя:
4INSERT INTO [subscribers]
5 |
|
([s id], |
|
6 |
|
[s |
name]) |
7 |
VALUES |
500, |
|
8 |
|
N' |
Читателев Ч.Ч.'); |
9 |
|
|
|
10-- Удаление только что добавленного читателя:
11DELETE FROM [subscribers]
12WHERE [s id] = 500
13
14SET IDENTITY INSERT [subscribers] OFF;
15SET IDENTITY INSERT [subscriptions] ON;
17-- Добавление двух выдач книг:
18 |
INSERT INTO [subscriptions] |
|||
19 |
|
([sb id] , |
||
20 |
|
[sb |
subscriber], |
|
21 |
|
[sb |
book] |
|
22 |
|
[sb |
start], |
|
23 |
|
[sb |
finish], |
|
24 |
|
[sb |
is active]) |
|
25 |
VALUES |
200, |
||
26 |
|
1 |
■ |
|
27 |
|
1 |
■ |
|
28 |
|
'2019-01-12', |
||
29 |
|
'2019-02-12', |
||
30 |
|
'N'), |
||
31 |
|
201, |
|
|
32 |
|
2 |
, |
|
33 |
|
1 |
■ |
|
34 |
|
'2020-01-12', |
||
35 |
|
'2020-02-12', |
||
36 |
|
'N'); |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 303/545
Пример 31: обновление кэширующих таблиц и полей
MS SQL I Решение 4.1.1.b (запросы для проверки работоспособности) (продолжение) |
37-- Изменение состояния добавленных выдач с «книга возвращена»
38-- на «книга не возвращена»:
39UPDATE [subscriptions]
40 |
SET |
[sb is active] = 'Y' |
41 |
WHERE |
[sb id] >= 200; |
42 |
|
|
43-- Удаление только что добавленных выдач книг:
44DELETE FROM [subscriptions]
45WHERE [sb id] >= 200;
46
47 SET IDENTITY_INSERT [subscriptions] OFF;
Переходим к решению для Oracle, которое отличается от решения для MS SQL Server только синтаксическими особенностями реализации той же логики:
Oracle і Решение 4.1.1.b (создание агрегирующей таблицы)
1CREATE TABLE "averages"
2(
3"books_taken" DOUBLE PRECISION NOT NULL,
4"days_to_read" DOUBLE PRECISION NOT NULL,
5"books_returned" DOUBLE PRECISION NOT NULL
6)
Oracl |
і Решение 4.1.1.b (очистка таблицы и инициализация данных) |
| |
|
||
e |
|
||||
|
|
|
|
|
|
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 |
COUNT("s id" |
AS "subscribers count" |
||
13 |
FROM |
"subscribers" |
"tmp subscribers count", |
||
14 |
(SELECT COUNT("sb id" |
AS "active count" |
|
||
15 |
FROM |
"subscriptions" |
|
|
|
16 |
WHERE |
"sb is active" = 'Y') "tmp active count" |
|||
17 |
(SELECT COUNT("sb id" |
AS "inactive count" |
|
||
18 |
FROM |
"subscriptions" |
|
|
|
19 |
WHERE |
"sb is active" = 'N') "tmp inactive count", |
|||
20 |
(SELECT SUM "sb finish" - "sb start" |
AS "days sum" |
|||
21 |
FROM |
"subscriptions" |
|
|
|
22 |
WHERE |
"sb is active" = 'N') "tmp days sum" |
Несмотря на то, что логика работы триггеров в Oracle полностью идентична подходам, использованным в MySQL и MS SQL Server, в силу синтаксических особенностей данной СУБД сам запрос на обновление данных выглядит несколько необычно. Здесь мы используем оператор MERGE, указав как условие объединения 1=1, т.е. заведомо выполняющееся равенство.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 304/545
Пример 31: обновление кэширующих таблиц и полей
Oracle Решение 4.1.1 .b (триггеры для
1 CREATE TRIGGER "upd_avgs_on_sbrs_ins_del"
2AFTER INSERT OR DELETE
3ON "subscribers"
4BEGIN
5 |
MERGE INTO "averages" |
6USING
7(
|
SELECT ( "active_count" / "subscribers_count" ) |
AS "books_taken" |
|||
9 |
|
( "days_sum" / "inactive_count" ) |
AS "days_to_read", |
||
10 |
|
( "inactive_count" / "subscribers_count" ) AS"books_returned" |
|||
11 |
FROM |
(SELECT COUNT "s_id") |
AS "subscribers_count" |
||
12 |
|
FROM |
"subscribers" |
"tmp_subscribers_count", |
|
13 |
|
(SELECT COUNT "sb_id" |
AS "active_count" |
|
|
14 |
|
FROM |
"subscriptions |
" |
|
15WHERE "sb_is_active" = 'Y') "tmp_active_count"
16(SELECT COUNT "sb_id" AS "inactive_count"
17 |
FROM |
"subscriptions " |
18WHERE "sb_is_active" = 'N') "tmp_inactive_count"
19(SELECT SUM("sb_finish " - "sb_start" AS "days_sum
20 |
|
FROM |
"subscriptions " |
21 |
|
WHERE |
"sb_is_active" = 'N') " tmp_days_sum" |
22 |
) |
ON 1 |
1) |
23 |
WHEN MATCHED THEN UPDATE |
||
24 |
SET |
"averages" "books_taken" = "tmp" "books_taken", |
25"averages" "days_to_read" = "tmp" "days_to_read",
26"averages" "books_returned" = "tmp" "books_returned";
27END;
Oracle Решение 4.1.1.b (триггеры для
1 CREATE TRIGGER "upd_avgs_on_sbps_ins_upd_del"
2AFTER INSERT OR UPDATE OR DELETE
3ON "subscriptions"
4BEGIN
5 MERGE INTO "averages"
6USING
7(
|
SELECT ( "active_count" / "subscribers_count" ) |
AS "books_taken" |
|||
9 |
|
( "days_sum" / "inactive_count" ) |
AS "days_to_read", |
||
10 |
|
( "inactive_count" / "subscribers_count" ) AS"books_returned" |
|||
11 |
FROM |
(SELECT COUNT "s_id") |
AS "subscribers_count" |
||
12 |
|
FROM |
"subscribers" |
"tmp_subscribers_count", |
|
13 |
|
(SELECT COUNT "sb_id" |
AS "active_count" |
|
|
14 |
|
FROM |
"subscriptions |
" |
|
15WHERE "sb_is_active" = 'Y') "tmp_active_count"
16(SELECT COUNT "sb_id" AS "inactive_count"
17 |
FROM |
"subscriptions " |
18WHERE "sb_is_active" = 'N') "tmp_inactive_count"
19(SELECT SUM("sb_finish" - "sb_start" AS "days_sum
20 |
|
FROM |
"subscriptions " |
21 |
|
WHERE |
"sb_is_active" = 'N') " tmp_days_sum" |
22 |
) |
ON 1 |
1) |
23 |
WHEN MATCHED THEN UPDATE |
||
24 |
SET |
"averages" "books_taken" = "tmp" "books_taken", |
25"averages" "days_to_read" = "tmp" "days_to_read",
26"averages" "books_returned" = "tmp" "books_returned";
27END;
Как и в решении{272} задачи 4.1.1.a{272}, здесь мы использовали возможность Oracle создавать т.н. «триггеры уровня выражения» (statement level triggers): такой триггер активируется после выполнения всей операции один раз, а не для каждого модифицируемого ряда отдельно, как это происходит, например, в MySQL, где поддерживаются только «триггеры уровня записи» (row level triggers), активирующиеся отдельно для каждого модифицируемого ряда.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 305/545
Пример 31: обновление кэширующих таблиц и полей
В корректности работы полученного решения вы можете убедиться, выполнив следующие запросы (они выполнены пошагово с пояснениями и показом результатов в решении для MySQL):
|
Oracl |
і Решение 4.1.1.b (запросы для проверки работоспособности) | |
e |
|
|
|
|
|
1 |
|
ALTER TRIGGER "TRG subscribers s id" DISABLE; |
2 |
|
ALTER TRIGGER "TRG_subscriptions_sb_id" DISABLE; |
3 |
4 |
|
|
-- Добавление читателя: |
|
5 |
INSERT INTO "subscribers" |
|
6 |
|
("s id" |
7 |
|
"s name") |
8 |
VALUES |
(500 |
9 |
|
N'Читателев Ч.Ч. ' ); |
10 |
|
|
11-- Удаление только что добавленного читателя:
12DELETE FROM "subscribers"
13WHERE "s id" = 500;
14
15-- Добавление двух выдач книг:
16INSERT ALL
17INTO "subscriptions"
18 |
|
("sb id" |
19 |
|
"sb subscriber" |
20 |
|
"sb book", |
21 |
|
"sb start" |
22 |
|
"sb finish" |
23 |
|
"sb is active" |
24 |
VALUES |
(200 |
25 |
|
1, |
26 |
|
1, |
27 |
|
TO DATE '2019-01-12', 'YYYY-MM-DD'), |
28 |
|
TO DATE '2019-02-12', 'YYYY-MM-DD'), |
29 |
|
'N' ) |
30 |
INTO "subscriptions" |
|
31 |
|
("sb id" |
32 |
|
"sb subscriber" |
33 |
|
"sb book", |
34 |
|
"sb start" |
35 |
|
"sb finish" |
36 |
|
"sb is active" |
37 |
VALUES |
(201 |
38 |
|
2, |
39 |
|
1, |
40 |
|
TO DATE '2020-01-12', 'YYYY-MM-DD'), |
41 |
|
TO DATE '2020-02-12', 'YYYY-MM-DD'), |
42 |
|
'N' ) |
43 |
SELECT 1 FROM "DUAL" |
|
44 |
|
|
45-- Изменение состояния добавленных выдач с «книга возвращена»
46-- на «книга не возвращена»:
47UPDATE "subscriptions"
48 |
SET |
"sb is active" = 'Y' |
49 |
WHERE |
"sb id" >= 200; |
50 |
|
|
51-- Удаление только что добавленных выдач книг:
52DELETE FROM "subscriptions"
53WHERE "sb id" >= 200;
54
55ALTER TRIGGER "TRG subscribers s id" ENABLE;
56ALTER TRIGGER "TRG subscriptions sb id" ENABLE;
На этом решение данной задачи завершено.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 306/545
Пример 31: обновление кэширующих таблиц и полей
СЗадание 4.1.1 .TSK.A: модифицировать схему базы данных «Библиотека» таким образом, чтобы таблица authors хранила актуальную информацию о дате последней выдачи книги автора читателю.
ОЗадание 4.1.1 .TSK.B: создать кэширующую таблицу best_averages, содержащую в любой момент времени следующую актуальную информацию: а) сколько в среднем книг находится на руках у читателей, за время работы с библиотекой прочитавших более 20 книг; б) за сколько в среднем по времени (в днях) прочитывает книгу читатель,
никогда не державший у себя книгу больше двух недель; в) сколько в среднем книг прочитал читатель, не имеющий просроченных выдач книг.
Задание 4.1.1.TSK.C: оптимизировать MySQL-триггеры из решения{281} задачи 4.1.1.b{272} так, чтобы не выполнять лишних действий там, где в них нет необходимости (подсказка: не в каждом случае нам нужны все собираемые имеющимися запросами данные).
|
Задание 4.1.1.TSK.D: доработать решение{272} задачи 4.1.1.a{272} для |
( |
MySQL таким образом, чтобы оно учитывало изменения в таблице sub- |
scriptions, вызванные операцией каскадного удаления (при удалении |
|
книг). Убедиться, что решения для MS SQL Server и Oracle не требуют такой |
|
|
доработки. |
|
Задание 4.1.1.TSK.E: доработать решение{281} задачи 4.1.1.b{272} для |
|
MySQL таким образом, чтобы оно учитывало изменения в таблице sub- |
|
scriptions, вызванные операцией каскадного удаления (при удалении |
|
книг). Убедиться, что решения для MS SQL Server и Oracle не требуют |
|
такой доработки. |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 307/545
Пример 32: обеспечение консистентности данных
4.1.2.Пример 32: обеспечение консистентности данных
ОЗадача 4.1.2.a{292}: модифицировать схему базы данных «Библиотека» таким образом, чтобы таблица subscribers хранила информацию о том, сколько
в настоящий момент книг выдано каждому из читателей.
О Задача 4.1.2.b{305}: модифицировать схему базы данных «Библиотека» таким образом, чтобы таблица genres хранила информацию о том, сколько в
настоящий момент книг относится к каждому жанру.
Ожидаемый результат 4.1.2.a.
Таблица subscribers содержит дополнительное поле, хранящее актуальную информацию о количестве выданных каждому читателю книг:
s_id |
s_name |
s_books |
1 |
Иванов И.И. |
0 |
2 |
Петров П.П. |
0 |
3 |
Сидоров С.С. |
3 |
4 |
Сидоров С.С. |
2 |
Ожидаемый результат 4.1.2.b.
Таблица genres содержит дополнительное поле, хранящее актуальную информацию о количестве относящихся к каждому жанру книг:
g_id |
g_name |
g_books |
1 |
Поэзия |
2 |
2 |
Программирование |
3 |
3 |
Психология |
1 |
4 |
Наука |
0 |
5 |
Классика |
4 |
6 |
Фантастика |
1 |
уЦ7
"А Решение 4.1.2.a{292}.
Как и в решении{272} задачи 4.1.1.a{272} здесь нужно будет выполнить три шага:
•модифицировать таблицу subscribers (добавив туда поле для хранения количества выданных читателю книг);
•проинициализировать значения количества выданных книг для всех читателей;
•создать триггеры для поддержания этой информации в актуальном состоянии.
Вотличие от решения{272} задачи 4.1.1.a{272} здесь значение по умолчанию для нового поля представляет собой не NULL, а 0 (потому что «читатель ни разу не
приходил в библиотеку» — это «неизвестность», т.е. NULL, а «у читателя нет книг»
— это вполне чёткое и понятное значение, т.е. 0). Следуя той же логике, в инициализирующем запросе мы используем JOIN, а не LEFT JOIN — нет никакого смысла обновлять данные для читателей, ни разу не бравших книги.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 308/545
Пример 32: обеспечение консистентности данных
Итак, для MySQL первые два шага выполняются с помощью следующих запросов.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 309/545