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

Пример 31: обновление кэширующих таблиц и полей

В корректности работы полученного решения вы можете убедиться, выполнив следующие запросы (они выполнены пошагово с пояснениями и показом результатов в решении для MySQL):

Oracle Решение 4.1.1.b (запросы для проверки работоспособности)

1ALTER TRIGGER "TRG_subscribers_s_id" DISABLE;

2ALTER TRIGGER "TRG_subscriptions_sb_id" DISABLE;

3

4-- Добавление читателя:

5INSERT 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 Стр: 290/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 таким образом, чтобы оно учитывало изменения в таблице subscriptions, вызванные операцией каскадного удаления (при удалении книг). Убедиться, что решения для MS SQL Server и Oracle не требуют такой доработки.

Задание 4.1.1.TSK.E: доработать решение{281} задачи 4.1.1.b{272} для MySQL таким образом, чтобы оно учитывало изменения в таблице subscriptions, вызванные операцией каскадного удаления (при удалении книг). Убедиться, что решения для MS SQL Server и Oracle не требуют такой доработки.

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

Решение 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 первые два шага выполняются с помощью следующих запросов.

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

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

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

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

2ALTER TABLE `subscribers`

3ADD COLUMN `s_books` INT(11) NOT NULL DEFAULT 0 AFTER `s_name`;

4

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

6UPDATE `subscribers`

7JOIN (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 Решение 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

31DELIMITER ;

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

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

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

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

1 DELIMITER $$

2

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

4CREATE TRIGGER `s_has_books_on_subscriptions_upd`

5AFTER UPDATE

6ON `subscriptions`

7FOR EACH ROW

8BEGIN

9

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

11IF ((OLD.`sb_subscriber` = NEW.`sb_subscriber`) AND

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

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

14UPDATE `subscribers`

15

SET

`s_books` = `s_books` - 1

16WHERE `s_id` = OLD.`sb_subscriber`;

17END IF;

18

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

20IF ((OLD.`sb_subscriber` = NEW.`sb_subscriber`) AND

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

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

23UPDATE `subscribers`

24

SET

`s_books` = `s_books` + 1

25WHERE `s_id` = OLD.`sb_subscriber`;

26END IF;

27

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

29IF ((OLD.`sb_subscriber` != NEW.`sb_subscriber`) AND

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

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

32UPDATE `subscribers`

33

 

SET

`s_books` = `s_books` - 1

34WHERE `s_id` = OLD.`sb_subscriber`;

35UPDATE `subscribers`

36

 

SET

`s_books` = `s_books` + 1

37WHERE `s_id` = NEW.`sb_subscriber`;

38END IF;

39

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

41IF ((OLD.`sb_subscriber` != NEW.`sb_subscriber`) AND

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

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

44UPDATE `subscribers`

45

 

SET

`s_books` = `s_books` - 1

46WHERE `s_id` = OLD.`sb_subscriber`;

47END IF;

48

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

50IF ((OLD.`sb_subscriber` != NEW.`sb_subscriber`) AND

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

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

53UPDATE `subscribers`

54

 

SET

`s_books` = `s_books` + 1

 

 

 

 

55WHERE `s_id` = NEW.`sb_subscriber`;

56END IF;

57

58END;

59$$

60

61 DELIMITER ;

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

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 294/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{240}, 4.1.1.TSK.D{291}, 4.1.1.TSK.E{291}. Напомним, что 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 Стр: 295/545

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

Проверим реакцию на добавление и удаление выдач книг. Добавим Иванову И.И. активную выдачу, а Петрову П.П. неактивную:

 

MySQL

 

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

 

1

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 (проверка работоспособности)

 

1

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

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

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

MySQL Решение 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

 

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

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

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

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

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

3ADD [s_books] INT NOT NULL DEFAULT 0;

4

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

6UPDATE [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 Стр: 298/545

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

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

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