Учебники

21) Триггеры в PL / SQL

Что такое триггер в PL / SQL?

TRIGGERS — это хранимые программы, которые запускаются механизмом Oracle автоматически, когда в таблицу выполняются такие операторы DML, как вставка, обновление, удаление или если происходят некоторые события. Код, подлежащий исключению в случае триггера, может быть определен согласно требованию. Вы можете выбрать событие, при котором должен быть запущен триггер, и время выполнения. Целью триггера является поддержание целостности информации в базе данных.

В этом уроке вы узнаете

Преимущества триггеров

Ниже приведены преимущества триггеров.

  • Генерация некоторых производных значений столбцов автоматически
  • Обеспечение ссылочной целостности
  • Регистрация событий и хранение информации о доступе к таблице
  • Аудиторская проверка
  • Синхронная репликация таблиц
  • Внедрение авторизации безопасности
  • Предотвращение недействительных транзакций

Типы триггеров в Oracle

Триггеры могут быть классифицированы на основе следующих параметров.

  • Классификация на основе сроков
    • ПЕРЕД триггером: срабатывает до наступления указанного события.
    • ПОСЛЕ триггера: срабатывает после наступления указанного события.
    • ВМЕСТО триггера: особый тип. Вы узнаете больше о дальнейших темах. (только для DML)
  • Классификация на основе уровня
    • Триггер уровня STATEMENT: запускается один раз для указанного оператора события.
    • Триггер уровня ROW: срабатывает для каждой записи, которая была затронута в указанном событии. (только для DML)
  • Классификация на основе события
    • Триггер DML: срабатывает, когда указано событие DML (INSERT / UPDATE / DELETE)
    • DDL Trigger: срабатывает, когда указано событие DDL (CREATE / ALTER)
    • Триггер базы данных: срабатывает, когда задано событие базы данных (LOGON / LOGOFF / STARTUP / SHUTDOWN)

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

Как создать триггер

Ниже приведен синтаксис для создания триггера.

Триггеры в PL / SQL

CREATE [ OR REPLACE ] TRIGGER <trigger_name> 

[BEFORE | AFTER | INSTEAD OF ]

[INSERT | UPDATE | DELETE......]

ON<name of underlying object>

[FOR EACH ROW] 

[WHEN<condition for trigger to get execute> ]

DECLARE
<Declaration part>
BEGIN
<Execution part> 
EXCEPTION
<Exception handling part> 
END;

Синтаксис Объяснение:

  • Приведенный выше синтаксис показывает различные дополнительные операторы, которые присутствуют при создании триггера.
  • ДО / ПОСЛЕ будет указывать время события.
  • INSERT / UPDATE / LOGON / CREATE / и т.д.. будет указывать событие, для которого должен быть запущен триггер.
  • Предложение ON будет указывать, на каком объекте действует указанное событие. Например, это будет имя таблицы, в которой может произойти событие DML в случае триггера DML.
  • Команда «FOR EACH ROW» будет указывать триггер уровня ROW.
  • В предложении WHEN будет указано дополнительное условие, при котором должен срабатывать триггер.
  • Часть объявления, часть исполнения, часть обработки исключений такая же, как и в других блоках PL / SQL. Часть объявления и часть обработки исключений являются необязательными.

: NEW и: СТАРЫЙ пункт

В триггере уровня строки триггер срабатывает для каждой связанной строки. И иногда требуется знать значение до и после оператора DML.

Oracle предоставил два условия в триггере уровня RECORD для хранения этих значений. Мы можем использовать эти предложения для ссылки на старые и новые значения внутри тела триггера.

  • : NEW — содержит новое значение для столбцов базовой таблицы / представления во время выполнения триггера.
  • : OLD — содержит старое значение столбцов базовой таблицы / представления во время выполнения триггера

Это предложение следует использовать на основе события DML. Ниже в таблице будет указано, какое предложение действительно для какого оператора DML (INSERT / UPDATE / DELETE).

ВСТАВИТЬ ОБНОВИТЬ УДАЛЯТЬ
: NEW ДЕЙСТВУЕТ ДЕЙСТВУЕТ НЕДЕЙСТВИТЕЛЬНЫМ. Нет нового значения в случае удаления.
: OLD НЕДЕЙСТВИТЕЛЬНЫМ. В случае вставки нет старого значения ДЕЙСТВУЕТ ДЕЙСТВУЕТ

ВМЕСТО триггера

«INSTEAD OF trigger» — это специальный тип триггера. Он используется только в триггерах DML. Он используется, когда любое событие DML происходит в сложном представлении.

Рассмотрим пример, в котором представление составлено из 3 базовых таблиц. Когда какое-либо событие DML генерируется над этим представлением, оно становится недействительным, поскольку данные взяты из 3 разных таблиц. Так что в этом используется триггер INSTEAD OF. Триггер INSTEAD OF используется для непосредственного изменения базовых таблиц вместо изменения представления для данного события.

