Oracle PL / SQL - пример триггера перед DELETE
В этой статье показано, как использоватьBEFORE DELETE TRIGGER
, он сработает до выполнения операции удаления. В сценариях реальной жизни он в основном используется для следующих целей:
-
Ограничить недопустимую операцию DELETE.
-
Удалить данные из другой таблицы.
1. Ограничить недопустимую операцию DELETE
В этом примере у нас есть две таблицыitem_details
иorder_details
. Таблицаorder_details
содержит значения заказов на поставку товаров из таблицыitem_details
. Теперь, когда пользователь хочет удалить элемент из item_details, нам нужно проверить, существует ли для этого элемента какой-либо ОТДЕЛЕННЫЙ ордер.
Если будет обнаружен какой-либо ОЖИДАЮЩИЙся заказ, мы не позволим удалить элемент и вызовем ошибку приложения сBEFORE DELETE TRIGGER
, чтобы ограничить операцию удаления наitem_details
1.1 Create tables and trigger.
ITEM_DETAILS
CREATE TABLE ITEM_DETAILS ( ITEM_ID number(10) primary key, ITEM_NAME varchar2(30), TYPE varchar2(50), PRICE_IN_DOLLAR number(10) );
ИНФОРМАЦИЯ ДЛЯ ЗАКАЗА
CREATE TABLE ORDER_DETAILS ( ORDER_ID number(10) primary key, ITEM_ID number(10), QUANTITY number(5), ORDER_DATE date, STATUS varchar2(20) );
trg_before_item_delete
CREATE OR REPLACE TRIGGER trg_before_item_delete BEFORE DELETE on item_details FOR EACH ROW DECLARE pending_orders number; BEGIN pending_orders := 0; -- Find pending orders SELECT count(1) INTO pending_orders FROM order_Details WHERE item_id = :OLD.item_id AND STATUS = 'PENDING'; -- Check whether any pending order exists or not IF (pending_orders > 0) THEN RAISE_APPLICATION_ERROR(-20000,pending_orders|| ' pending orders found for this item. First COMPLETE or CANCEL the order and then delete.'); END IF; END;
1.2 Insert data for testing.
INSERT INTO ITEM_DETAILS VALUES (1,'Fidget Spinner','TOYS',10); INSERT INTO ITEM_DETAILS VALUES (2,'Radio','ELECTRONICS',15); INSERT INTO ITEM_DETAILS VALUES (3,'Toys Car','TOYS',25); INSERT INTO ITEM_DETAILS VALUES (4,'Mobile','ELECTRONICS',150); alter session set nls_date_format = 'DD-MON-YYYY'; INSERT INTO ORDER_DETAILS VALUES (101,1,5,'10-JUN-2017','COMPLETED'); INSERT INTO ORDER_DETAILS VALUES (102,2,2,'15-JUN-2017','CANCELLED'); INSERT INTO ORDER_DETAILS VALUES (103,4,1,'17-JUN-2017','PENDING'); INSERT INTO ORDER_DETAILS VALUES (104,4,1,'01-JUN-2017','COMPLETED');
1.3 Display the data.
select * from ITEM_DETAILS;
ITEM_ID | ИМЯ ЭЛЕМЕНТА | TYPE | PRICE_IN_DOLLAR |
---|---|---|---|
1 |
Непоседа Spinner |
TOYS |
10 |
2 |
Радио |
ЭЛЕКТРОНИКА |
15 |
3 |
Игрушки Автомобиль |
TOYS |
25 |
4 |
мобильный |
ЭЛЕКТРОНИКА |
150 |
select * from ORDER_DETAILS;
НОМЕР ЗАКАЗА | ITEM_ID | КОЛИЧЕСТВО | ДАТА ЗАКАЗА | ПОЛОЖЕНИЕ ДЕЛ |
---|---|---|---|---|
101 |
1 |
5 |
10-ИЮН-2017 |
ВЫПОЛНЕНО |
102 |
2 |
2 |
15-ИЮН-2017 |
ОТМЕНЕН |
103 |
4 |
1 |
17-ИЮН-2017 |
ОЖИДАНИЕ |
104 |
4 |
1 |
01-ИЮН-2017 |
ВЫПОЛНЕНО |
1.4 Delete item which have PENDING orders.
DELETE FROM item_details WHERE item_id = 4; -- output Error report - ORA-20000: 1 pending orders found for this item. First COMPLETE or CANCEL the order and then delete. ORA-06512: at "SYSTEM.TRG_BEFORE_ITEM_DELETE", line 11 ORA-04088: error during execution of trigger 'SYSTEM.TRG_BEFORE_ITEM_DELETE'
2. УДАЛИТЬ из другой таблицы
В этом примере у нас есть две таблицыpatient
иpatient_details
. patient
содержит основные сведения, аpatient_details
содержит значения пациента, такие как болезнь, имя врача и т. Д.
Теперь, когда пользователь хочет удалить данные изpatient
, нам нужно удалить данные изpatient_details
, также как и после удаления пациента, которые нам больше не нужны. Итак, здесь мы удалим данныеBEFORE DELETE TRIGGER
в таблице пациентов.
2.1 Create tables and trigger.
ТЕРПЕЛИВЫЙ
CREATE TABLE PATIENT ( PATIENT_ID number(10) primary key, NAME varchar2(30), PHONE_NO number(12) );
PATIENT_DETAILS
CREATE TABLE PATIENT_DETAILS ( PD_ID number(10) primary key, PATIENT_ID number(10), DISEASE varchar2(50), ADMITTED_DATE date, DOCTOR varchar2(30) );
trg_delete_from_details
CREATE OR REPLACE TRIGGER trg_delete_from_details BEFORE DELETE on patient FOR EACH ROW BEGIN -- Delete from PATIENT_DETAILS also DELETE FROM PATIENT_DETAILS PD WHERE PD.PATIENT_ID = :OLD.PATIENT_ID; END;
2.2 Insert data for testing.
alter session set nls_date_format = 'DD-MON-YYYY'; INSERT INTO PATIENT VALUES(1,'Devil Lal',9898989898); INSERT INTO PATIENT VALUES(2,'Martin Kiyosaki',9090909090); INSERT INTO PATIENT_DETAILS VALUES(101,1,'FEVER','10-JUN-2016','Dr. RJ Sharma'); INSERT INTO PATIENT_DETAILS VALUES(102,1,'COLD','01-DEC-2016','Dr. RJ Sharma'); INSERT INTO PATIENT_DETAILS VALUES(103,2,'ARTHRITIS','01-DEC-2015','Dr. KD Verma'); INSERT INTO PATIENT_DETAILS VALUES(104,2,'BACKPAIN','12-FEB-2017','Dr. KD Verma');
2.3 Display the data.
select * from PATIENT;
PATIENT_ID | NAME | НОМЕР ТЕЛЕФОНА |
---|---|---|
1 |
Дьявол Лал |
9898989898 |
2 |
Мартин Кийосаки |
9090909090 |
select * from PATIENT_DETAILS;
PD_ID | PATIENT_ID | БОЛЕЗНЬ | ADMITTED_DATE | ВРАЧ |
---|---|---|---|---|
101 |
1 |
ВЫСОКАЯ ТЕМПЕРАТУРА |
10-ИЮН-2016 |
Dr. Р.Дж. Шарма |
102 |
1 |
COLD |
01-ДЕК-2016 |
Dr. Р.Дж. Шарма |
103 |
2 |
АРТРИТ |
01 декабря 2015 г. |
Dr. К.Д. Верма |
104 |
2 |
БОЛЬ В СПИНЕ |
12-ФЕВ-2017 |
Dr. К.Д. Верма |
2.4 Delete items from patient
table. Просмотрите таблицуpatient_detail
, связанные данные будут автоматически удалены триггером.
DELETE FROM patient WHERE patient_id = 2; -- output -- 1 row deleted.
select * from PATIENT;
PATIENT_ID | NAME | НОМЕР ТЕЛЕФОНА |
---|---|---|
1 |
Дьявол Лал |
9898989898 |
select * from PATIENT_DETAILS;
PD_ID | PATIENT_ID | БОЛЕЗНЬ | ADMITTED_DATE | ВРАЧ |
---|---|---|---|---|
101 |
1 |
ВЫСОКАЯ ТЕМПЕРАТУРА |
10-ИЮН-2016 |
Dr. Р.Дж. Шарма |
102 |
1 |
COLD |
01-ДЕК-2016 |
Dr. Р.Дж. Шарма |