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

Пример 36: выборка и модификация данных с использованием хранимых функций

Решение 5.1.1 .с

1DROP FUNCTION IF EXISTS BOOKS DELTA;

2DELIMITER $$

3CREATE FUNCTION BOOKS DELTA() RETURNS INT

4BEGIN

5DECLARE old books count INT DEFAULT 0

6DECLARE new_books_count INT DEFAULT 0

7

8 SET old_books_count := (SELECT 'total' FROM 'books_statistics'); 9

10UPDATE 'books statistics'

11JOIN

12(SELECT IFNULL('total', 0 AS 'total',

13IFNULL('given', 0 AS 'given',

14IFNULL('total' - 'given', 0) AS 'rest'

15

FROM

(SELECT (SELECT SUM('b quantity')

 

16

 

FROM

'books')

AS 'total',

17

 

(SELECT COUNT('sb book')

 

18

 

FROM

'subscriptions'

 

19

 

WHERE

'sb is active' = 'Y') AS 'given')

20AS 'prepared data') AS 'src'

21SET 'books statistics' 'total' = 'src' 'total',

22'books statistics' 'given' = 'src' 'given',

23'books statistics' 'rest' = 'src' 'rest';

25SET new books count := (SELECT 'total' FROM 'books statistics');

26

27RETURN new books count - old books count ;

28END;

29$$

30DELIMITER ;

Решение для MySQL готово, а т.к. решения для MS SQL Server не существует, сразу переходим к Oracle, где полностью воспроизведём логику решения для

MySQL.

Oracl

і Решение 5.1.1.c (создание таблицы и инициализация данных)

|

e

 

 

 

 

 

1

-- Создание таблицы:

 

 

2

CREATE TABLE "books statistics"

 

 

3

(

 

 

 

 

4

 

"total" NUMBER(10 ,

 

 

5

 

"given" NUMBER(10 ,

 

 

6

 

"rest"

NUMBER(10

 

 

7

);

 

 

 

 

8

 

 

 

 

 

9

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

 

 

10

INSERT INTO "books statistics"

 

 

11

 

("total"

 

 

12

 

"given"

 

 

13

 

"rest"

 

 

14

SELECT "total",

 

 

15

 

"given",

 

 

16

 

("total" - "given") AS "rest"

 

17

FROM

(SELECT SUM("b quantity"

AS "total"

 

18

 

FROM

"books"

 

 

19

JOIN (SELECT COUNT "sb book"

AS "given"

 

20

 

FROM

"subscriptions"

 

 

21

 

WHERE

"sb is active" =

'Y')

 

22

ON 1 = 1;

 

 

 

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

Пример 36: выборка и модификация данных с использованием хранимых функций

Oracl

і

Решение 5.1.1.c (код функции)

I

 

e

 

 

 

 

 

 

 

1

CREATE OR REPLACE FUNCTION BOOKS DELTA RETURN NUMBER IS

2

PRAGMA AUTONOMOUS TRANSACTION;

 

3

old books count NUMBER;

 

 

4

new books count NUMBER;

 

 

5

BEGIN

 

 

 

 

 

6

SELECT "total" INTO old books count FROM "books statistics";

7

COMMIT;

 

 

 

 

8

 

 

 

 

 

 

9

UPDATE "books statistics"

 

 

10

SET

"total", "given", "rest"

=

11

(SELECT "total",

 

 

 

12

 

 

"given",

 

 

 

13

 

 

"total" - "given"

AS "rest"

14

FROM

 

(SELECT SUM "b quantity") AS "total"

15

 

 

FROM

"books")

 

 

16

JOIN (SELECT COUNT("sb book") AS "given"

17

 

 

FROM

"subscriptions"

18

 

 

WHERE

"sb is active" = 'Y')

19

ON 1 = 1 ;

 

 

 

20

COMMIT;

 

 

 

 

21

 

 

 

 

 

 

22

SELECT "total" INTO new books count FROM "books statistics";

23

COMMIT;

 

 

 

 

24

 

 

 

 

 

 

25

RETURN

new books count - old books count ;

26

END;

 

 

 

 

 

Поскольку у Oracle есть ряд ограничений на модификацию данных из кода хранимых функций, нам нужно реализовать две идеи:

выполнять функцию в автономной транзакции (строка 2);

подтверждать транзакцию в теле функции после выполнения каждого запроса (строки 7, 20, 23), т.к. в противном случае возникает ситуация взаимной блокировки между запросами на чтение и обновление данных).

Получить результат выполнения функции можно запросом.

Oracle Решение 5.1.1.c (запрос для получения результата работы функции)

1 SELECT BOOKS_DELTA FROM dual

На этом решение данной задачи завершено.

Задание 5.1.1.TSK.A: создать хранимую функцию, получающую на вход &идентификатор читателя и возвращающую список идентификаторов книг,

которые он уже прочитал и вернул в библиотеку.

& Задание 5.1.1.TSK.B: создать хранимую функцию, возвращающую список первого диапазона свободных значений автоинкрементируемых первичных ключей в указанной таблице (например, если в таблице есть первичные ключи

1,4, 8, то первый свободный диапазон — это значения 2 и 3).

& Задание 5.1.1.TSK.C: дополнить решение{355} задачи 5.1.1. b{352} для Oracle двумя вариантами реализации хранимой функции, в которых:

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

функция возвращает строку, в которой через запятую перечислены все значения свободных ключей.

Задание 5.1.1.TSK.D: создать хранимую функцию, актуализирующую данные в таблице subscriptions_ready (см. задачу 3.1.2. b{215}) и возвращающую число, показывающее изменение количества выдач книг.

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

Пример 37: контроль операций с данными с использованием хранимых функций

5.1.2.Пример 37: контроль операций с данными с использованием хранимых функций

ОЗадача 5.1.2.a{370}: создать хранимую функцию, автоматизирующую проверку условий задачи 4.2.1.a{315}, т.е. возвращающую значение 1 (все условия

выполнены) или -1, -2, -3 (если хотя бы одно условие нарушено, модуль числа соответствует номеру условия) в зависимости от того, выполняются ли следующие условия:

дата выдачи книги не может находиться в будущем;

дата возврата книги не может находиться в прошлом (только в случае вставки данных);

дата возврата книги не может быть меньше даты выдачи книги.

ОЗадача 5.1.2.b{373}: создать хранимую функцию, автоматизирующую проверку условий задачи 4.2.2.a{338}, т.е. возвращающую 1, если имя читателя

содержит хотя бы два слова и одну точку, и 0, если это условие нарушено.

Ожидаемый результат 5.1.2.a.

Функция возвращает 1, если все условия задачи выполнены, и 0, если хотя бы одно условие нарушено.

Ожидаемый результат 5.1.2.b.

Функция возвращает 1, если условие задачи выполнено, и 0, если оно нару-

шено.

Решение 5.1.2.a{370}.

Во всех трёх СУБД логика решения данной задачи будет одинакова: мы передадим в функцию три параметра (дату выдачи книги, дату возврата книги, признак обновления данных), проверим в теле функции выполнение условий и вернём соответствующее число.

MySQL I

Решение 5.1.2.a (код функции)

|

1DELIMITER $$

2CREATE FUNCTION CHECK SUBSCRIPTION DATES sb start DATE,

3

sb

finish

DATE,

4

is

insert

INT)

5RETURNS INT

6DETERMINISTIC

7BEGIN

8DECLARE result INT DEFAULT 1;

10 -- Блокировка выдач книг с датой выдачи в будущем

11IF sb start > CURDATE())

12THEN

13SET result = 1;

14END IF;

15

 

 

 

16

--

Блокировка выдач книг с датой возврата в прошлом.

17

IF

( sb finish <

AND is insert = 1 )

18THEN

19SET result = 2 ;

20END IF;

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

Пример 37: контроль операций с данными с использованием хранимых функций

MySQL I

Решение 5.1.2.a (код функции) (продолжение)

|

21-- Блокировка выдач книг с датой возврата меньшей, чем дата выдачи.

22IF sb finish < sb start)

23THEN

24SET result = 3

25END IF;

26

27RETURN result;

28END;

29$$

30DELIMITER ;

MySQL

Решение 5.1.2.a (код для проверки работы функции)

1SELECT CHECK

2SELECT CHECK

3_

CHECK

4SELECT _

5SELECT CHECK

6_

CHECK

7SELECT _

8SELECT CHECK

SUBSCRIPTION DATES('2025-01-01', '2026-01- SUBSCRIPTION DATES('2025-01-01', '2026-01-

01'

'2006-01- SUBSCRIPTION DATES('2005-01-01' 01'

SUBSCRIPTION DATES('2005-01-01', '2006-01-

01'

'2004-01- SUBSCRIPTION DATES('2005-01-01' 01'

SUBSCRIPTION DATES('2005-01-01', '2004-01-

,1);

,0);

,1);

,0);

,1);

,0);

MS SQL I

Решение 5.1.2.a (код функции)

|

1

CREATE FUNCTION CHECK SUBSCRIPTION DATES @sb start DATE,

2

 

 

@sb finish DATE,

3

 

 

@is insert INT)

