Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
11
Добавлен:
15.01.2021
Размер:
10.35 Mб
Скачать

Пример 32: обеспечение консистентности данных

MS SQL Решение 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]

9

 

FROM

[subscribers]

10

 

 

JOIN (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]

19

 

FROM

[subscribers]

20

 

 

JOIN (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 Решение 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 Стр: 300/545

Пример 32: обеспечение консистентности данных

MS SQL Решение 4.1.2.a (проверка работоспособности) (продолжение)

36-- Удалим добавленные выдачи:

37DELETE FROM [subscriptions]

38WHERE [sb_id] IN (200, 201, 202, 203);

39

40-- Проверим реакцию на обновление выдач книг.

41-- Сначала добавим две выдачи:

42INSERT 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',

60

 

 

'Y');

61

 

 

 

62-- Не меняя идентификатор читателя сделаем выдачи неактивными:

63UPDATE [subscriptions]

64

 

SET

[sb_is_active] =

'N'

65

 

WHERE

[sb_id] IN (300,

301);

66

 

 

 

 

67-- Не меняя идентификатор читателя сделаем выдачи снова активными:

68UPDATE [subscriptions]

69

 

SET

[sb_is_active] =

'Y'

70

 

WHERE

[sb_id] IN (300,

301);

71

 

 

 

 

72-- Изменим идентификатор читателя, не меняя состояние активности выдач:

73UPDATE [subscriptions]

74

 

SET

[sb_subscriber] = 2

75

 

WHERE

[sb_id] IN (300, 301);

76

 

 

 

77-- Изменим идентификатор читателя и сделаем выдачи неактивными:

78UPDATE [subscriptions]

79

 

SET

[sb_subscriber] = 1,

80[sb_is_active] = 'N'

81WHERE [sb_id] IN (300, 301);

82

83-- Изменим идентификатор читателя и сделаем выдачи активными:

84UPDATE [subscriptions]

85

 

SET

[sb_subscriber] = 2,

86[sb_is_active] = 'Y'

87WHERE [sb_id] IN (300, 301);

88

89-- Удаление книги с идентификатором 1 (выдана по одному экземпляру

90-- Петрову и обоим Сидоровым):

91DELETE FROM [books]

92WHERE [b_id] = 1;

93

 

94

SET IDENTITY_INSERT [subscriptions] OFF;

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

Пример 32: обеспечение консистентности данных

Переходим к решению поставленной задачи для Oracle. Модифицируем таблицу subscribers и проинициализируем добавленное поле данными.

MS SQL Решение 4.1.2.a (модификация таблицы и инициализация данных)

1-- Модификация таблицы:

2ALTER TABLE "subscribers"

3ADD ("s_books" INT DEFAULT 0 NOT NULL);

4

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

6UPDATE "subscribers"

7

 

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 (триггеры для таблицы subscriptions)

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

 

 

 

 

10WHERE "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

23WHERE "s_id" = :old."sb_subscriber";

24END IF;

25END;

ВUPDATE-триггере мы также используем один в один тот же самый код, который был использован в решении для MySQL (там же были рассмотрены и показаны графически все ситуации, которые должен учитывать данный триггер).

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

Пример 32: обеспечение консистентности данных

Oracle Решение 4.1.2.a (триггеры для таблицы subscriptions)

1-- Реакция на обновление выдачи книги:

2CREATE OR REPLACE TRIGGER "s_has_books_on_sbps_upd"

3AFTER UPDATE

4ON "subscriptions"

5FOR EACH ROW

6BEGIN

7-- A) Читатель тот же, Y -> N

8IF ((:old."sb_subscriber" = :new."sb_subscriber") AND

9(:old."sb_is_active" = 'Y') AND

10(:new."sb_is_active" = 'N')) THEN

11UPDATE "subscribers"

12

SET

"s_books" = "s_books" - 1

13WHERE "s_id" = :old."sb_subscriber";

14END IF;

15

16-- B) Читатель тот же, N -> Y

17IF ((:old."sb_subscriber" = :new."sb_subscriber") AND

18(:old."sb_is_active" = 'N') AND

19(:new."sb_is_active" = 'Y')) THEN

20UPDATE "subscribers"

21

SET

"s_books" = "s_books" + 1

22WHERE "s_id" = :old."sb_subscriber";

23END 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

31WHERE "s_id" = :old."sb_subscriber";

32UPDATE "subscribers"

33

 

SET

"s_books" = "s_books" + 1

