PS/SQL - TRIGGER

jsbak·2020년 9월 2일
0

DB

목록 보기
27/35

Trigger

  • 어떤 이벤트가 발생하며 자동적으로 실행되는 프로시져 일종
  • 사용형식
 CREATE [OR REPLACE] TRIGGER 트리거명
   BEFORE|AFTER INSERT|UPDATE|DELETE
   --before(10%↓), atfer(90%↑) 타이밍? Trigger 실행되는 내용이 명령문인데
   --insert, update, delete Event가 발생되었을때  그전에(before) 그후에(after)
   ON 테이블명 -- Event가 발생된 테이블명, Trigger에 사용되어질 테이블이 아님
   [FOR EACH ROW] --행(Row)단위 Trigger, 행 하나씩 다 Trigger가 발동
                  --문장단위 트리거는 한쿼리에 한번만 발동
                  -- 생략 -> 문장단위, 기술 -> 행단위
   [WHEN 조건] --트리거 조건, 트리거를 좀더 Detail하게 발동할때
 BEGIN
   명령문();
 END;
  • 1) 트리거 유형
    • (1) 문장단위 트리거 : 이벤트가 발생되었을 때 한번만 트리거 발생. 'FOR EACH ROW'생략
      :NEW, :OLE와 같은 의사레코드 사용 불가.
    • (2) 행단위 트리거 : 이벤트에 의해 여러 행이 영향 받는 경우 각 행마다 트리거 발생.
      'FOR EACH ROW' 기술해야 하고, :NEW, :OLD와 같은 의사레코드 사용 가능.
      ** 하나의 트리거가 종료 되지 않은 상태에서 다른 트리거 호출 불가, 무결성, 일관성을 유지하기 위해서
  • 2)트리거 조건
    • 행단위 트리거에서만 사용 가능
    • 이벤트가 발생된 때 보다 구체적인 데이터검색 조건 부여할 때 기술
      예) 분류테이블에 새로운 데이터 하나를 입력하라. 입력된 후 '새로운 분류코드가 입력됨'을 출력하는 트리거를 작성하시오.
      -- event: 새로운 데이터 하나 입력, trigger: '새로운 분류코드가 입력됨'을 출력
 (새로운 분류코드 - LPROD_ID : 10, LPROD_GU : 'P501', LPROD_NM : '농산물')
  **(trigger)**   
 create or replace trigger tg_lprod01
   after insert on lprod
   --for each row 한번만 할꺼니까 생략
 begin
   dbms_output.put_line('새로운 분류코드가 입력됨');
 end;
  **(Event)**
 insert into lprod values(10,'P501','농산물');
 select * from lprod;



☆퇴직자 정보를 저장하는 테이블을 생성하시오.


테이블명 : RETIRE


속성
employee_id number(6,0) FK/PK
emp_name varchar2(80 byte) FK
department_id number(6,0) FK
job_id varchar2(10 byte) fk
r_date date


create table RETIRE(
   employee_id     number(6,0),
   emp_name        varchar2(80),
   department_id   number(6,0),
   job_id          varchar2(10),
   r_date          date    not null, 
 constraint pk_retire primary key(employee_id, r_date),
 constraint fk_retire foreign key(employee_id)
   references employees(employee_id));
--drop table retire; 잘못만들었을때 활용

예) 사원번호 105번 사원을 퇴직처리하시오. 단 퇴직자는 사원테이블에서
-- 사원테이블의 퇴직일자를 오늘 날짜로 변경
퇴직자 정보를 퇴직자테이블(RETIRE)에 보관하시오.

 (Trigger)
 create or replace trigger tg_retire01
   before update on employees
   for each row
 begin
   insert into retire(employee_id, emp_name, department_id, job_id, r_date)    
   	values(:old.employee_id,:old.emp_name,:old.department_id,
    		:old.job_id,sysdate);
 end;
 (Event)
 update employees
    set retire_date = sysdate
  where employee_id = 105;
select * from employees where employee_id = 105;
select * from retire;

alter table remain1
 add constraint pk_remain1
     primary key(remain_year, remain_prod);
alter table remain1
 add constraint fk_remain1
     foreign key(remain_prod) references prod(prod_id)
      on delete cascade; --연쇄 삭제 제약조건 설정

예시) 오늘이 2005년 8월 1일이라고 가정하고 제품코드 'P201000007'인 상품을 회원번호가 'r001'인 회원이 5개를 구매 했다고 하자 cart테이블에 해당 데이터를 추가하고 재고 수불테이블을 변경하시오.

 (Trigger 생성)
 create or replace trigger tg_remain02 
   after insert on cart
   for each row
 declare
   v_qty number := 0;
   v_prod_id prod.prod_id%type;
 begin
   v_qty := :new.cart_qty;
   v_prod_id := :new.cart_prod;
   update remain
      set remain_o = remain_o + v_qty,
          remain_j_99 = remain_j_99 - v_qty,
          remain_date = to_date('20050801')
    where remain_year = '2005'
      and remain_prod = v_prod_id;
 end;
(Event 수행전)
  select * from remain
  where remain_prod = 'P201000007'
    and remain_year = '2005'

(Event)
insert into cart
 values('r001','2005080100001','P201000007',5);
(Event확인)
select * from remain
where remain_prod = 'P201000007'
  and remain_year = '2005'


★ 의사(pseudo)레코드

  • 행단위 트리거에만 사용 가능
    :NEW INSERT,UPDATE문에 사용.
    데이터가 삽입(갱신)될 때 새로 들어온 값, DELETE에는 모든 값이 NULL이다.
    :OLD DELETE,UPDATE문에 사용.
    데이터가 삭제(갱신)될 때 존재하고 있는 값, DELETE에는 INSERT에는 모든 값이 NULL이다.
    ★ 트리거 함수
    1) INSERTING : 트리거 문장이(Event) INSERT이면 참
    2) UPDATING : 트리거 문장(Event)이 UPDATE이면 참
    3) DELETING : 트리거 문장(Event)이 DELETE이면 참
    예시)
 create or replace trigger tg_remain02 
   after insert or update or delete 
   on cart
   for each row
 declare
   v_qty number := 0;
   v_prod_id prod.prod_id%type;
 begin
   -- 3가지 유형의 이벤트가와도 update문 하나만 쓸수 있게 변수를 둠??
   IF INSERTING THEN
     v_qty := :new.cart_qty;
     v_prod_id := :new.cart_prod;
   elsif UPDATING THEN
     v_qty := :new.cart_qty - :old.cart_qty; 
     v_prod_id := :new.cart_prod;
   elsif DELETING THEN
     v_qty := :old.cart_qty;
     v_prod_id := :old.cart_prod;
   end if;
   update remain
      set remain_o = remain_o + v_qty,
          remain_j_99 = remain_j_99 - v_qty,
          remain_date = to_date('20050801')
    where remain_year = '2005'
      and remain_prod = v_prod_id;
 end;
 (ㅇㅣ벤트)
 update cart
    set cart_qty = cart_qty + 2
  where cart_no = '2005080100001'
    and cart_prod = 'P201000007'; 
--
select * from cart where cart_no = '2005080100001';
select * from remain where remain_prod= 'P201000007';
 (8개를 반품)
update cart
   set cart_qty = cart_qty - 8
 where cart_no = '2005080100001'
   and cart_prod = 'P201000007'; 
profile
끄적끄적 쓰는곳

0개의 댓글