4RETURNS INT

5WITH SCHEMABINDING

6AS

7BEGIN

8DECLARE @result INT = 1;

10-- Блокировка выдач книг с датой выдачи в будущем

11IF @sb start > CONVERT(date, GETDATE()))

12BEGIN

13SET @result = - 1

14END;

15 16 -- Блокировка выдач книг с датой возврата в прошлом.

17 IF ( @sb finish < CONVERT(date, GETDATE())) AND (@is insert = 1))

18BEGIN

19SET @result = - 2

20END;

21 22 -- Блокировка выдач книг с датой возврата меньшей, чем дата выдачи.

23IF @sb finish < @sb start

24BEGIN

25SET @result = - 3

26END;

27

28RETURN @result

29END;

Oracl

і

Решение 5.1.2.a (код функции)

|

 

e

 

 

 

 

 

1

CREATE OR REPLACE FUNCTION CHECK SUBSCRIPTION DATES

sb start DATE,

2

 

 

 

sb finish DATE,

3

 

 

 

is insert INT)

4

RETURN NUMBER DETERMINISTIC IS

 

 

5

result value NUMBER := 1;

 

 

6

BEGIN

 

 

7

-- Блокировка выдач книг с датой выдачи в будущем

 

8

IF (sb start > TRUNC(SYSDATE))

 

