MySQL

트리거(Trigger).MySQL

john_ 2023. 2. 10. 17:15
728x90

2023.02.10 - [MySQL] - 커서(Cursor).MySQL

 

커서(Cursor).MySQL

2023.02.10 - [MySQL] - 스토어드 함수(Stored Function) 스토어드 함수(Stored Function) 2023.02.10 - [MySQL] - 스토어드 프로시저(Stored Procedure).MySQL 스토어드 프로시저(Stored Procedure).MySQL 2023.02.08 - [MySQL] - 스토어드

less-go.tistory.com

 

이전 글에서 계속 됩니다.

 


트리거(Trigger)의 개요

트리거란?

  • 사전적 의미로 '방아쇠'
  • 방아쇠 당기면 '자동'으로 총알이 나가듯이 테이블에 무슨 일이 일어나면 '자동' 으로 실행
  • 제약 조건과 더불어 데이터 무결성을 위해 MySQL에서 사용 할 수 있는 기능
  • 테이블에 DML문(Insert, Update, Delete 등) 이벤트가 발생될 때 작동
  • 테이블에 부착되는 프로그램 코드
  • 직접 실행 불가
    • 테이블에 이벤트 일어나야 자동 실행
  • In, Out 매개 변수를 사용할 수 없습니다.
  • MySQL은 View에 트리거를 부착 할수 없습니다.

-- 트리거 : 테이블에 DML(i, u, d)문이 실행 될때 자동으로 SQL문을 실행
create database if not exists testdb;

use testdb;

create table if not exists testtbl ( id int, txt varchar(10));

insert into testtbl values (1, '레드벨벳');
insert into testtbl values (2, '잇지');
insert into testtbl values (3, '블랙핑크');

select * from testtbl;

drop trigger if exists testtrg;
-- 트리거 부착
DELIMITER //
create trigger testtrg			-- 트리거를 하나 생성
	after delete				-- DELETE를 실행하고 난 뒤 트리거 작동
    on testtbl					-- testTbl에 트리거를 부착
    for each row				-- 한 행씩 실행이 되게 설정
begin
	set @msg = '가수 그룹이 삭제됨';			-- 트리거가 일어 났을때 실행할 구문
END	//
DELIMITER ;

-- 데이터를 삽입, 수정, 삭제
set @msg = '';
insert into testtbl values(4,',마마무');			-- 데이터 입력시 아무일도 일어 나지 않습니다.
select @msg;
update testtbl set txt = '블핑' where id = 3;	-- 수정 : 아무일이 일어나지 않음
select @msg;
delete from testtbl where id = 4;				-- 삭제 : 트리거 작업이 일어납니다.
select @msg;

-- 데이터를 삽입 했을때 ------------------------
drop trigger if exists trig_in;

delimiter //
create trigger trig_in
	after insert
    on testtbl
    for each row
begin
	set @msg1 = '가수 이름이 추가됨';
end	//
delimiter ;

set @msg1 = '';
insert into testtbl values (4, '마마무');
select @msg1;

select * from testtbl;

delete from testtbl where id = 4;

-- 수정 시의 트리거 발동 ----------------------------------
drop trigger if exists trig_upd;

delimiter //
create trigger trig_upd
	after update
    on testtbl
    for each row
begin
	set @msg2 = '가수 그룹이 수정됨'; 	-- 트리거 실행시 작동하는 코드
end //
delimiter ;

set @msg2 = '';
update testtbl set id = 3 where id =1;
select * from testtbl;
select @msg2;

 


트리거의 종류

AFTER 트리거

  • 테이블에 INSERT, UPDATE, DELETE 등의 작업이 일어났을 때 작동
  • 이름이 뜻하는것  처럼 해당 작업 후(AFTER) 작동

 

BEFORE 트리거

  • BEFORE 트리거는 이벤트가 발생하기 전에 작동
  • INSERT, UPDATE, DELETE 세 가지 이벤트로 작동

 

-- AFTER트리거 사용
-- 회원 테이블에 update, delete 를 시도 하면 수정 또는 삭제된 데이터를 별도의 테이블에 보관하고 변경일자와 변경인을 기록합니다.
use sqldb;

DROP TABLE if exists backup_usertbl;
create table backup_usertbl
(
	userid char(8) not null primary key,
    name varchar(10) not null,
    birthyear int not null,
    addr char(2) not null,
    mobile1 char(3),
    mobile2 char(8),
    height smallint,
    mDate date,
    modType char(2),		-- 변경된 타입 : 수정 또는 삭제
    modDate date,			-- 변경된 날짜
    modUser varchar(256)	-- 변경한 사용자
);

-- 변경(update)과 삭제(delete)가 발생할 때 작동하는 트리거
-- 변경 발생시 트리거
DROP TRIGGER IF EXISTS backUsertbl_UpdateTrg;

delimiter //
create trigger backUserTbl_UpdateTrg
	after update	-- 업데이트 이후에 동작
    on userTbl		-- usertbl에 부착
    for each row
begin
	insert into backup_usertbl values(OLD.userid, OLD.name, OLD.birthyear,
    OLD.addr, OLD.mobile1, OLD.mobile2, OLD.height, OLD.mDate,
    '수정', curdate(), current_user());
