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

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

Пример 45: управление транзакциями в триггерах, хранимых функциях и процедурах

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

1CREATE FUNCTION NO_AUTOCOMMITT()

2RETURNS INT

3WITH SCHEMABINDING

4AS

5BEGIN

6DECLARE @autocommit INT;

7

8IF (@@TRANCOUNT = 0 AND (@@OPTIONS & 2 = 0))

9BEGIN

10SET @autocommit = 1;

11END

12ELSE IF (@@TRANCOUNT = 0 AND (@@OPTIONS & 2 = 2))

13BEGIN

14SET @autocommit = 0;

15END

16ELSE IF (@@OPTIONS & 2 = 0)

17BEGIN

18SET @autocommit = 1;

19END

20ELSE

21BEGIN

22SET @autocommit = 0;

23END;

24

25IF (@autocommit = 1)

26BEGIN

27-- В функциях MS SQL Server нельзя использовать RAISEERROR!

28-- RAISERROR ('Please, turn the autocommit off.', 16, 1);

29

30-- Обходной путь по порождению исключения:

31RETURN CAST('Please, turn the autocommit off.' AS INT);

32

33-- Отменить транзакцию из функции в MS SQL Server тоже нельзя.

34-- ROLLBACK TRANSACTION;

35END;

36

 

 

37

 

-- Тут может быть какой-то полезный код :).

38

 

 

39RETURN 0;

40END;

41GO

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

MS SQL Решение 6.2.3.b (код для проверки работоспособности решения)

1SET IMPLICIT_TRANSACTIONS OFF;

2SELECT dbo.NO_AUTOCOMMITT();

3

4SET IMPLICIT_TRANSACTIONS ON;

5SELECT dbo.NO_AUTOCOMMITT();

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

Пример 45: управление транзакциями в триггерах, хранимых функциях и процедурах

Решение для Oracle выглядит следующим образом. Да, именно так и выглядит, т.к. в Oracle нет такого явления, как автоподтверждение транзакций — этот эффект может быть реализован некоторыми средствами работы с СУБД, но сама СУБД всегда ждёт явного COMMITT или ROLLBACK.

Oracle

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

1CREATE FUNCTION NO_AUTOCOMMITT

2RETURN INT

3DETERMINISTIC

4IS

5BEGIN

6DBMS_OUTPUT.PUT_LINE('Have a nice day :)');

7RETURN 1;

8END;

Проверить работоспособность и корректность представленного решения можно выполнением следующего кода.

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

1SET SERVEROUTPUT ON;

2SELECT NO_AUTOCOMMITT FROM DUAL;

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

Решение 6.2.3.c{465}.

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

В MySQL таким уровнем является READ UNCOMMITTED, в MS SQL Server —

тоже READ UNCOMMITTED или SNAPSHOT (но SNAPSHOT может приводить к допол-

нительным расходам ресурсов), в Oracle чтение данных всегда происходит в независимом режиме, потому в этой СУБД можно использовать READ COMMITTED (тем более, что READ UNCOMMITTED в Oracle нет).

Решение для MySQL выглядит следующим образом.

MySQL Решение 6.2.3.c (код процедуры)

1DELIMITER $$

2CREATE PROCEDURE COUNT_ROWS(IN table_name VARCHAR(150),

3

 

OUT rows_in_table INT)

 

 

 

4BEGIN

5SET SESSION TRANSACTION

6ISOLATION LEVEL READ UNCOMMITTED;

7

8SET @count_query =