9

 

THEN

 

 

10

 

result value := -1;

 

 

11

 

END IF;

 

 

12

 

 

 

 

13-- Блокировка выдач книг с датой возврата в прошлом.

14IF ( sb finish < TRUNC(SYSDATE)) AND (is insert = 1))

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

Пример 37: контроль операций с данными с использованием хранимых функций

15THEN

16result value := -2;

17END IF;

18

19-- Блокировка выдач книг с датой возврата меньшей, чем дата выдачи.

20IF (sb finish < sb start)

21THEN

22result value := -3;

23END IF;

24

25RETURN result value

26END;

Сам код функций примитивен и не нуждается в пояснениях, но стоит отметить

отличие логики представленного здесь решения от логики решения{315} задачи

4.2.1. a<315>.

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

Здесь же мы в решениях для всех трёх СУБД возвращаем результат лишь в самом конце тела функции, потому провал каждой следующей проверки будет аннулировать признак провала предыдущей проверки.

Если такое поведение окажется неудобным, всегда можно переписать код,

Oracle

1

2

3

4

5

6

7

8

9

10

і

Решение 5.1.2.a (код для проверки работы функции)

|

SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2025-01-01' 'YYYY-MM-DD') TO_DATE('2026-01-01', 'YYYY-MM-DD'), 1 FROM dual;

SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2025-01-01' 'YYYY-MM-DD') TO DATE('2026-01-01', 'YYYY-MM-DD'), 0 FROM dual;

SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2005-01-01' 'YYYY-MM-DD') TO_DATE('2006-01-01', 'YYYY-MM-DD'), 1 FROM dual;

SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2005-01-01' 'YYYY-MM-DD' ) TO DATE('2006-01-01', 'YYYY-MM-DD'), 0 FROM dual;

11SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2005-01-01' 'YYYY-MM-DD' )

12TO_DATE('2004-01-01', 'YYYY-MM-DD'), 1 FROM dual;

