본문 바로가기
카테고리 없음

mySQL 종합 예제 (기본 문법 및 프로시저, 트리거)

by prlkt5200 2024. 9. 27.
반응형

여기 나온 문제는 테이블이 있어야 하기에 같이  테이블 생성 코드도 올렸습니다.

 

아래는 테이블 생성 예제입니다.

drop database if exists madang;
create database madang;
use madang;
create table book
(
bookid int auto_increment not null primary key,
bookname varchar(20) not null,
publisher varchar(10) not null,
price int not null
);

insert into book values(null, '축구의 역사', '굿스포츠', 7000);
insert into book values(null, '축구아는 여자', '나무수', 13000);
insert into book values(null, '축구의 이해', '대한 미디어', 7000);
insert into book values(null, '골프 바이블', '대한 미디어', 35000);
insert into book values(null, '피겨 교본', '굿스포츠', 8000);
insert into book values(null, '역도 단계별 기술', '굿스포츠', 6000);
insert into book values(null, '야구의 추억', '이상 미디어', 20000);
insert into book values(null, '야구를 부탁해', '이상 미디어', 13000);
insert into book values(null, '올림픽 이야기', '삼성당', 7500);
insert into book values(null, 'Olympic Champions', 'Pearson', 13000);


create table customer
( 
custid int auto_increment not null primary key,
name varchar(10) not null,
address varchar(20) not null,
phone char(13)
);

insert into customer values (null, '박지성','영국 맨체스타', '000-5000-0001');
insert into customer values (null, '김연아','대한민국 서울', '000-6000-0001');
insert into customer values (null, '장미란','대한민국 강원도', '000-7000-0001');
insert into customer values (null, '추신수','미국 클리브랜드', '000-8000-0001');
insert into customer values (null, '박세리','대한민국 대전', null);

create table orders
(
orderid int auto_increment not null primary key,
custid int not null,
bookid int not null,
saleprice int not null,
orderdate date not null,
foreign key(custid) references customer(custid),
foreign key(bookid) references book(bookid)
);

insert into orders values(null, 1,1, 6000, '2014-07-01');
insert into orders values(null, 1,3, 21000, '2014-07-03');
insert into orders values(null, 2,5, 8000, '2014-07-03');
insert into orders values(null, 3,6, 6000, '2014-07-04');
insert into orders values(null, 4,7, 20000, '2014-07-05');
insert into orders values(null, 1,2, 12000, '2014-07-07');
insert into orders values(null, 4,8, 13000, '2014-07-07');
insert into orders values(null, 3,10, 12000, '2014-07-08');
insert into orders values(null, 2,10, 7000, '2014-07-09');
insert into orders values(null, 3,8, 13000, '2014-07-10');

 

아래는 테이블 활용 예제입니다.

순차적으로 하나씩 읽어가면서 진행해보시면 됩니다.

 
 -- 주문 테이블에 주문 수량을 의미하는 필드를 새로 생성합니다. 또한 이는 기본값이 있습니다.
 alter table orderstbl add column ordercount int not null default 0;
 


-- 북 테이블에 재고를 의미하는 필드를 만들어줍니다.
 Alter table booktbl add column count int not null default 100; 
 



-- 고객 테이블에 구매실적에 따른 등급을 저장할 필드를 생성합니다.
 Alter table customertbl add column vip_grade varchar(10) not null default 'bronze'; 




-- 고객 테이블에서 등급의 변경이 있을 시 관련 고객의 정보와 등급에 관련된 정보를 저장할 테이블을 생성합니다.
drop table if exists vip_history;
 CREATE TABLE vip_history (
    no INT AUTO_INCREMENT PRIMARY KEY,
    cusid INT NOT NULL,
    update_date DATE,
    past_vip_grade VARCHAR(10),
    now_vip_grade VARCHAR(10),
    FOREIGN KEY (cusid)
        REFERENCES customertbl (cusid)
); 


-- 고객의 등급을 변경시키는 프로시저입니다. 이것은 길기에 각 줄로 주석을 달겠습니다.
-- 만약 프로시저가 존재하면 삭제시키는 것을 진행합니다.
DROP PROCEDURE IF EXISTS vip_change_proc;
delimiter $$
-- 프로시저를 생성합니다.
 CREATE PROCEDURE vip_change_proc()
 begin
 
 -- 커서가 반복문을 돌면서 레코드에서 가져오는 값을 저장하기 위한 변수 두개입니다.
 	declare cus_id int;
 	declare price INT;
    
    
    -- 반복문을 돌면서 그 안에 조건문을 통해 받은 값을 저장할 변수입니다.
	declare ch_vip_grade varchar(10);
     
    -- 커서가 반복문을 빠져나오기 위한 조건문에서 사용할 값입니다. 
	declare endOfRow Boolean default false;
     
     -- 커서를 생성하고 cusid를 기준으로 그룹핑한 주문테이블에서 cusid, sum(집계함수) 필드를 표시하는 테이블이랑 연결해줍니다. 
     declare userCursor CURSOR FOR select cusid,sum(saleprice * ordercount) from orderstbl group by cusid;
 	-- 만약 커서가 반복문을 돌다가 not found 에러를 발견시 endofrow를 true로 바꿔줍니다.
    declare continue handler for not found set endOfRow = true;
     
     -- 커서를 사용할 준비를 해줍니다.
    OPEN userCursor;
    
    -- 반복문이고 vip_loop라벨이 붙어있습니다.
     vip_loop : LOOP
     
     -- 커서가 본인이 부착된 테이블의 레코드를 반복문에 따라서 순차적으로 돌게 되는데, 그때 into 다음에 나오는 변수에 값을 지정해줍니다.
 		FETCH userCursor INTO cus_id,price;
        
        -- 커서가 돌다가 not found 에러가 나오면 endofrow가 true가 되면서 leave문이 실행이됩니다.
        if endOfRow then
 			LEAVE vip_loop;
 		END IF;
         
         -- java 스위치 케이스문과 똑같습니다. 해당 조건에 맞는 쿼리를 실행합니다.
         -- 커서가 돌면서 받은 price 값으로 조건에 맞는 값을 등급 변수에 넣어줍니다.
         CASE
 			WHEN (price >= 30000) then set ch_vip_grade = 'vip';
             WHEN (price < 30000 and price >= 20000) then set ch_vip_grade = 'gold';
             WHEN (price < 20000 and price >= 10000) then set ch_vip_grade = 'silver';
 			else set ch_vip_grade = 'bronze';
 		END CASE;
        
 -- customer 테이블에서의 등급 컬럼을 수정해주는 과정입니다.        