9CONCAT('SELECT COUNT(1) INTO @rows_found

10FROM ', table_name);

11

12PREPARE count_stmt FROM @count_query;

13EXECUTE count_stmt;

14DEALLOCATE PREPARE count_stmt;

15

16SET rows_in_table := @rows_found;

17END;

18$$

19DELIMITER ;

Проверить работоспособность и корректность представленного решения можно выполнением следующего кода.

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

Пример 45: управление транзакциями в триггерах, хранимых функциях и процедурах

MySQL Решение 6.2.3.c (код для проверки работоспособности решения)

1CALL COUNT_ROWS('subscriptions', @rows_in_table);

2SELECT @rows_in_table;

Решение для MS SQL Server выглядит следующим образом.

MS SQL Решение 6.2.3.c (код процедуры)

1

 

CREATE PROCEDURE COUNT_ROWS

2

 

@table_name NVARCHAR(150),

3

 

@rows_in_table INT OUTPUT

4AS

5DECLARE @count_query NVARCHAR(1000) = '';

6

7SET TRANSACTION ISOLATION

8LEVEL READ UNCOMMITTED;

9

10SET @count_query =

11CONCAT('SET @rows_f = (SELECT COUNT(1) FROM [', @table_name, '])');

12EXECUTE sp_executesql @count_query,

13

 

N'@rows_f INT OUT',

14

 

@rows_in_table OUTPUT;

15

 

GO

 

 

 

Проверить работоспособность и корректность представленного решения можно выполнением следующего кода.

MySQL Решение 6.2.3.c (код для проверки работоспособности решения)

1DECLARE @res INT;

2EXECUTE COUNT_ROWS 'subscriptions', @res OUTPUT;

3SELECT @res;

Решение для Oracle выглядит следующим образом.

Oracle Решение 6.2.3.c (код процедуры)

1

 

CREATE PROCEDURE COUNT_ROWS (table_name IN

VARCHAR,

2

 

rows_in_table

OUT NUMBER) AS

3count_query VARCHAR(1000) := '';

4BEGIN

5

6EXECUTE IMMEDIATE 'ALTER SESSION SET

7ISOLATION_LEVEL = READ COMMITTED';

8

9count_query :=

10'SELECT COUNT(1) FROM "' || table_name || '"';

11EXECUTE IMMEDIATE count_query INTO rows_in_table;

12END;

13/

Проверить работоспособность и корректность представленного решения можно выполнением следующего кода.

Oracle Решение 6.2.3.c (код для проверки работоспособности решения)

1DECLARE

2res NUMBER;

3BEGIN

4COUNT_ROWS('subscriptions', res);

5DBMS_OUTPUT.PUT_LINE('Rows: ' || res);

6END;

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

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

Пример 45: управление транзакциями в триггерах, хранимых функциях и процедурах

Задание 6.2.3.TSK.A: создать на таблице subscriptions триггер, определяющий уровень изолированности транзакции, в котором сейчас проходит операция обновления, и отменяющий операцию, если уровень изолированности транзакции отличен от REPEATABLE READ.

Задание 6.2.3.TSK.B: создать хранимую функцию, порождающую исключительную ситуацию в случае, если выполняются оба условия:

режим автоподтверждения транзакций выключен;

функция запущена из вложенной транзакции.

Подсказка: эта задача имеет решение только для MS SQL Server.

Задание 6.2.3.TSK.C: создать хранимую процедуру, выполняющую подсчёт количества записей в указанной таблице таким образом, чтобы она возвращала максимально корректные данные, даже если для достижения этого результата придётся пожертвовать производительностью.

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

Пример 46: формирование и анализ иерархических структур

Раздел 7: Решение типичных задач и выполнение типичных операций

7.1. Работа с иерархическими и связанными структурами

7.1.1. Пример 46: формирование и анализ иерархических структур

Для решения задач из данного примера нам понадобится новая таблица, которую мы создадим в базе данных «Исследование». Эта таблица будет хранить дерево элементов (допустим, что это будет древовидная структура сайта нашей гипотетической библиотеки).

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

dm MySQL

dm SQLServ er2012

dm Oracle

 

site_pages

«column»

*PK

sp_id: INT

FK

sp_parent: INT

 

sp_name: VARCHAR(200)

«FK»

+FK_site_pages_site_pages(INT)

«PK»

+PK_site_pages(INT)

0..*

 

1

 

(sp_parent = sp_id)

 

«FK»

+PK_site_pages

+FK_site_pages_site_pages

 

 

site_pages

«column»

*PK

sp_id: int

FK

sp_parent: int

 

sp_name: nvarchar(200)

«FK»

+FK_site_pages_site_pages(int)

 

«PK»

 

 

+

PK_site_pages(int)

 

 

0..*

 

1

 

(sp_parent = sp_id)

 

 

«FK»

 

 

+FK_site_pages_site_pages

+PK_site_pages

 

 

site_pages

«column» *PK sp_id: NUMBER(10) FK sp_parent: NUMBER(10) sp_name: NVARCHAR2(200)

«FK»

+FK_site_pages_site_pages(NUMBER)

«PK»

+PK_site_pages(NUMBER)

0..*

 

1

(sp_parent = sp_id)

 

«FK»

+PK_site_pages

 

+FK_site_pages_site_pages

 

 

 

MySQL

MS SQL Server

Oracle

Рисунок 7.а — Таблица site_pages во всех трёх СУБД

Сохраним в таблице site_pages следующий набор данных, визуально представленный на рисунке 7.b.

sp_id

sp_parent

sp_name

1

NULL

Главная

2

1

Читателям

3

1

Спонсорам

4

1

Рекламодателям

5

2

Новости

6

2

Статистика

7

3

Предложения

8

3

Истории успеха

9

4

Акции

10

1

Контакты

11

3

Документы

12

6

Текущая

13

6

Архивная

14

6

Неофициальная

39 http://www.amazon.com/dp/1558609202/

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

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