13SELECT CHECK_SUBSCRIPTION_DATES(TO_DATE('2005-01-01' 'YYYY-MM-DD' )

14TO DATE('2004-01-01', 'YYYY-MM-DD'), 0 FROM dual;

возвращая результат по факту провала первой же проверки, обнаружившей нарушение условия задачи.

На этом решение данной задачи завершено.

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

Пример 37: контроль операций с данными с использованием хранимых функций

'ЬАЙ'

Решение 5.1.2.b{370}.

По сравнению с предыдущей задачей здесь всё будет ещё проще: нужно просто «обернуть» в функцию две проверки, на основе результата которых возвратить 1 или 0.

Только в решении для MS SQL Server будет одна необычная деталь: мы вынуждены использовать промежуточную переменную и возвращать её значение в самом конце тела функции, т.к. данная СУБД требует, чтобы последним выражением внутри хранимой функции был оператор RETURN.

MySQL

Решение 5.1.2.b (код функции) [

 

1

DROP ... FUNCTION. IF

EXISTS CHECK_SUBSCRIBER_NAME;

2

DELIMITER $$

 

 

3

CREATE FUNCTION CHECK_SUBSCRIBER_NAME

subscriber_name VARCHAR(150 )

4RETURNS

5INT DETERMINISTIC

6BEGIN

7IF ((CAST subscriber_name AS CHAR CHARACTER SET cp1251 REGEXP

8CAST('Л[a-zA-Za-яА-ЯёЁХ'-]+([лa-zA-Zа-яА-ЯёЁ\'-]+[a-zA-Za-HA-

9ЯёЁ\'.-]+){1,}$' AS CHAR CHARACTER SET cp1251)) = 0)

10

OR (LOCATE('.',

subscriber_name) = 0)

11THEN

12RETURN 0; ELSE

13RETURN 1; END IF;

14END; $$ DELIMITER ;

16MySQL Решение 5.1.2.b (код для проверки работы функции)

17

1

SELECT CHECK_SUBSCRIBER_NAME('Иванов');

 

2

SELECTCHECK_SUBSCRIBER_NAME('Иванов И' );

3

SELECT

CHECK SUBSCRIBER NAME('Иванов И.');

MS SQL Решение 5.1.2.b (код функции)

1CREATE FUNCTION CHECK SUBSCRIBER NAME @subscriber name NVARCHAR 150))

2RETURNS INT

3WITH SCHEMABINDING

4AS

5BEGIN

6DECLARE @result INT = -1;

7

8IF ((CHARINDEX(' ', LTRIM(RTRIM @subscriber name )) = 0) OR

9(CHARINDEX('.', @subscriber name = 0 )

10BEGIN

11SET @result = 0;

12END

13ELSE

14BEGIN

15SET @result = 1;

16END;

17

18RETURN @result

19END;

20GO

MS SQL

Решение 5.1.2.b (код для проверки работы функции)

1SELECT dbo.CHECK_SUBSCRIBER_NAME('Иванов');

2SELECT dbo.CHECK_SUBSCRIBER_NAME('Иванов И' );

3SELECT dbo.CHECK SUBSCRIBER NAME('Иванов И.' );

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

Пример 37: контроль операций с данными с использованием хранимых функций

Oracl

і

Решение 5.1.2.b (код функции)

|

 

 

e

 

 

 

 

 

 

 

1

CREATE OR REPLACE

 

 

 

2

FUNCTION CHECK SUBSCRIBER NAME (subscriber name NVARCHAR2)

3

RETURN NUMBER DETERMINISTIC IS

 

 

4

BEGIN

 

 

 

5

IF ((NOT REGEXP LIKE subscriber name, 'Л[a-zA-Zа-яA-ЯёЁ''-]+([Лa-zA-Zа-яA-

6

ЯёЁ' '-^[a-zA-Za-яА-ЯёЁ' ' .-]+){1,}$'))

 

7

 

OR (INSTRC subscriber name

'.', 1, 1

= 0))

8

 

THEN

 

 

 

9

 

RETURN 0;

 

 

 

10

 

ELSE

 

 

 

11

 

RETURN 1;

 

 

 

12

 

END IF;

 

 

 

13

END;

 

 

 

 

Oracle

Решение 5.1.2.b (код для

 

 

 

1

SELECT CHECK_SUBSCRIBER_NAME(N'Иванов') FROM dual;

2

SELECT CHECK_SUBSCRIBER_NAME(N'Иванов И') FROM dual;

3

SELECT CHECK SUBSCRIBER NAME(N'Иванов И.') FROM dual;

 

На этом решение данной задачи завершено.

 

Задание 5.1.2.TSK.A: переписать решения*315*, *338} задач 4.2.1.a*315} и 4.2.2. a*338} с использованием хранимых функций, созданных в решениях*37^ *373} задач 5.1.2.a*370} и 5.1.2.b*370} соответственно.

