DeepEdit!

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

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Триггеры событий базы данных

Триггеры событий базы данных запускаются при возникновении событий на уровне базы данных. Существует пять триггеров событий базы данных:
STARTUP
Запускается при запуске базы данных.
SHUTDOWN
Запускается при нормальной остановке базы данных.
SERVERERROR
Запускается при возникновении ошибки Oracle.
LOGON
Запускается при открытии сеанса Oracle.

Запускается при нормальном завершении сеанса Oracle.
Администраторы базы данных сразу обратят внимание на то, что эти триггеры представляют собой великолепное средство автоматизации процесса администрирования базы данных и обеспечения детального контроля над базой данных.
Создание триггера события базы данных
Синтаксис, используемый для создания такого триггера, очень похож на синтаксис создания триггера DDL:

Существует ряд ограничений, накладываемых на использование атрибутов BEFORE и AFTER для определенных событий. Некоторые ситуации представляются просто бессмысленными:
Не бывает триггеров BEFORE STARTUP
Не бывает триггеров AFTER SHUTDOWN
Опять-таки, когда бы такой триггер мог запускаться? Попытки создания такого триггера отвергаются с выдачей следующего сообщения об ошибке:
Даже если бы такой триггер и можно было бы создать, когда бы он запускался? Попытка создания триггера такого вида приводит к появлению очевидного сообщения об ошибке:
Не бывает триггеров BEFORE LOGON
Для реализации таких триггеров потребовался бы какой-то чрезвычайно проницательный код: «Слушай, мне кажется, кто-то собирается подключиться: давай-ка сделаем что-нибудь!». Будучи реалистом, Oracle не позволяет создавать такие триггеры, выдавая сообщение об ошибке:

Не бывает триггеров AFTER LOGOFF
«Нет, пожалуйста, вернись! Только не отключайся!»... Попытки создания этих триггеров завершаются появлением следующего сообщения:

Не бывает триггеров BEFORE SERVERERROR
Но, к сожалению, наши мечты прерывает сообщение:
Подобный триггер был бы мечтой каждого программиста! Только представьте себе, что было бы возможно такое:
Динамический SQL и динамический PL/SQL
Динамический SQL подразумевает под собой те операторы SQL, которые формируются и исполняются во время исполнения программы. Термин «динамический» - антоним для термина «статический». Статический SQL - это операторы SQL, которые фиксируются в момент компиляции программы и далее не изменяются. Динамический PL/ SQL соответственно понимается как целые PL/SQL-блоки кода, которые динамически формируются, затем компилируются и исполняются.
С выходом версии Oracle7 Release 1 разработчики PL/SQL получили возможность использовать для исполнения динамического SQL встроенный пакет DBMS_SQL. В Oracle8i Database появилась дополнительная возможность исполнения динамически формируемых команд SQL - NDS (native dynamic SQL - встроенный динамический SQL). NDS входит в состав языка PL/SQL; его гораздо легче использовать, чем DBMS_SQL, к тому же во многих приложениях он исполняется более эффективно.
Оператор EXECUTE IMMEDIATE
Используйте оператор EXECUTE IMMEDIATE для (немедленного!) исполнения указанной команды SQL:


