트리거(Trigger)
(사용형식)
CREATE [OR REPLACE] TRIGGER 트리거명
BEFORE|AFTER INSERT|DELETE|UPDATE ON 테이블명
[FOR EACH ROW]
[WHEN 조건]
[DECLARE
선언영역]
BEGIN
트리거 본문;
[EXCEPTION
예외처리블록]
END;
- 'BEFORE|AFTER' : 트리거 본문이 실행될 시점으로(timing) EVENT(INSERT,UPDATE,DELETE)발생 전 또는 발생 후를 설정
- 'INSERT|DELETE|UPDAT' : 이벤트를 의미하며 'ON 테이블'에 DML동작이 발생되기 전 또는 후에 트리거 본문이 실행되는 요인을 결정. OR연산자로 복합사용 가능
- 'FOR EACH ROW' : 행단위 트리거를 생성
- 'WHEN 조건' : EVENT 발생시 트리거가 수행되는데 좀 더 구체적으로 트리거 발생을 구체화 시킬때 사용하며, 반드시 행단위 트리거에서만 사용 가능
A. 트리거의 종류
1).문장단위 트리거
- 이벤트 결과집합의 행의 수에 관계없이 한 번만 트리거 발생
- FOR EACH ROW가 생략되면 문장단위 트리거로 취급
2) 행단위 트리거
- FOR EACH ROW를 사용한 트리거
- 이벤트의 결과 집합내의 행마다 트리거 본문 수행
- 하나의 트리거가 완료되지 않은 상태에서 또 다른 트리거를 호출하거나, 두 테이블이 서로 영향을 미치는 트리거는 실행 오류(mutable error)
사용예) 사원테이블에서 사원번호 125번 사원을 삭제(퇴직처리)하시오. 삭제 전 퇴직자테이블에
사원번호,사원명,부서코드,직무코드를 입력하는 트리거를 작성하시오.
CREATE OR REPLACE TRIGGER TG_DEL_EMP
BEFORE DELETE on T_EMP
FOR EACH ROW
BEGIN
INSERT INTO RETIRE VALUES(:old.EMPLOYEE_ID,:old.EMP_NAME);
END;
DELETE FROM T_EMP
WHERE EMPLOYEE_ID=149;
-- DROP TRIGGER TG_DEL_EMP
사용예) LPROD 테이블에서 LPROD_DI=10인 자료를 삭제한 후
'자료가 정상적으로 삭제 되었습니다.'라는 메시지를 출력하는 트리거를 작성하시오.
CREATE OR REPLACE TRIGGER TD_DEL_LPROD01
AFTER DELETE ON LPROD
BEGIN
DBMS_OUTPUT.PUT_LINE('자료가 정상적으로 삭제 되었습니다.');
END;
DELETE FROM LPROD WHERE LPROD_ID>=7;
SELECT * FROM LPROD;
-- ROLLBACK;
-- COMMIT;
--
SELECT * FROM LPROD;
**ORDER 테이블과 ORDER_DETAIL 테이블에 다음 자료를 입력하시오.
[ORDER 테이블]
------------------------------------------------------------
ORDER_ID ORDER_DATE MEM_ID
------------------------------------------------------------
20230209001 2023/02/09 b001
20230209002 2023/02/09 f001
INSERT INTO ORDERS VALUES('20230209001', TO_DATE('20230209'), 'b001');
INSERT INTO ORDERS VALUES('20230209002', TO_DATE('20230209'), 'f001');
[ORDER_DETAIL 테이블]
------------------------------------------------------------
ORDER_ID PROD_ID ORDER_QTY
------------------------------------------------------------
20230209001 P201000001 2
20230209001 P201000010 5
20230209001 P201000016 1
20230209001 P202000001 2
20230209002 P302000003 2
20230209002 P102000005 1
insert into order_detail(order_id,prod_id,order_qty)
values('20230209001','P201000001',2);
insert into order_detail(order_id,prod_id,order_qty)
values('20230209001','P201000010',5);
insert into order_detail(order_id,prod_id,order_qty)
values('20230209001','P201000016',1);
insert into order_detail(order_id,prod_id,order_qty)
values('20230209001','P202000001',2);
insert into order_detail(order_id,prod_id,order_qty)
values('20230209002','P302000003',2);
insert into order_detail(order_id,prod_id,order_qty)
values('20230209002','P102000005',1);
COMMIT;
B. 트리거 의사레코드와 트리거 함수
1) 트리거 의사레코드
- 행단위 트리거에서만 사용
--------------------------------------------------------------------------------------
의사레코드 설명
--------------------------------------------------------------------------------------
:NEW insert, update event에 사용되며 데이터가 삽입(갱신)될때
새롭게 입력된 자료를 지칭함. delete에 사용하면 모든 컬럼이 null로 설정됨
:OLD insert, update event에 사용되며 데이터가 삭제(갱신)될때
새롭게 입력된 자료를 지칭함. delete에 사용하면 모든 컬럼이 null로 설정됨
2) 트리거 함수
- 이벤트가 복수개 사용되는 트리거에 사용
--------------------------------------------------------------------------------------
트리거 함수 설명
--------------------------------------------------------------------------------------
inserting 트리거 이벤트가 insert이면 true
updating 트리거 이벤트가 update이면 true
deleting 트리거 이벤트가 delete이면 true
사용예) orders테이블에서 오늘 날짜의 주문 중 'b001' 회원이 주문을 취소한 경우
orders와 order_detail테이블의 변동 사항을 처리하는 트리거를 작성하시오.
create or replace trigger tg_del_order
before delete on orders
for each row
declare
l_order_id ORDERS.ORDER_ID%type;
begin
l_order_id:=(:OLD.ORDER_ID);
delete from order_detail
where ORDER_ID=l_order_id;
end;
-- delete from orders where order_id='20230209001';
사용예) 오늘이 2020년 6월 15일이라고 가정하고 다음 입고자료를 처리하는 트리거를 작성하시오.
--시스템 시간 조정
[입고자료]
------------------------------------------------
입고일 입고상품코드 수량 단가
------------------------------------------------
2020-06-15 p102000004 10 990000
2020-06-15 p101000003 20 440000
2020-06-15 p202000009 15 28500
create or replace trigger tg_update_buy
after insert or update or delete on buyprod
for each row
declare
l_qty number:=0;
l_pid prod.prod_id%type;
l_date date;
begin
if inserting then
l_qty:=(:new.buy_qty);
l_pid:=(:new.buy_prod);
l_date:=(:new.buy_date);
elsif updating then
l_qty:=(:new.buy_qty - :old.buy_qty);
l_pid:=(:new.buy_prod);
l_date:=(:new.buy_date);
elsif deleting then
l_qty:= -(:old.buy_qty);
l_pid:=(:old.buy_prod);
l_date:=(:old.buy_date);
end if;
update remain a
set a.REMAIN_I=a.REMAIN_I+l_qty,
a.REMAIN_J_99=a.REMAIN_J_99+l_qty,
a.REMAIN_DATE=l_date
where a.prod_id=l_pid;
exception when others then
dbms_output.put_line('예외발생 : '||sqlerrm);
end;
[매출처리 : 재고수불테이블 update,MEMBER테이블 update => 트리거 본문]
create or replace trigger tg_update_cart
after insert or update or delete on cart
for each row
declare
l_qty number:=0;
l_pid prod.prod_id%type;
l_date date;
l_mileage number:=0;
l_mem_id member.mem_id%type;
begin
if inserting then
l_qty:=(:new.cart_qty);
l_pid:=(:new.cart_prod);
l_date:=(:new.cart_date);
l_mem_id:=(:new.cart_member); -- 마일리지 변경
elsif updating then
l_qty:=(:new.cart_qty - :old.cart_qty);
l_pid:=(:new.cart_prod);
l_date:=(to_date(substr(:new.cart.no,1,8)));
l_mem_id:=(:new.cart_member);
elsif deleting then
l_qty:= -(:old.cart_qty);
l_pid:=(:old.cart_prod);
l_date:=(to_date(substr(:old.cart.no,1,8)));
l_mem_id:=(:old.cart_member);
end if;
-- 재고처리
update remain a
set a.REMAIN_I=a.REMAIN_I+l_qty,
a.REMAIN_J_99=a.REMAIN_J_99-l_qty,
a.REMAIN_DATE=l_date
where a.prod_id=l_pid;
-- 마일리지 변경
select prod_mileage*l_qty into l_mileage
from prod
where prod_id=l_pid;
update member
set mem_mileage+l_mileage
where mem_id=mem_id;
exception when others then
dbms_output.put_line('예외발생 : '||sqlerrm);
end;
함수생성 : 장바구니번호(cart_no)를 자동으로 생성하는 함수
create or replace function fn_create_cart_no(p_date in date, p_mem_id in member.mem_id%type)
return varchar2
is
l_cart_no cart.cart_no%type;
l_flag number:=0;
l_no varchar2(8):=to_char(p_date,'yyyymmdd');
l_member member.mem_id%type;
begin
select count(*) into l_flag
from cart
where cart_no like l_no||'%';
if l_flag=0 then
l_cart_no:=l_no||trim('00001');
else
select max(cart_no) into l_cart_no
from cart
where cart_no like l_no||'%';
select cart_member into l_member
from cart
where cart_no=l_cart_no;
if l_member!=p_mem_id then
l_cart_no:=l_cart_no+1;
end if;
end if;
return l_cart_no;
end;
사용예) 오늘이 2020년 7월 28일인 경우 다음 매출자료를 cart 테이블에 저장하는 프로시져를 작성하시오.
-- 재료수불테이블 변경 -> 마일리지 변경
create or replace procedure proc_insert_cart(p_cmem in member.mem_id%type,
p_pid in prod.prod_id%type, p_qty number)
is
begin
insert into cart values(p_cmem,fn_create_cart_no(sysdate,p_cmem),p_qty,p_pid);
commit;
end;
------------------------------------
회원번호 상품번호 수량
------------------------------------
b001 P102000005 1
d001 P102000004 2
"" P101000003 1
"" P202000009 2
**prod_mileage : (매출단가 - 매입단가)*0.1%
select prod_id,
round((prod_price-prod_cost)*0.001)
from prod;
update prod
set prod_mileage=round((prod_price-prod_cost)*0.001);
update prod
set prod_mileage=10
where prod_mileage<10;
commit;
(실행) 기초 매입 매출 현재고
2020 P102000005 8 38 18+10 28-10 2020/07/31 mileage 130
2020 P102000005 8 38 28 18 2020/07/31 mileage 130
2020 P102000009 9 22 6+2 25-2 2020/04/30 mileage 16
2020 P102000009 9 22 8 23 2020/04/30 mileage 16
execute proc_insert_cart('d001','P102000005',10);
execute proc_insert_cart('d001','P102000009',2);
'DBMS' 카테고리의 다른 글
[DBMS/Oracle] 데이터베이스 오라클 (0) | 2023.04.03 |
---|---|
[DBMS/Oracle] 함수(User Defined function) (0) | 2023.03.18 |
[DBMS/Oracle] 저장 프로시져(STORED PROCEDURE) (0) | 2023.03.18 |
[DBMS/Oracle] IF문, 커서(CURSOR), 반복명령 (0) | 2023.03.18 |
[DBMS/Oracle] PL/SQL(Procedual LANGUAGE SQL) (0) | 2023.03.18 |