Материал: Using_MySql,_MS_SQL_Server_and_Oracle(1)

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

Пример 27: выборка данных с использованием кэширующих представлений и таблиц

Увеличим на пять единиц количество экземпляров книги, которой сейчас в библиотеке зарегистрировано 10 экземпляров (такая книга у нас одна):

 

Oracle

 

Решение 3.1.2.a (проверка реакции на изменение количества книги)

 

1

 

UPDATE

"books"

 

2

 

SET

"b_quantity" = "b_quantity" + 5

 

 

 

 

 

 

3WHERE "b_quantity" = 10;

4COMMIT; -- И подождать минуту.

 

total

given

rest

Было

48

5

43

Стало

53

5

48

Удалим книгу, оба экземпляра которой сейчас находится на руках у читателей (книга с идентификатором 1).

Oracle

Решение 3.1.2.a (проверка реакции на удаление книги)

1DELETE FROM "books"

2WHERE "b_id" = 1;

3COMMIT; -- И подождать минуту.

 

total

given

rest

Было

53

5

48

Стало

51

3

48

Отметим, что по выдаче с идентификатором 3 книга возвращена:

 

Oracle

 

 

Решение 3.1.2.a (проверка реакции на возврат книги)

 

1

 

UPDATE

"subscriptions"

 

2

 

SET

"sb_is_active" = 'N'

3WHERE "sb_id" = 3;

4COMMIT; -- И подождать минуту.

 

total

given

rest

Было

51

3

48

Стало

51

2

49

Отменим эту операцию (снова отметим книгу как невозвращённую):

 

Oracle

 

 

Решение 3.1.2.a (проверка реакции на отмену возврата книги)

 

1

 

UPDATE

"subscriptions"

2

 

SET

"sb_is_active" = 'Y'

3WHERE "sb_id" = 3;

4COMMIT; -- И подождать минуту.

 

total

given

rest

Было

51

2

49

Стало

51

3

48

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

Пример 27: выборка данных с использованием кэширующих представлений и таблиц

Добавим в базу данных информацию о том, что читатель с идентификатором 2 взял в библиотеке книги с идентификаторами 5 и 6:

Oracle

Решение 3.1.2.a (проверка реакции на выдачу книг)

1INSERT ALL

2INTO "subscriptions" ("sb_subscriber",

3

 

"sb_book",

4

 

"sb_start",

5

 

"sb_finish",

6

 

"sb_is_active")

7

 

VALUES (2,

8

 

5,

9

 

TO_DATE('2016-01-10', 'YYYY-MM-DD'),

10

 

TO_DATE('2016-02-10', 'YYYY-MM-DD'),

11

 

'Y')

12

 

INTO "subscriptions" ("sb_subscriber",

13

 

"sb_book",

14

 

"sb_start",

15

 

"sb_finish",

16

 

"sb_is_active")

17

 

VALUES (2,

18

 

6,

19

 

TO_DATE('2016-01-10', 'YYYY-MM-DD'),

20

 

TO_DATE('2016-02-10', 'YYYY-MM-DD'),

21

 

'Y')

22SELECT 1 FROM "DUAL";

23COMMIT; -- И подождать минуту.

 

total

given

rest

Было

51

3

48

Стало

51

5

46

Удалим информацию о выдаче с идентификатором 42 (книга по этой выдаче уже возвращена):

Oracle

Решение 3.1.2.a (проверка реакции на удаление выдачи с возвращённой книгой)

1DELETE FROM "subscriptions"

2WHERE "sb_id" = 42;

3COMMIT; -- И подождать минуту.

 

total

given

rest

Было

51

5

46

Стало

51

5

46

Удалим информацию о выдаче с идентификатором 62 (книга по этой выдаче ещё не возвращена):

Oracle

Решение 3.1.2.a (проверка реакции на удаление выдачи с не возвращённой книгой)

1DELETE FROM "subscriptions"

2WHERE "sb_id" = 62;

3COMMIT; -- И подождать минуту.

 

total

given

rest

Было

51

5

46

Стало

51

4

47

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

Пример 27: выборка данных с использованием кэширующих представлений и таблиц

Наконец, удалим все книги (что также приведёт к каскадному удалению всех выдач):

Oracle

Решение 3.1.2.a (проверка реакции на удаление всех книг)

1DELETE FROM "books";

2COMMIT; -- И подождать минуту.

 

total

given

rest

Было

51

4

47

Стало

0

0

0

Итак, все операции модификации данных в таблицах books и subscriptions вызывают соответствующие изменения в материализованном представле-

нии books_statistics.

Решение 3.1.2.b{215}.

Если вы пропустили решение{216} задачи 3.1.2.a{215}, настоятельно рекомендуется ознакомиться с ним перед тем, как продолжить чтение, т.к. многие неочевидные моменты, которые встретят в данном решении, были рассмотрены ранее.

По сравнению с предыдущей задачей{215} здесь всё будет намного проще, т.к. запрос, формирующий необходимый набор данных, не содержит выражений, подпадающих под ограничения индексированных представлений MS SQL Server и материализованных представлений Oracle.

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