Переменная, которая получает значение столбца, возвращенное запросом.
запись
Запись, основанная на определенном пользователем типе или атрибуте %ROWTYPE, которая получает целую строку, возвращенную запросом.
аргумент_связывания
Выражение, значение которого передается в команду SQL или PL/ SQL-блок, или идентификатор, который служит входной и/или выходной переменной для функции или процедуры, вызываемой в PL/SQL-блоке.
INTO предложение
Используется для однострочных запросов. Для каждого значения столбца, возвращенного запросом, следует указать отдельную переменную или поле записи совместимого типа.
USING предложение
Используется для передачи аргументов связывания в строку SQL. Это предложение используется как для динамического SQL, так и для динамического PL/SQL, поэтому существует возможность указать режим передачи параметров (имеет смысл только для PL/SQL; по умолчанию установлен в значение «IN», соответствующее единственному виду аргументов, доступных для команд SQL).
Оператор EXECUTE IMMEDIATE может использоваться для любой SQL-ко- манды или PL/SQL-блока за исключением многострочных запросов. Если строка_SQL заканчивается точкой с запятой, то она воспринимается как PL/SQL-блок. В противном случае она воспринимается как SELECT, оператор DML (INSERT, UPDATE или DELETE) или DDL (например, CREATE TABLE). В строке могут присутствовать заполнители для аргументов связывания, но с их помощью нельзя передавать имена объектов схемы, такие как имена таблиц и столбцов.
Если в вашей программе выполняется оператор DDL, то вместе с ним выполнится и фиксация изменений. Если вы не хотите, чтобы фиксация изменений, вызванная оператором DDL, повлияла на ранее сделанные изменения в остальной части приложения, то следует поместить динамический оператор DDL в процедуру, реализованную как автономная транзакция (см. пример в файле auton_ddl.sql на веб-сайте этой книги).
При выполнении команды исполняющее ядро заменяет каждый заполнитель (идентификатор, перед которым стоит двоеточие, например
:salary_value) в строке_SQL соответствующим аргументом_связывания (в соответствии с позицией). Вы можете передавать числа, даты и строки.
Логические выражения передавать нельзя, так как BOOLEAN - это тип данных PL/SQL. Также нельзя передавать литеральное значение NULL (вместо этого следует передавать переменную разрешенного типа, имеющую значение NULL).
NDS поддерживает все типы данных SQL. Переменные и аргументы_связы- вания могут быть коллекциями, большими объектами (типа LOB), экземплярами объектного типа и типа REF. Типы данных, специфичные для PL/SQL, NDS не поддерживает: тип BOOLEAN, ассоциативные массивы и пользовательские типы записей. При этом предложение INTO может содержать PL/SQL-запись.
Давайте рассмотрим несколько примеров:
• Создание индекса:

PL/SQL не поддерживает встроенные команды DDL; необходимо использовать динамический SQL.
• Получение количества строк некоторой таблицы в некоторой схеме для указанного предложения WHERE:

Теперь уже можно больше не писать SELECT COUNT(*) ни в SQL*Plus, ни в программе на PL/SQL. Для подсчета количества строк поступаем следующим образом:


• Функция, позволяющая обновить значение любого числового столбца в таблице employee. Реализовано в виде функции, чтобы можно было дополнительно возвращать количество обновленных строк.

И для достижения подобной гибкости требуется совсем небольшой объем кода! В примере использован аргумент связывания: после синтаксического анализа команды UPDATE ядро PL/SQL заменяет заполнители :the_value, :lo и :hi значениями из предложения USING. Обратите внимание, что, как и в случае со статическими командами SQL, можно использовать атрибут курсора SQL%ROWCOUNT.
Как видите, синтаксис оператора EXECUTE IMMEDIATE очень прост и доступен!
Оператор OPEN FOR
PL/SQL-оператор OPEN FOR не создавался специально для работы с NDS; он появился в версии Oracle7 и обеспечивал поддержку курсорных переменных. Теперь этот оператор используется для элегантной реализации многострочных динамических запросов. Использование DBMS_SQL для выполнения многострочных запросов представляло собой мучительную многоэтапную процедуру: синтаксический анализ, связывание, определение каждого столбца в отдельности, выборка, извлечение значений каждого столбца в отдельности. Приходилось писать значительный объем кода!
Разработчики Oracle использовали существующую функциональность - курсорные переменные - и сохранили синтаксис, весьма естественно расширив его для поддержки динамического SQL. Давайте посмотрим на синтаксис оператора OPEN FOR:


где: курсорная_переменная
Слабо типизированная курсорная переменная.
:внешняя_курсорная_переменная
Курсорная переменная, объявленная в среде, вызывающей PL/SQL (например, в программе Oracle Call Interface - OCI).
SQL_строка
Содержит команду SELECT, подлежащую динамическому исполнению.
USING предложение
Следует тем же правилам, что и для оператора EXECUTE IMMEDIATE.        
Если вы работаете с версией Огас1е9/ Database Release 2 или Ога-
cle Database Юе', то можете использовать EXECUTE IMMEDIATE в со четании с BULK СЮLLЕС'.Т для извлечения нескольких строк в динамическом запросе. Такой подход требует гораздо меньшего объема кода и может значительно улучшить производительность работы вашего запроса.
Рассмотрим пример, в котором объявляется слабо типизированный REF CURSOR, курсорная переменная на основе этого типа, а затем при помощи оператора OPEN FOR открывается динамический запрос:

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









jAntivirus