Поскольку замещающие триггеры, в отличие от предваряющих, не могут содержать фразу UPDATE OF, мы должны написать код, определяющий, был ли изменен столбец Title.
Листинг 4. Замещающий триггер Title_Update
CREATE OR REPLACE TRIGGER Title_Update INSTEAD OF UPDATE ON CustomerPurchases
FOR EACH ROW
BEGIN
/* Ничего не делаем, кроме случая, когда обновляется столбец Title
*/
IF :new.Title 5 :old.Title THEN RETURN;
END IF;
UPDATE |
WORK |
SET Title = :new.Tit1e |
|
WHERE |
Title = :old.Title; |
END;
Если пользователь обновляет столбец Title, то соответствующее изменение вносится в таблицу WORK. Обратите внимание, что запуск триггера происходит при обновлении представления CustomerPurchases, но само обновление производится в таблице WORK — одной из таблиц, на которой базируется это представление. Как раз для таких действий и предназначаются замещающие триггеры,
Этот триггер может приводить к неожиданным результатам. Если пользователь введет:
UPDATE CustomerPurchases SET Title = 'аа'. Copy = '1/3' WHERE Title = 'bb';
то будет произведено обновление столбца Title, но ничего не произойдет со столбцом Copy. Лучше было бы выдать пользователю сообщение, предупреждающее о таком эффекте.
46
В лекциях опущена тема обработки исключений в PL/SQL. Однако, обработка исключений важна и полезна. Дело в том, что эта тема является слишком обширной, чтобы обсуждать ее подробно. Однако если вы в будущем собираетесь программировать на PL/SQL, обязательно изучите этот важный вопрос. Обработка исключений может использоваться в любых видах процедур на PL/SQL, но особо она полезна в предваряющих и замещающих триггерах для отмены незафиксированных обновлений. Исключения необходимы потому, что в Oracle откат транзакции невозможно произвести в теле триггера. Вместо этого можно использовать исключения для генерации предупреждений и сообщений об ошибках. Исключения также дают Oracle больше информации о том, что делает триггер.
Например, триггер, изображенный в листинге 4, имеет странную особенность. Если вы введете
UPDATE CustomerPurchases SET Copy = '5/5' WHERE Title = 'Mystic Fabric';
триггер не обновит ни одной строки. Однако Oracle сообщит, что все строки представления, имеющие в столбце Title название «Mystic Fabric», были обновлены. Это было обусловлено тем, что триггеру были переданы все строки, и Oracle не знала, какая из них вызвала обновление, а какая нет. Если же вы включите в этот триггер код, генерирующий исключение, Oracle будет знать, что строка не была обновлена, и выдаст правильное количество обновленных строк.
Oracle поддерживает исчерпывающий словарь метаданных. Этот словарь описывает структуру таблиц, последовательностей, представлений, индексов, ограничений, хранимых процедур и многого другого. Он также содержит исходные тексты процедур, функций и триггеров. И это еще не все.
В таблице DICT словаря метаданных содержатся данные, описывающие сам словарь. Вы можете запрашивать данные из этой таблицы, чтобы узнать больше о содержимом словаря данных, но имейте в виду, что она имеет большие
47
размеры. Например, если вы запросите имена всех таблиц словаря данных, вам будет возвращено более 800 строк.
Предположим, Вы хотите узнать, какие таблицы с информацией о пользовательских и системных таблицах имеются в словаре данных. В этом вам поможет следующий запрос;
SELECT Table_Name, Contents FROM DICT
WHERE Table_Name LIKE (‘%TABLES%’);
Будет возвращено около двадцати пяти строк. Одна из таблиц будет называться USER_TABLES. Чтобы увидеть столбцы этой таблицы, введите
DESC USER_TABLES:
Вы можете использовать эту стратегию для получения из словаря метаданных информации об интересующих вас объектах и структурах. В таблице перечислены многие из представлений и указано их назначение. Таблицы USER_SOURCE и USER_TRIGGERS полезны, когда требуется узнать, исходные тексты каких процедур и триггеров хранятся в настоящий момент в базе данных.
Таблица. Некоторые полезные таблицы из словаря данных Oracle
Имя таблицы |
Содержимое |
DICT |
Метаданные, описывающие словарь данных |
USER_CATALOG |
Список таблиц, представлений, последовательностей |
USER_TABLES |
и других структур, принадлежащих пользователю |
Структуры таблиц пользователя |
|
USER_TAB_COLUM Потомок таблицы USER_TABLES. Содержит данные |
|
NS |
о столбцах таблиц. Синонимом является COLS |
USER_VIEWS |
Пользовательские представления |
USER_CONSTRAIN |
Пользовательские ограничения |
USER_CONS_COLU |
Потомок таблицы USER_CONSTRAINTS. Содержит |
MNS |
столбцы, на которые наложены ограничения |
USER_TRIGGERS |
Метаданные, описывающие триггеры, Запрашивайте |
столбцы Trigger_Name, Trigger_Type и Trigger_Event.
Предупреждение'. Trigger_Body в действительности
48
USER_SOURCE Чтобы получить текст процедуры MYTRIGGER.
введите
SELECT Text
FROM USER_SOURCE WHERE Name='MYTRIGGER'
AND Type='PROCEDURE'
Самостоятельно исследуйте словарь метаданных.
Имейте в виду, что Oracle записывает все имена в верхнем регистре. Если вы ищете триггер On_Customer__Insert, вам следует искать имя
ON_CUSTOMER_INSERT.
Полученную информацию отобразите в отчете.
49
Oracle поддерживает три различных уровня изоляции транзакций и вдобавок позволяет приложениям налагать блокировки явным образом. Явное наложение блокировок, однако, не рекомендуется, поскольку оно может войти в конфликт со стратегией блокировки, применяемой Oracle по умолчанию, и, кроме того, увеличивает вероятность взаимной блокировки транзакций.
Прежде чем обсуждать уровни изоляции транзакций, необходимо кратко рассмотреть то, как Oracle обрабатывает изменения в базе данных. Oracle ведет учет числа изменений в системе (System Change Number, SCN), которое представляет собой значение масштаба базы данных, увеличивающееся на единицу всякий раз, когда в базе данных производится изменение. Когда изменяется строка, текущее значение SCN сохраняется вместе со строкой. Одновременно исходный образ строки помещается в сегмент отката (rollback segment) — буфер, поддерживаемый Oracle для выполнения отката и записи транзакций в журнал. Исходный образ включает в себя значение SCN, которое было записано в строке до изменения. Завершив обновление, Oracle увеличивает SCN.
Допустим, приложение выдает SQL-оператор вида
UPDATE MYTABLE
SET |
MyColumn1 = 'Новое_Значение' |
WHERE |
MyColumn2 = 'Что-нибудь'; |
Сначала записывается значение SCN, имевшее место в момент запуска оператора. Назовем это значение SCN оператора. При обработке запроса, в данном случае при поиске строк, в которых MyColumn2 = 'Что-нибудь', Oracle выберет только те строки, которые содержат завершенные изменения с SCN, меньшим или равным SCN оператора. Если Oracle находит строку с завершенным изменением, SCN которой превышает SCN оператора, она ищет в сегменте отката версию этой строки с завершенным изменением, SCN которой меньше, чем SCN оператора.
При таком способе обработки SQL-операторы всегда считывают согласованный набор значений — те значения, которые были записаны до или в
50