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

Пример 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: обеспечение консистентности данных

MySQL

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

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

DELIMITER ....................... $$

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

CREATE TRIGGER 's_has_books_on_subscriptions_upd' AFTER UPDATE

ON 'subscriptions'

 

FOR EACH ROW

 

BEGIN

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

IF

((OLD.'sb_subscriber' = NEW.'sb_subscriber') AND

 

(OLD.'sb_is_active' = 'Y') AND

 

(NEW.'sb_is_active' = 'N')) THEN

UPDATE 'subscribers'

SET

's_books' = 's_books' - 1

WHERE

's_id' = OLD.'sb_subscriber';

END IF;

 

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

IF

((OLD.'sb_subscriber' = NEW.'sb_subscriber') AND

 

(OLD.'sb_is_active' = 'N') AND

(NEW.'sb_is_active' = 'Y')) THEN

UPDATE 'subscribers'

SET

's_books' = 's_books' + 1

WHERE

's_id' = OLD.'sb_subscriber';

END IF;

 

— C) Читатели разные, Y -> Y

IF ((OLD.'sb_subscriber' ! = NEW.'sb_subscriber') AND

(OLD.'sb_is_active' = 'Y') AND

(NEW.'sb_is_active' = 'Y')) THEN

UPDATE 'subscribers'

SET

's_books' = 's_books' - 1

WHERE

's_id' = OLD.'sb_subscriber';

UPDATE 'subscribers'

SET

's_books' = 's_books' + 1

WHERE

's_id' = NEW.'sb_subscriber';

END IF;

 

— D) Читатели разные, Y -> N

IF ((OLD.'sb_subscriber' != NEW.'sb_subscriber') AND

(OLD.'sb_is_active' = 'Y') AND

(NEW.'sb_is_active' = 'N')) THEN

UPDATE 'subscribers'

SET 's_books' = 's_books' - 1

WHERE 's_id' = OLD.'sb_subscriber';

END IF;

48— E) Читатели разные, N -> Y

49IF ((OLD.'sb_subscriber' != NEW.'sb_subscriber') AND (OLD.'sb_is_active'

50

51

52

53

54

55

56

57

58

59

60

61

 

 

= 'N') AND

(NEW.'sb_is_active' = 'Y')) THEN

UPDATE 'subscribers'

SET

's_books' =

's_books' + 1

WHERE

's_id' = NEW

'sb_subscriber';

END IF;

 

 

END;

$$

DELIMITER ;

Изобразим рассмотренные ситуации графически.

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 311/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