본문 바로가기

SQL

Oracle_16. TRIGGER

 

 

더보기

 <TRIGGER> 트리거
    내가 트리거로 지정한 테이블에 DML문(INSERT, UPDATE, DELETE) 등에 의해
    변경사항이 발생할 경우
    "자동으로" 매번 실행할 내용을 정의해 둘 수 있는 객체
    
    EX) 
    회원 탈퇴시 기존의 회원테이블에 데이터를 DELTE한 후 
    곧바로 탈퇴된 회원들만 따로 보관하는 테이블에 자동으로 INSERT 시킬때
    
    신고 횟수가 일정수를 넘었을때 회원을 블랙리스트 처리 하고자 할때
    
    입출고에 대한 데이터가 기록될 때마다 해당 상품에 대한 재고수량을 
    매번 수정해줘야 할때

 

* 트리거 종류
    SQL문 시행시기에 따른 분류
    > BEFORE TRIGGER : 내가 지정한 테이블에 DML(INSERT, UPDATE, DELETE)가
                    발생되기 전에 트리거 먼저 실행
    
    > AFTER TRIGGER : 내가 지정한 테이블에 DML가 발생된 후 트리거 실행
    
    
    * SQL문에 영향을 받는 각 행에 따른 분류
    > STATEMENT TRIGGER(문장트리거) : DML이 발생한 SQL문에 딱 한 번만 트리거를 실행
    > ROW TRIGGER(행 트리거) : 해당 SQL문을 실행할 때마다 매번 트리거 실행
        :OLD - BEFORE UPDATE, BEFORE DELETE에서 사용
        :NEW - AFTER INSERT, AFTER UPDATE에서 사용
    
    
* 트리거 생성구문
    [표현식]
    CREATE OR REPLACE TRIGGER 트리거명
    BEFORE|AFTER INSERT|DELETE|UPDATE ON 테이블명
    [FOR EACH ROW] <- 행트리거 만들때 구문(없으면 문장트리거)
    BEGIN
        실행내용(위 지정한 이벤트 발생시 자동으로 실행할 구문)
    END;
    /

 

 

더보기

트리거 장점
    1. 데이터 추가, 수정, 삭제시 자동으로 데이터를 관리해줌으로써 무결성 보장
    2. DB 관리의 자동화
    
* 트리거 단점
    1. 빈번한 추가, 수정, 삭제시 ROW의 삽입, 추가, 삭제가 함께 실행되므로 성능상 좋지 못하다.
    2. 관리적 측면에서 형상관리가 불가능하다.
    3. 트리거를 남용하게 되는 경우 예상하지 못하는 상황이 발생할 수 있고 처리하기 힘들다.

 

-- EMPLOYEE 테이블에 새로운 행이 추가될 때마다 자동으로 메세지를 출력해주는 트리거 정의하기

CREATE OR REPLACE TRIGGER TRG_01
AFTER INSERT ON EMPLOYEE
BEGIN
    DBMS_OUTPUT.PUT_LINE('신입사원님 환영합니다.');
END;
/

INSERT INTO EMPLOYEE(EMP_ID, EMP_NAME, EMP_NO, JOB_CODE, SAL_LEVEL)
VALUES (905, '홍길동', '990101-1234567', 'J1', 'S1');

SELECT * FROM EMPLOYEE;

 

 

 

-- 상품 입출고 관련 예시
-- 필요한 테이블 및 시퀀스 생성


-- 1. 상품에 대한 데이터를 보관할 테이블 생성(TB_PRODUCT)
CREATE TABLE TB_PRODUCT (
    PCODE NUMBER PRIMARY KEY,   -- 코드
    PNAME VARCHAR2(30) NOT NULL,    -- 상품명
    BRAND VARCHAR2(30) NOT NULL,    -- 브랜드명
    PRICE NUMBER,           -- 가격
    STOCK NUMBER DEFAULT 0  -- 재고
    );


-- 상품번호용 시퀀스 생성
CREATE SEQUENCE SEQ_PCODE
START WITH 200
INCREMENT BY 5;