34WHERE "s_id" = :new."sb_subscriber";

35END 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

43WHERE "s_id" = :old."sb_subscriber";

44END 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

52WHERE "s_id" = :new."sb_subscriber";

53END IF;

54END;

Витоге код триггеров для Oracle получился полностью идентичным коду триггеров для MySQL, потому и запросы для проверки работоспособности полученного решения также совпадают для обеих СУБД.

См. код самих запросов ниже, а логика их работы с пояснением и демонстрацией изменения содержимого таблицы subscribers представлена в решении для

MySQL.

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

Пример 32: обеспечение консистентности данных

Oracle Решение 4.1.2.a (проверка работоспособности)

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"

21WHERE "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 Стр: 304/545

Пример 32: обеспечение консистентности данных

Решение 4.1.2.b{292}.

Как и в решении{292} задачи 4.1.2.a{292} здесь нужно будет выполнить те же самые действия — модифицировать таблицу, проинициализировать данные, создать триггеры. И даже код триггеров будет чем-то похож на рассмотренные ранее решения.

Традиционно начинаем с решения для MySQL: модифицируем таблицу и проинициализируем данные.

MySQL Решение 4.1.2.b (модификация таблицы и инициализация данных)

1-- Модификация таблицы:

2ALTER TABLE `genres`

3ADD COLUMN `g_books` INT(11) NOT NULL DEFAULT 0 AFTER `g_name`;

4

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

6UPDATE `genres`

7JOIN (SELECT `g_id`,

8

 

 

 

COUNT(`b_id`)

AS `g_has_books`

9

 

 

FROM

`m2m_books_genres`

10

 

 

GROUP

BY `g_id`) AS

`prepared_data`

11

 

 

USING (`g_id`)

 

12

 

SET

`g_books` = `g_has_books`;

 

Код всех трёх триггеров будет предельно прост: в INSERT-триггере мы увеличиваем счётчик книг у соответствующего жанра, в DELETE-триггере — уменьшаем, в UPDATE-триггере уменьшаем «старому» жанру и увеличиваем «новому» жанру. Никаких дополнительных проверок и ухищрений здесь не требуется.

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

1 DELIMITER $$

2

3-- Реакция на добавление связи между книгами и жанрами:

4CREATE TRIGGER `g_has_books_on_m2m_b_g_ins`

5AFTER INSERT

6ON `m2m_books_genres`

7FOR EACH ROW

8BEGIN

9UPDATE `genres`

10

 

SET

`g_books` = `g_books` + 1

11WHERE `g_id` = NEW.`g_id`;

12END;

13$$

14

15-- Реакция на обновление связи между книгами и жанрами:

16CREATE TRIGGER `g_has_books_on_m2m_b_g_upd`

17AFTER UPDATE

18ON `m2m_books_genres`

19FOR EACH ROW

20BEGIN

21UPDATE `genres`

22

SET

`g_books` = `g_books` - 1

23WHERE `g_id` = OLD.`g_id`;

24UPDATE `genres`

25

SET

`g_books` = `g_books` + 1

26WHERE `g_id` = NEW.`g_id`;

27END;

28$$

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

Пример 32: обеспечение консистентности данных

MySQL Решение 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 Стр: 306/545

Пример 32: обеспечение консистентности данных

Добавим две связи к жанру «Наука» (идентификатор жанра равен 4):

MySQL Решение 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 Решение 4.1.2.b (проверка работоспособности)

 

1

UPDATE

`m2m_books_genres`

 

2

SET

`b_id` =

3

 

 

 

3

WHERE

`b_id` =

1

 

 

 

4

AND

`g_id` =

4;

 

 

 

5

 

 

 

 

 

 

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 Стр: 307/545

Пример 32: обеспечение консистентности данных

Изменим в этих связях значения идентификаторов жанров, и идентификаторов книг одновременно:

 

MySQL

 

Решение 4.1.2.b (проверка работоспособности)

 

1

 

UPDATE

`m2m_books_genres`

 

2

 

SET

 

`b_id` = 1,

 

3

 

 

 

 

`g_id` = 4

 

4

 

WHERE

`b_id` = 3

 

5

 

 

 

AND

`g_id` = 5;

 

6

 

 

 

 

 

 

7

 

UPDATE

`m2m_books_genres`

 

8

 

SET

 

`b_id` = 2,

 

 

 

 

 

 

 

9`g_id` = 4

10WHERE `b_id` = 4

11AND `g_id` = 5;

g_id

