Иван Задворьев - Язык PL/SQL

Здесь есть возможность читать онлайн «Иван Задворьев - Язык PL/SQL» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2018, Издательство: Array SelfPub.ru, Жанр: Программирование, Базы данных, , на русском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Язык PL/SQL: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Язык PL/SQL»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

В учебно-методическом пособии рассматриваются основы языка программирования PL/SQL, реализованного в системе управления базами данных Oracle Database Server. Приводятся сведения о поддерживаемых типах данных, структуре программ PL/SQL и выполнении SQL-предложений в них. Отдельно рассмотрено создание хранимых в базах данных Oracle программ PL/SQL – процедур, функций, пакетов и триггеров.

Язык PL/SQL — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Язык PL/SQL», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

DECLARE

CURSOR c_balances IS SELECT * FROM balances;

l_client_type VARCHAR2(100);

l_new_year_coeff NUMBER;

BEGIN

FOR rec_balance IN c_balances LOOP

– определяем тип клиента (активный / не активный)

l_client_type := getClientType(rec_balance); – вызов длится 1 минуту

CASE l_client_type

WHEN 'active' THEN l_new_year_coeff := 1.05;

WHEN 'non-actve' THEN l_new_year_coeff := 1.01;

END CASE;

UPDATE balances SET balance = rec_balance.balance*l_new_year_coeff

WHERE balances.client_id = rec_balance.client_id;

END LOOP;

COMMIT;

END;

Если в базе данных 100 клиентов, то анонимный блок будет выполняться 100 минут. Пусть на 30-й минуте с момента начала выполнения блока клиент одной из еще не считанной из курсора строк (для определенности, пусть 70-й по счету) вносит платеж и его баланс увеличивается на сумму платежа. Транзакция увеличения баланса этого клиента фиксируется (изменить 70-ю строку этой транзакции можно, строка не блокирована, так как ней пока еще не обращались в ходе «подарочного» расчета).

Когда на 70-й минуте курсор c_balances дочитает до этой строки, то обнаружится, что строка с момента начала выполнения SQL-запроса курсора была изменена зафиксированной транзакцией и для обеспечения согласованности чтения восстановит ее предыдущую версию (с балансом без нового платежа). Соответственно, после выполнения команды UPDATE для этого клиента будет проставлена увеличенная на один или пять процентов сумма старого (без учета нового платежа) баланса.

В теории баз данных это называется явлением пропавшего обновления (lost update phenomena) – пропало отражение на балансе нового платежа, оно было перезаписано ранее считанными данными. В данном случае более правильная формулировка – перезаписано данными, восстановленными по состоянию, которое было ранее. Ведь собственно считывалась-то 70-я строка из курсора уже после поступления нового платежа, просто в ходе ее считывания для обеспечения согласованности произошло восстановление старой версии строки.

Чтобы не сталкиваться с проблемой пропавшего обновления, необходимо на все время «подарочной» транзакции заблокировать данные балансов от изменений. Для этого в курсоре c_balances следует записать не просто SQL-запрос, а SQL-запрос с блокировкой отбираемых строк:

CURSOR c_balances IS SELECT * FROM balances FOR UPDATE;

Посмотрим, что изменится в этом случае. Для запросов с опцией FOR UPDATE блокировка на отбираемые строки накладывается в ходе открытия курсора командой OPEN, еще до считывания первой строки командой FETCH. Поэтому если курсор с FOR UPDATE успешно открылся, то это значит, что все отбираемые SQL-запросом курсора строки уже заблокированы. Если какие-то строки с балансами заблокированы другими активными транзакциями, то наш процесс во время открытия курсора с SELECT FOR UPDATE будет ждать снятия этих блокировок.

После успешного открытия курсора c_balances с FOR UPDATE строки всех балансов будут заблокированы нашей транзакцией и до снятия этой блокировки только она может их изменять. Все другие транзакции, которые будут вносить платежи и изменять (увеличивать) балансы, сами будут переходить в режим ожидания снятия блокировки с балансов, установленной нашей «подарочной» транзакцией.

Как только на всех балансах будут отражены подарочные суммы и цикл считывания и обработки строк курсора c_balances завершится, в конце анонимного блока есть команда COMMIT, фиксирующая транзакцию. После этого все транзакции новых платежей, поступавших во время выполнения «подарочной» транзакции и ожидавшие ее завершения, выйдут из режима ожидания и увеличат уже увеличенные «по-новогоднему» балансы на суммы своих платежей. Проблема пропавшего обновления не возникнет.

Конструкция WHERE CURRENT OF в DML-командах

Конструкция WHERE CURRENT OF предназначена для удаления или изменения той строки таблицы, которая является текущей в курсоре. Преимущество использования этой конструкции заключается в однократном задании критерия отбора данных в SQL.

Перепишем рассмотренный выше пример с расчетом новогоднего подарочного увеличения баланса с использованием конструкции WHERE CURRENT OF и немного изменим его, сделав расчет не для всех клиентов, а для баланса одного конкретного клиента по его идентификатору.

Первый вариант программы (без использования WHERE CURRENT OF):

DECLARE

l_client_id INTEGER := 122329;

l_balance balances%ROWTYPE;

l_new_year_coeff NUMBER;

BEGIN

SELECT * INTO l_balance FROM balances

WHERE balances.client_id=l_client_id FOR UPDATE;

CASE getClientType(l_balance);

WHEN 'active' THEN l_new_year_coeff := 1.05;

WHEN 'non-actve' THEN l_new_year_coeff := 1.01;

END CASE;

UPDATE balances SET balance = l_balance.balance*l_new_year_coeff

WHERE balances.client_id=l_client_id;

END;

Второй вариант программы (c использованием WHERE CURRENT OF):

DECLARE

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Язык PL/SQL»

Представляем Вашему вниманию похожие книги на «Язык PL/SQL» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Язык PL/SQL»

Обсуждение, отзывы о книге «Язык PL/SQL» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x