Создадим кэширующую таблицу (именно кэширующую, а не агрегирующую, как в задаче 3.1.2.a{215}, т.к. здесь мы ничего не агрегируем, а лишь сохраняем готовый результат). Код её создания можно почти полностью взять из кода создания таблицы subscritions, а для полей sb_subscriber и sb_book взять их опреде-

ления из таблицы subscribers и books.

MySQL Решение 3.1.2.b (создание кэширующей таблицы)

1CREATE TABLE `subscriptions_ready`

2(

3`sb_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,

4`sb_subscriber` VARCHAR(150) NOT NULL,

5`sb_book` VARCHAR(150) NOT NULL,

6`sb_start` DATE NOT NULL,

7`sb_finish` DATE NOT NULL,

8`sb_is_active` ENUM ('Y', 'N') NOT NULL,

9CONSTRAINT `PK_subscriptions` PRIMARY KEY (`sb_id`)

10)

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

Пример 27: выборка данных с использованием кэширующих представлений и таблиц

Проинициализируем данные в созданной таблице:

MySQL Решение 3.1.2.b (очистка таблицы и инициализация данных)

1-- Очистка таблицы:

2TRUNCATE TABLE `subscriptions_ready`;

3

4-- Инициализация данных:

5INSERT INTO `subscriptions_ready`

6

 

(`sb_id`,

7

 

`sb_subscriber`,

8

 

`sb_book`,

9

 

`sb_start`,

10

 

`sb_finish`,

11

 

`sb_is_active`)

12SELECT `sb_id`,

13`s_name` AS `sb_subscriber`,

14`b_name` AS `sb_book`,

15`sb_start`,

16`sb_finish`,

17`sb_is_active`

18 FROM `books`

19JOIN `subscriptions`

20ON `b_id` = `sb_book`

21JOIN `subscribers`

22ON `sb_subscriber` = `s_id`;

Напишем триггеры, модифицирующие данные в кэширующей таблице. Источником данных являются таблицы books, subscribers и subscriptions, потому придётся создавать триггеры для всех трёх таблиц.

Поскольку MySQL версии 5.6 не позволяет создавать несколько однотипных триггеров на одной и той же таблице, перед выполнением следующего кода придётся удалить созданные в задаче 3.2.1.a{215} триггеры с таблиц books и subscriptions.

Регистрация в библиотеке новых книг и читателей никак не влияет на содержимое таблицы subscriptions, потому нет необходимости создавать INSERT- триггеры на таблицах books и subscribers — достаточно DELETE- и UPDATE- триггеров.

Обратите внимание на несколько важных моментов в представленном ниже

коде:

внутри триггера в MySQL мы не можем явно или неявно подтверждать транзакцию, а потому не можем использовать для очистки таблицы оператор TRUNCATE (он является «нетранзакционным», и потому приводит к неявному подтверждению транзакции);

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

в задаче 3.2.1.a{215} мы использовали BEFORE-триггеры, хотя могли использовать и AFTER — там это не имело значения, здесь же мы обязаны использовать только AFTER-триггеры, т.к. в противном случае в силу особенностей логики транзакций поведение MySQL отличается от ожидаемого, и информация в кэширующей таблице может не обновиться.

За исключением только что рассмотренных нюансов код тела обоих триггеров совершенно тривиален и представляет собой два запроса — на удаление всех

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

Пример 27: выборка данных с использованием кэширующих представлений и таблиц

данных из таблицы и на наполнение таблицы данными на основе полученной выборки. Оба эти запроса можно выполнить совершенно отдельно от триггеров как самостоятельные SQL-конструкции.

В триггере, реагирующем на обновление информации о книге, есть проверка (строка 45) того, поменялось ли название книги. Если не поменялось, то нет необходимости обновлять закэшированные данные.

MySQL Решение 3.1.2.b (триггеры для таблицы books)

1-- Удаление старых версий триггеров

2-- (удобно в процессе разработки и отладки):

3DROP TRIGGER `upd_sbs_rdy_on_books_del`;

4DROP TRIGGER `upd_sbs_rdy_on_books_upd`;

5

6-- Переключение разделителя завершения запроса,

7-- т.к. сейчас запросом будет создание триггера,

8-- внутри которого есть свои, классические запросы:

9DELIMITER $$

10

11-- Создание триггера, реагирующего на удаление книг:

12CREATE TRIGGER `upd_sbs_rdy_on_books_del`

13AFTER DELETE

14ON `books`

15FOR EACH ROW

16BEGIN

17DELETE FROM `subscriptions_ready`;

18INSERT INTO `subscriptions_ready`

19

 

 

(`sb_id`,

20

 

 

`sb_subscriber`,

21

 

 

`sb_book`,

22

 

 

`sb_start`,

23

 

 

`sb_finish`,

24

 

 

`sb_is_active`)

25

 

SELECT

`sb_id`,

26

 

 

`s_name`,

27

 

 

`b_name`,

28

 

 

`sb_start`,

29

 

 

`sb_finish`,

30

 

 

`sb_is_active`

31

 

FROM

`books`

32

 

 

JOIN `subscriptions`

33

 

 

ON `b_id` = `sb_book`

34

 

 

JOIN `subscribers`

35

 

 

ON `sb_subscriber` = `s_id`;

36END;

37$$

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

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