g_name

g_books

1

Поэзия

2

2

Программирование

3

3

Психология

1

4

Наука

2

5

Классика

4

6

Фантастика

1

Удалим эти созданные для проверки работоспособности решения связи:

MySQL Решение 4.1.2.b (проверка работоспособности)

 

1

DELETE

FROM `m2m_books_genres`

 

2

WHERE

`b_id` = 1

 

 

 

3

AND

`g_id` = 4;

 

 

 

4

 

 

 

 

 

5

DELETE

FROM `m2m_books_genres`

 

6

WHERE

`b_id` = 2

 

 

 

7

AND

`g_id` = 4;

 

 

 

 

 

 

 

 

 

g_id

 

g_name

g_books

 

 

1

Поэзия

2

 

 

2

Программирование

3

 

 

3

Психология

1

 

 

4

Наука

0

 

 

5

Классика

4

 

 

6

Фантастика

1

 

Удалим книги с идентификаторами 1 и 2 (обе эти книги одновременно относятся к жанрам «Поэзия» и «Классика»):

MySQL Решение 4.1.2.b (проверка работоспособности)

1DELETE FROM `books`

2WHERE `b_id` IN (1, 2)

g_id

g_name

g_books

1

Поэзия

0

2

Программирование

3

3

Психология

1

4

Наука

0

5

Классика

2

6

Фантастика

1

Итак, решение для MySQL завершено и проверено.

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

Пример 32: обеспечение консистентности данных

Переходим к решению для MS SQL Server. Модифицируем таблицу и проинициализируем данные.

MS SQL Решение 4.1.2.b (модификация таблицы и инициализация данных)

1-- Модификация таблицы:

2ALTER TABLE [genres]

3ADD [g_books] INT NOT NULL DEFAULT 0;

4

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

6UPDATE [genres]

7

 

SET

[g_books] = [g_has_books]

8

 

FROM

[genres]

 

9

 

 

JOIN (SELECT

[g_id],

10

 

 

 

COUNT([b_id]) AS [g_has_books]

11

 

 

FROM

[m2m_books_genres]

12

 

 

GROUP

BY [g_id]) AS [prepared_data]

13ON [genres].[g_id] = [prepared_data].[g_id];

ВMS SQL Server триггеры активируются каскадными операциями, потому здесь будет достаточно создать триггеры только на таблице m2m_books_genres.

INSERT- и DELETE-триггеры достаточно просты: каждый из них подсчитывает

количество книг, добавленных к жанру или убранных у жанра, и изменяет счётчик книг у соответствующего жанра на полученное значение.

MS SQL Решение 4.1.2.b (триггеры для таблицы m2m_books_genres)

1-- Реакция на добавление связи между книгами и жанрами:

2CREATE TRIGGER [g_has_books_on_m2m_b_g_ins]

3ON [m2m_books_genres]

4AFTER INSERT

5AS

6UPDATE [genres]

7

 

SET

[g_books] = [g_books] +

[g_new_books]

8

 

FROM

[genres]

 

 

9

 

 

JOIN (SELECT

[g_id],

 

10

 

 

 

COUNT([b_id]) AS [g_new_books]

11

 

 

FROM

[inserted]

 

12

 

 

GROUP

BY [g_id])

AS [prepared_data]

13ON [genres].[g_id] = [prepared_data].[g_id];

14GO

15

16-- Реакция на обновление связи между книгами и жанрами:

17CREATE TRIGGER [g_has_books_on_m2m_b_g_upd]

18ON [m2m_books_genres]

19AFTER UPDATE

20AS

21UPDATE [genres]

22

 

SET

[g_books] = [g_books] + [delta]

23

 

FROM

[genres]

 

 

24

 

 

JOIN (SELECT [g_id],

 

25

 

 

 

SUM([delta]) AS [delta]

26

 

 

FROM

(SELECT

[g_id],

27

 

 

 

 

-COUNT([b_id]) AS [delta]

28

 

 

 

FROM

[deleted]

29

 

 

 

GROUP

BY [g_id]

30

 

 

 

UNION

 

31

 

 

 

SELECT

[g_id],

32

 

 

 

 

COUNT([b_id]) AS [delta]

33

 

 

 

FROM

[inserted]

34

 

 

 

GROUP

BY [g_id]) AS [raw_deltas]

35

 

 

GROUP

BY [g_id]) AS [ready_delta]

36ON [genres].[g_id] = [ready_delta].[g_id];

37GO

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