Пример 1 : В этом примере мы собираемся создать сложное представление из двух базовых таблиц.

  • Таблица_1 является таблицей emp и
  • Таблица_2 — таблица отдела.

Затем мы увидим, как триггер INSTEAD OF используется для выполнения UPDATE оператора детализации местоположения в этом сложном представлении. Мы также увидим, как: NEW и: OLD полезны в триггерах.

  • Шаг 1: Создание таблицы emp и dept с соответствующими столбцами
  • Шаг 2: заполнение таблицы примерами значений
  • Шаг 3: Создание представления для созданной выше таблицы
  • Шаг 4: Обновление представления перед триггером вместо
  • Шаг 5: Создание триггера вместо
  • Шаг 6: Обновление представления после триггера вместо

Шаг 1) Создание таблицы emp и dept с соответствующими столбцами

Триггеры в PL / SQL

CREATE TABLE emp(
emp_no NUMBER,
emp_name VARCHAR2(50),
salary NUMBER,
manager VARCHAR2(50),
dept_no NUMBER);
/

CREATE TABLE dept( 
Dept_no NUMBER, 
Dept_name VARCHAR2(50),
LOCATION VARCHAR2(50));
/

Код Объяснение

  • Строка кода 1-7 : создание таблицы emp.
  • Строка кода 8-12 : создание таблицы dept.

Вывод

Таблица создана

Шаг 2) Теперь, когда мы создали таблицу, мы заполним эту таблицу примерами значений и созданием представлений для вышеуказанных таблиц.

Триггеры в PL / SQL

BEGIN
INSERT INTO DEPT VALUES(10,‘HR’,‘USA’);
INSERT INTO DEPT VALUES(20,'SALES','UK’);
INSERT INTO DEPT VALUES(30,‘FINANCIAL',‘JAPAN'); 
COMMIT;
END;
/

BEGIN
INSERT INTO EMP VALUES(1000,'XXX5,15000,'AAA',30);
INSERT INTO EMP VALUES(1001,‘YYY5,18000,‘AAA’,20) ;
INSERT INTO EMP VALUES(1002,‘ZZZ5,20000,‘AAA',10); 
COMMIT;
END;
/

Код Объяснение

  • Строка кода 13-19 : вставка данных в таблицу «dept».
  • Строка кода 20-26: вставка данных в таблицу emp.

Вывод

Процедура PL / SQL завершена

Шаг 3) Создание представления для созданной выше таблицы.

Триггеры в PL / SQL

CREATE VIEW guru99_emp_view(
Employee_name:dept_name,location) AS
SELECT emp.emp_name,dept.dept_name,dept.location
FROM emp,dept
WHERE emp.dept_no=dept.dept_no;
/
SELECT * FROM guru99_emp_view;

Код Объяснение

  • Строка кода 27-32: создание представления «guru99_emp_view».
  • Строка кода 33: запрос guru99_emp_view.

Вывод

Просмотр создан

ИМЯ СОТРУДНИКА DEPT_NAME РАСПОЛОЖЕНИЕ
ZZZ HR Соединенные Штаты Америки
YYY ПРОДАЖИ Великобритания
XXX ФИНАНСОВЫЙ ЯПОНИЯ

Шаг 4) Обновление представления перед триггером.

Триггеры в PL / SQL

BEGIN
UPDATE guru99_emp_view SET location='FRANCE' WHERE employee_name=:'XXX’;
COMMIT;
END;
/

Код Объяснение

  • Строка кода 34-38: измените местоположение «XXX» на «FRANCE». Возникло исключение, поскольку операторы DML не допускаются в сложном представлении.

Вывод

ORA-01779: невозможно изменить столбец, который сопоставляется с таблицей без сохранения ключа

ORA-06512: в строке 2

Шаг 5) Чтобы избежать ошибки при обновлении представления на предыдущем шаге, на этом шаге мы будем использовать «вместо триггера».

Триггеры в PL / SQL

CREATE TRIGGER guru99_view_modify_trg
INSTEAD OF UPDATE
ON guru99_emp_view
FOR EACH ROW
BEGIN
UPDATE dept
SET location=:new.location
WHERE dept_name=:old.dept_name;
END;
/

Код Объяснение

  • Строка кода 39: создание триггера INSTEAD OF для события «UPDATE» в представлении «guru99_emp_view» на уровне ROW. Он содержит оператор update для обновления местоположения в базовой таблице «dept».
  • Строка кода 44: оператор Update использует «: NEW» и «: OLD», чтобы найти значение столбцов до и после обновления.

Вывод

Триггер создан