end	//
delimiter ;

select * from backup_usertbl;

-- 삭제 발동시 작동 트리거

drop trigger if exists backusertbl_deletetrg;

delimiter //
create trigger backUserTbl_DeleteTrg
	after delete	-- 업데이트 이후에 동작
    on userTbl		-- usertbl에 부착
    for each row
begin
	insert into backup_usertbl values(OLD.userid, OLD.name, OLD.birthyear,
    OLD.addr, OLD.mobile1, OLD.mobile2, OLD.height, OLD.mDate,
    '삭제', curdate(), current_user());
end	//
delimiter ;

update usertbl set addr = '몽고' where userid = 'jkw';
delete from usertbl where height = 177;

select * from backup_usertbl;

AFTER 트리거의 사용

  • TRUNCATE TABLE 테이블이름
    • DELETE FROM <테이블이름> 문과 동일한 효과
    • DML문이 아니라 트리거를 작동시키지 않습니다.
  • SIGNAL SQLSTATE '45000' 문
    • 사용자가 오류를 강제로 발생시키는 함수
    • 사용자가 정의한 오류 메시지 출력
    • 사용자가 시도한 INSERT는 롤백됩니다.

트리거가 생성하는 임시 테이블

  • INSERT, UPDATE, DELETE 작업이 수행되면 임시 사용하는 시스템 테이블.
  • 이름은 'NEW'와 'OLD'

 


BEFORE 트리거의 사용

  • 테이블에 변경이 가해지기 전 작동
  • BEFORE 트리거 활용 예
    • BEFORE INSERT 트리거를 부착 해놓으면 입력될 데이터 값을 미리 확인해서 문제가 있을 경우에 다른 값으로 변경 합니다.
  • BEFORE 트리거 실습
    • 값이 입력될 때, 출생년도의 데이터를 검사 해서 데이터에 문제가 있으면 값을 변경시켜서 입력시키는 BEFORE INSERT 트리거 작성
-- BEFORE 트리거 : 트리거 실행 이전에 SQL 실행 - 입력 되는 데이터의 문제가 있는지 확인해서 수정
-- 1900 년 이전의 데이터가 입력되면 0으로 표기, 현재년도 보다 더 높은 년도가 입력 ㅗ디면 현재 년도로 수정
-- SQLDB.sql을 실행해서 sqldb 초기화
use sqldb;

drop trigger if exists userTbl_beForeInsertTrg;

delimiter //
create trigger userTbl_BeforeInserTrg
	before insert
	on unsertbl
    for each row
begin
	if new.birthYear < 1900 then		-- 1900년 이전의 연도가 입력시 0으로 표기
		set new.birthYear = 0;
	elseif new.birthYear > Year(curdate()) then		-- 현재 년도보다 더 큰 미래 년도가 입력시 현재 년도로 변경
		set new.birthYear = Year(curdate());
	end if;
end //
delimiter ;

insert into usertbl values ('AAA','에이', 1877, '서울', '011', '1112222', 181, '2022-12-25');
insert into usertbl values ('BBB','비이', 2977, '경기', '011', '1113333', 171, '2019-3-25');

select * from usertbl;

-- 생성된 트리거 확인
show triggers from sqldb;

 


기타 트리거

다중 트리거(Multiple Triggers)

  • 하나의 테이블에 동일한 트리거가 여러 개 부착되어 있는 것
    • ex) AFTER INSERT <트리거>  ->  한 개 테이블에 2개 이상부착

 

중첩 트리거(Nested Triggers)

  • 트리거가 또 다른 트리거를 작동 시키는것

  • 트리거의 작동 순서
    • 하나의 테이블에 여러 개의 트리거가 부착된 경우 트리거의 작동 순서 지정 가능

 

-- 중첩 트리거
-- 구매 테이블에서 구매가 있을때(insert) 물품테이블에 개수를 감소

DROP TRIGGER IF EXISTS orderTrg;

delimiter //
create trigger orderTrg      -- 구매 트리거
   after insert         -- orderTbl에 insert : 구매자가 물품 구매가 있을때
    on orderTbl
    for each row
begin
   update prodTbl set account = account - NEW.orderamount
         where prodName = NEW.prodName;      -- 제품 테이블의 재고수량을 주문수량을 제외 하고 재고수량 수정
end //   
delimiter ;



delimiter //
create trigger prodTrg      -- 물품 트리거
   after update         
    on prodTbl
    for each row
begin
   DECLARE orderAmount int;   -- 주문 개수 : (변경 전의 개수 - 변경 후의 개수)
    SET orderAmount = old.account - new.account;
    insert into deliverTbl (prodName, account) values(new.prodName, orderAmount);
end //   
delimiter ;

select * from ordertbl;
select * from prodtbl;
select * from delivertbl;

insert into ordertbl values (NULL, 'JOHN', '배', 5)

 

728x90

'MySQL' 카테고리의 다른 글

파티션.MySQL  (0) 2023.02.10
전체 텍스트 검색.MySQL  (0) 2023.02.10
커서(Cursor).MySQL  (0) 2023.02.10
스토어드 함수(Stored Function)  (0) 2023.02.10
스토어드 프로시저(Stored Procedure).MySQL  (0) 2023.02.10