-- 샘플데이터 추가
INSERT INTO TB_PRODUCT VALUES (SEQ_PCODE.NEXTVAL, '갤럭시Z플립5', '삼성', 1350000, DEFAULT);
INSERT INTO TB_PRODUCT VALUES (SEQ_PCODE.NEXTVAL, '갤럭시11', '삼성', 1000000, 10);
INSERT INTO TB_PRODUCT VALUES (SEQ_PCODE.NEXTVAL, '아이폰14', '애플', 1500000, 20);

COMMIT;


-- 2. 상품 입출고 상세 이력 테이블 생성(TB_PRO_DETAIL)
-- 어떤 상품이 어떤 날짜에 몇개가 입고 또는 출고 되었는지 데이터를 기록용 테이블

CREATE TABLE TB_PRO_DETAIL (
    DCODE NUMBER PRIMARY KEY,   -- 이력번호
    PCODE NUMBER REFERENCES TB_PRODUCT, -- 상품번호
    PDATE DATE NOT NULL,    -- 상품입출고일
    AMOUNT NUMBER NOT NULL,  -- 입출고 수량
    STATUS CHAR(6) CHECK(STATUS IN ('입고','출고')) -- 상태(입고,출고)
    );


-- 입출고용 시퀀스 생성
CREATE SEQUENCE SEQ_DCODE;


-------------- 트리거 적용 전 --------------------

-- 200번 상품이 오늘 날짜로 10개 입고
INSERT INTO TB_PRO_DETAIL
VALUES (SEQ_DCODE.NEXTVAL, 200, SYSDATE, 10, '입고');

-- 입고내용 확인
SELECT * FROM TB_PRO_DETAIL; -- 입고내용 적용됨
SELECT * FROM TB_PRODUCT;   -- 입고내용 적용안됨


-- TB_PRODUCT 테이블에 200번 상품의 재고수량 10개 직접 증가시키기
UPDATE TB_PRODUCT 
    SET STOCK = STOCK +10
    WHERE PCODE = 200;

SELECT * FROM TB_PRODUCT;  -- 입고내용 직접 적용시킴



-------------- 트리거 적용하기  --------------------

-- TB_PRO_DETAIL 테이블에 상품이 INSERT 되면 
-- TB_PRODUCT 테이블에 매번 자동으로 재고수량이 UPDATE 되게끔 트리거 정의하기

/*
    - 상품이 입고된 경우 -> 입고된 상품을 찾아서 재고수량 증가시키기(UPDATE)    
    - 상품이 출고된 경우 -> 출고된 상품을 찾아서 재고수량 감소시키기(UPDATE)
*/

CREATE OR REPLACE TRIGGER TRG_02
AFTER INSERT ON TB_PRO_DETAIL
FOR EACH ROW 
BEGIN
    -- 상품이 입고되었는지 출고되었는지 확인하기
    IF (:NEW.STATUS = '입고')
        THEN
        UPDATE TB_PRODUCT
            SET STOCK = STOCK + :NEW.AMOUNT
            WHERE PCODE = :NEW.PCODE;
    ELSE
        UPDATE TB_PRODUCT
            SET STOCK = STOCK - :NEW.AMOUNT
            WHERE PCODE = :NEW.PCODE;
    END IF;    
END;
/

-- 200번 상품이 오늘 날짜로 10개 입고
INSERT INTO TB_PRO_DETAIL
VALUES (SEQ_DCODE.NEXTVAL, 200, SYSDATE, 10, '입고');

SELECT * FROM TB_PRODUCT;
-- 입고시 자동으로 재고 수량이 적용된다.

 

 

 

 

 

'SQL' 카테고리의 다른 글

Oracle_15. PROCEDURE, FUNCTION  (1) 2023.12.08
Oracle_14. PL/SQL  (1) 2023.12.08
Oracle_13. Object<INDEX>  (1) 2023.12.08
JDBC_JAVA와 ORACLE 연결하기  (0) 2023.12.01