Шаг 6) Обновление вида после вместо триггера. Теперь ошибка не возникнет, так как «вместо триггера» будет обрабатывать операцию обновления этого сложного представления. А после выполнения кода местоположение сотрудника XXX будет обновлено до «Франция» из «Японии».

Триггеры в PL / SQL

BEGIN
UPDATE guru99_emp_view SET location='FRANCE' WHERE employee_name='XXX'; 
COMMIT;
END;
/
SELECT * FROM guru99_emp_view;

Объяснение кода:

  • Кодовая строка 49-53: Обновление местоположения «XXX» до «FRANCE». Это успешно, потому что триггер «INSTEAD OF» остановил фактический оператор обновления в представлении и выполнил обновление базовой таблицы.
  • Строка кода 55: проверка обновленной записи.

Вывод:

Процедура PL / SQL успешно завершена

ИМЯ СОТРУДНИКА DEPT_NAME РАСПОЛОЖЕНИЕ
ZZZ HR Соединенные Штаты Америки
YYY ПРОДАЖИ Великобритания
XXX ФИНАНСОВЫЙ ФРАНЦИЯ

Составной триггер

Составной триггер — это триггер, который позволяет вам определять действия для каждой из четырех временных точек в одном теле триггера. Четыре различных момента времени, которые он поддерживает, как показано ниже.

  • ДО ЗАЯВЛЕНИЯ — уровень
  • ДО РЯДА — уровень
  • ПОСЛЕ ROW — уровень
  • ПОСЛЕ ЗАЯВЛЕНИЯ — уровень

Он предоставляет возможность объединять действия для разных временных интервалов в один и тот же триггер.

Триггеры в PL / SQL

CREATE [ OR REPLACE ] TRIGGER <trigger_name> 
FOR
[INSERT | UPDATE | DELET.......]
ON <name of underlying object>
<Declarative part>‭	‬
BEFORE STATEMENT IS
BEGIN
<Execution part>;
END BEFORE STATEMENT;

BEFORE EACH ROW IS
BEGIN
<Execution part>;
END EACH ROW;

AFTER EACH ROW IS
BEGIN
<Execution part>;
END AFTER EACH ROW;

AFTER STATEMENT IS
BEGIN
<Execution part>;
END AFTER STATEMENT;
END;

Синтаксис Объяснение:

  • Приведенный выше синтаксис показывает создание триггера «СОЕДИНЕНИЕ».
  • Декларативный раздел является общим для всего блока выполнения в теле триггера.
  • Эти 4 блока синхронизации могут быть в любой последовательности. Не обязательно иметь все эти 4 блока синхронизации. Мы можем создать триггер СОЕДИНЕНИЯ только для того времени, которое требуется.

Пример 1 : В этом примере мы собираемся создать триггер для автоматического заполнения столбца зарплаты значением по умолчанию 5000.

Триггеры в PL / SQL

CREATE TRIGGER emp_trig 
FOR INSERT 
ON emp
COMPOUND TRIGGER 
BEFORE EACH ROW IS 
BEGIN
:new.salary:=5000;
END BEFORE EACH ROW;
END emp_trig;
/
BEGIN
INSERT INTO EMP VALUES(1004,‘CCC’,15000,‘AAA’,30); 
COMMIT;
END;
/
SELECT * FROM emp WHERE emp_no=1004;

Объяснение кода:

  • Строка кода 2-10 : создание составного триггера. Он создан для синхронизации до уровня ROW-ROW для заполнения зарплаты значением по умолчанию 5000. Это изменит зарплату на значение по умолчанию ‘5000’ перед вставкой записи в таблицу.
  • Строка кода 11-14 : вставьте запись в таблицу emp.
  • Строка кода 16 : проверка вставленной записи.

Вывод:

Триггер создан

Процедура PL / SQL успешно завершена.

EMP_NAME EMP_NO ЗАРПЛАТА УПРАВЛЯЮЩИЙ ДЕЛАМИ DEPT_NO
CCC 1004 5000 AAA 30

Включение и отключение триггеров

Триггеры могут быть включены или отключены. Чтобы включить или отключить триггер, необходимо указать инструкцию ALTER (DDL) для триггера, который отключает или включает его.

Ниже приведен синтаксис для включения / отключения триггеров.

ALTER TRIGGER <trigger_name> [ENABLE|DISABLE];
ALTER TABLE <table_name> [ENABLE|DISABLE] ALL TRIGGERS;

Синтаксис Объяснение:

  • Первый синтаксис показывает, как включить / отключить один триггер.
  • Второй оператор показывает, как включить / отключить все триггеры в определенной таблице.

Резюме

В этой главе мы узнали о триггерах PL / SQL и их преимуществах. Мы также изучили различные классификации и обсудили триггер INSTEAD OF и триггер COMPOUND.