Задание 5.1.2.TSK.B: создать хранимую функцию, автоматизирующую &проверку условий задачи 4.2.1.b*315}, т.е. возвращающую 1, если у читателя на

руках сейчас менее десяти книг, и 0 в противном случае.

& Задание 5.1.2.TSK.C: создать хранимую функцию, автоматизирующую проверку условий задачи 4.2.2.b*338}, т.е. возвращающую 1, если книга издана менее ста лет назад, и 0 в противном случае.

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

Пример 38: выполнение динамических запросов с помощью хранимых процедур

5.2. Использование хранимых процедур

5.2.1.Пример 38: выполнение динамических запросов с помощью хранимых процедур

ОЗадача 5.2.1.a{375}: создать хранимую процедуру, устраняющую промежутки в последовательности значений первичного ключа для заданной таблицы

(например, если значения первичного ключа были равны 4, 7, 9, то после выполнения хранимой процедуры они станут равны 1,2, 3).

Задача 5.2.1.b{382}: создать хранимую процедуру, формирующую список представлений, триггеров и внешних ключей для указанной таблицы.

Ожидаемый результат 5.2.1.a.

После выполнения хранимой процедуры, в которую первыми двумя параметрами передано имя обрабатываемой таблицы и её первичного ключа, значения первичного ключа в таблице принимают вид 1, 2, 3, ... (т.е. начинаются с 1 и идут без пропусков), а сама хранимая процедура возвращает информацию о том, сколько значений первичного ключа было изменено.

Ожидаемый результат 5.2.1.b.

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

object_type

object_name

 

foreign_key

FK_1

 

foreign key

FK 2

 

trigger

TRG_1

 

trigger

TRG 2

 

view

VIEW 1

 

view

VIEW_2

 

 

'Vf Решение 5.2.1 .a{375}.

Т радиционно начнём решение задачи с MySQL. В отличие от хранимых функций в хранимые процедуры данной СУБД позволяют формировать и выполнять динамические SQL-запросы.

Прежде, чем начать рассмотрение кода хранимой процедуры, сделаем два важных замечания:

выполнять динамические запросы и помещать результаты их работы в переменные можно только с использованием т.н. «сессионных переменных20» (имена которых начинаются со знака @);

имена переменных, в которые помещается результат выполнения запроса, не должны совпадать с именами параметров хранимой процедуры (и, в некоторых случаях, с именами полей, возвращаемых запросом21).

20http://stackoverflow.com/questions/1009954/mysql-variable-vs-variable-whats-the-difference

21http://dba.stackexchange.com/questions/112285/select-into-variable-results-in-null-or-idk

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

Пример 38: выполнение динамических запросов с помощью хранимых процедур

MySQL