UPDATE customertbl 
SET 
    vip_grade = ch_vip_grade
WHERE
-- 커서가 주문테이블을 반복문으로 돌면서 받아오는 cusid를 cus_id로 저장해줬으며, 그 값을 다시 고객테이블에 cusid와 비교해주는 값입니다.
-- 그리고 그 조건에 해당하는 레코드(1개만 나올 것이다)의 등급 컬럼을 수정해줍니다.
    cusid = cus_id;
    
    -- 여기까지 반복문이 실행됩니다.
 		END LOOP vip_loop;
        -- cursor에서 더이상 값이 출력될 것이 없으면 반복문을 빠져나와서 커서를 닫아줄 것입니다.
         CLOSE userCursor;
 end $$ DELIMITER ;
 CALL vip_change_proc();
 
 

-- 고객등급에서 수정이 일어나게 되면 실행되는 트리거입니다.
-- 예를 들어 위의 프로시저가 실행하면 결국 커서를 반복시켜서 가져온 값들로 비교하고, 등급컬럼을 수정. 하게 되는데 이때 이 트리거도 자연스럽게 실행이 됩니다.
 DROP TRIGGER IF EXISTS vip_change_Trg;
 delimiter $$
 create trigger vip_change_Trg
 -- 고객 테이블에서 수정이 발생될 시 트리거가 작동됩니다.
 after update
 on customertbl
 for each row
 begin
	-- 트리거의 실행문입니다. 간단히 말해서 고객테이블의 등급이 변경시, 고객등급이 변경되었을 때의 정보들을 표시하는 테이블에 insert를 해줍니다.
 	INSERT INTO vip_history values (null,cusid,curdate(),old.vip_grade,new.vip_grade);
     
 end $$
 delimiter ;

-- 북테이블의 서적 개수를 변경시켜주는 트리거입니다.
-- 주문 테이블에 값을 insert 해주면 이 트리거가 작동하게 됩니다.
 DROP TRIGGER IF EXISTS bookCntTrg;
 DELIMITER //
 CREATE TRIGGER bookCntTrg
 AFTER insert
 ON orderstbl
 FOR EACH ROW 
 BEGIN 
 -- 북 테이블의 카운트 값은 기존 카운트(재고수량)에 주문테이블에 insert 하면서 받아온 값을 빼준 것이다.
 -- 그리고 그 값을, 
 -- 북테이블의 아이디와 주문테이블에 insert하면서 받는 주문한 책의아이디(북아이디)랑 같은 레코드에서 수정합니다.
 update booktbl set count = count - new.ordercount where bookid = new.bookid;

 END // 
 DELIMITER ;

-- 주문테이블에서 insert시 북테이블의 재고 수량이 변경되는 트리거가 발생합니다.
 INSERT INTO orderstbl values (null,1,1,6000,curdate(),5);
    

-- 주문테이블의 실적이 생기면 다시 고객등급을 업데이트 하는 트리거입니다.
-- 고객등급을 변경시켜주는 프로시저랑 비슷합니다.
 DROP TRIGGER IF EXISTS updateVipTrg;
 DELIMITER //
 CREATE TRIGGER updateVipTrg
 AFTER insert
 ON orderstbl
 FOR EACH ROW 
 BEGIN 
 
 -- 위의 고객등급 변경 프로시저를 참고해주시기 바랍니다.
 	declare cus_id int;
 	declare price INT;
    declare ch_vip_grade varchar(10);
    declare endofrow boolean default false;

	
declare userCursor CURSOR FOR select cusid,sum(saleprice * ordercount) from orders group by custid;
 	declare continue handler for not found set endOfRow = true;
     
     OPEN userCursor;
     vip_loop : LOOP
 		FETCH userCursor INTO cus_id,price;
         if endOfRow then
 			LEAVE vip_loop;
 		END IF;
        
         CASE
			WHEN (price >= 30000) then set ch_vip_grade = 'vip';
             WHEN (price < 30000 and price >= 20000) then set ch_vip_grade = 'gold';
             WHEN (price < 20000 and price >= 10000) then set ch_vip_grade = 'silver';
 			else set ch_vip_grade = 'bronze';
 		END CASE;
             update customertbl set vip_grade = ch_vip_grade where custid = cust_id;
 		END LOOP vip_loop;
         CLOSE userCursor;
 END // 
 DELIMITER ;


-- 주문테이블에서 insert 시 고객등급을 변경시켜주는 트리거가 실행됩니다.
-- 그리고 위에서 북테이블 재고수량 변경 트리거도 같이 발생합니다.
  INSERT INTO orderstbl values (null,5,1,6000,curdate(),3);


select * from orderstbl;
   select * from booktbl;
  SELECT * FROM customertbl;
  select * from vip_history;
반응형