Решение 5.2.1.a (код процедуры) [ DROP PROCEDURE COMPACT_KEYS; DELIMITER $$

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

CREATE PROCEDURE

COMPACT_KEYS (IN

table_name VARCHAR'150 ,

3

 

 

 

 

IN pk_name

VARCHAR(150 ,

 

 

 

 

 

 

OUT

keys_changed INT)

 

 

4

 

 

 

 

 

 

 

BEGIN

 

 

 

 

 

 

 

 

 

 

 

5

 

 

 

 

 

 

 

 

 

 

 

 

 

SET keys_changed = 0;

 

 

 

 

 

 

 

 

 

 

6

 

 

 

 

 

 

 

 

 

 

 

 

SELECT

 

 

 

 

 

 

 

 

 

 

 

7

 

 

 

 

 

 

 

 

 

 

 

 

 

CONCAT('Point 1.

table_name =

', table_name,

',

pk_name

8

 

=

 

 

',

 

 

 

 

 

 

 

 

 

 

9

 

 

 

 

 

 

 

 

 

 

 

 

 

 

pk_name,

', keys_changed =

', IFNULL(keys_changed 'NULL'));

10

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

11

 

SET

@empty_key_query =

 

 

 

 

 

 

 

 

 

12

 

 

 

 

 

 

 

 

 

 

 

CONCAT('SELECT MIN('empty_key') AS

 

 

'empty_key'

INTO

 

13

 

 

 

 

@empty_key_value

 

 

 

 

 

 

 

 

 

 

 

14

 

 

 

 

 

 

 

 

 

 

 

15

 

 

FROM (SELECT 'left'.'',

pk_name

'' + 1 AS 'empty_key'

 

 

 

FROM '',

 

table_name,

'' AS 'left'

 

 

16

 

 

 

 

 

 

 

 

LEFT OUTER JOIN '',

table_name '' AS 'right'

17

 

 

 

 

 

 

 

 

 

ON 'left'.'',

pk_name

 

 

18

 

 

 

 

 

 

 

 

 

 

 

 

''

+ 1 =

 

'right'.'',

pk_name

19

 

 

 

 

 

 

 

WHERE 'right'.'',

pk_name

'' IS NULL

 

 

 

 

20

 

 

 

 

 

 

 

 

UNION

 

 

 

 

 

 

 

 

 

 

 

21

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SELECT

1 AS 'empty_key'

 

 

 

 

 

 

 

 

 

22

 

 

 

 

 

 

 

 

 

 

 

 

 

FROM ' ' , table_name,

''

 

 

 

 

 

 

 

 

23

 

 

 

 

 

 

 

 

 

 

 

 

WHERE

NOT EXISTS(SELECT '',

pk_name,''

 

 

 

 

24

 

 

 

 

 

 

 

 

 

 

FROM '',

 

table_name,

''

 

 

25

 

 

 

 

 

 

 

 

 

 

 

WHERE

'',

pk_name,''

 

 

 

= 1)) AS

26

 

 

 

 

 

 

 

 

 

 

 

'prepared_data'

 

 

 

 

 

27

 

 

 

 

 

 

 

 

 

 

 

WHERE 'empty_key' < (SELECT MAX('',

pk_name, '')

 

 

28

 

 

 

 

 

 

 

 

FROM '',

 

table_name, '')');

 

 

29

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

30

 

SET

 

@max_key_query

=

 

 

 

 

 

 

 

31

 

 

 

 

 

 

 

 

 

 

CONCAT('SELECT MAX('', pk_name

'')

 

 

 

 

 

 

32

 

 

 

 

 

 

 

 

INTO

 

 

@max_key_value FROM '',

table_name,

''');

33

 

 

 

 

SELECT CONCAT('Point 2.

 

 

 

empty_key_query =

',

 

34

 

 

 

 

 

 

 

 

@empty_key_query,

 

 

 

 

 

 

35

 

 

 

 

 

 

 

 

 

 

 

'max_key_query =

 

',

 

@max_key_queryl;

 

 

36

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

37

 

PREPARE empty_key_stmt FROM @empty_key_query;

 

 

 

 

38

 

 

 

 

 

 

PREPARE max_key_stmt

FROM

 

@max_key_query;

 

 

39

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

40

 

while_loop: LOOP

 

 

 

 

 

 

 

 

 

 

41

 

 

 

 

 

 

 

 

 

 

 

 

EXE CUTE emp ty_key_s tmt;

 

 

 

 

 

 

 

 

 

42

 

 

 

 

 

 

 

 

 

 

 

SELECT CONCAT('Point 3.

 

 

 

 

@empty_key_value =

',

43

 

 

 

 

 

@empty_key_value);

 

 

 

 

 

 

 

 

 

 

 

44

 

 

 

 

 

 

 

 

 

 

 

 

 

 

45IF @empty_key_value IS NULL)

46THEN LEAVE while_loop END IF;

48

EXECUTE max_key_stmt

49

SET

@update_key_query =

50CONCAT('UPDATE '', table_name, '' SET '',pk_name,

51'' = @empty_key_value WHERE '', pk_name, '' = ', @max_key_value ;

52SELECT CONCAT('Point 4. @update_key_query = ', @update_key_query ;

54

55

56

57

58

59

60

61

62

63

64

65

PREPARE update_key_stmt FROM @update_key_query; EXECUTE update_key_stmt;

DEALLOCATE PREPARE update_key_stmt;

SET keys_changed = keys_changed + 1

ITERATE while_loop;

END LOOP while_loop;

DEALLOCATE

PREPARE max_key_stmt;

DEALLOCATE

PREPARE

empty_key_stmt

END;

$$

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

Пример 38: выполнение динамических запросов с помощью хранимых процедур

DELIMITER ;

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