MySQL

스토어드 프로시저(Stored Procedure).MySQL

john_ 2023. 2. 10. 11:37
728x90

2023.02.08 - [MySQL] - 스토어드 프로시저(Procedure)를 이용한 프로그래밍.MySQL

 

스토어드 프로시저(Procedure)를 이용한 프로그래밍.MySQL

스토어드 프로시저를 이용한 프로그래밍 IF...ELSE 조건에 따라 분기 참 / 거짓 두가지만 있기에 2중분기 한 문장 이상 처리되어야 할때 begin...end로 묶어주기 형식 부울 표현식 부분이 참이면 SQL문

less-go.tistory.com

 

 위 글과 관계있는 내용입니다.


스토어드 프로시저(Stored Procedure)의 개요

  • 스토어드 프로시저(Stored Procedure, 저장 프로시저)
    • MySQL에서 제공되는 프로그래밍 기능
    • 쿼리문의 집합으로 어떠한 동작을 일괄 처리하기 위한 용도로 사용
    • 쿼리 모듈화
      • 필요할 때마다 홀출만 하면 훨씬 편리하게 MySQL 운영
      • CALL 프로시저_이름() 으로 호출
  • 기본 형식

 


스토어드 프로시저의 수정과 삭제

스토어드 프로시저의 수정과 삭제

  • 수정 : ALTER PROCEDURE
  • 삭제 : DROP PROCEDURE

매개 변수의 사용

  • 입력 매개 변수를 지정하는 형식

  • 입력 매개 변수가 있는 스토어드 프로시저 실행방법

  • 출력 매개 변수를 지정하는 방법

  • 출력 매개 변수에 값 대입하기 위해 주로 SELECT...INTO 문 사용
  • 출력 매개 변수가 있는 스토어드 프로시저 실행 방법

 


스토어드 프로시저의 특징

MySQL의 성능 향상

  • 긴 쿼리가 아니라 짧은 프로시저 내용만 클라이언트에서 서버로 전송
    • 네트워크 부하 줄임으로 MySQL의 성능 향상

 

유지관리가 간편

  • 응용 프로그램에서는 프로시저만 호출
    • 데이터베이스에서 관련된 스토어드 프로시저의 내용 수정/유지보수

 

모듈식 프로그래밍 가능

  • 언제든지 실행 가능
  • 스토어드 프로시저로 저장해 놓은 쿼리의 수정, 삭제 등의 관리가 수월합니다.
  • 모듈식 프로그래밍 언어와 동일한 장점을 갖습니다

보안 강화

  • 사용자 별로 테이블 접근 권한 주지않고 스토어드 프로시저에만 접근 권한을 주어 보안을 강화
    • 뷰 또한 스토어드 프로시저와 같이 보안 강화가 가능합니다.

drop database if exists sqld;

create database if not exists sqldb;

use sqldb;

create table usertbl(
   userID      char(8)         not null   primary key,   -- 사용자 아이디(PK)
    name      varchar(10)      not null,               -- 이름
    birthYear   int          not null,               -- 출생년도
    addr      char(2)         not null,               -- 지역 : 경기, 서울, 경남 식으로 2글자 입력
    mobile1      char(3),                           -- 휴대폰의 국번 : 011, 016, 017, 018, 019, 010               
    mobile2      char(8),                           -- 휴대폰의 나머지 전화번호
    height      smallint,                           -- 키
    mDate      date                              -- 회원 가입일
 );
 
 -- 회원 구매 테이블 (buytbl)
 create table buytbl(
   num         int         auto_increment not null primary key,   -- 순번(PK)
   userID      char(8)      not null,                        -- 아이디(FK)
    prodName   char(6),                                 -- 물품명
    groupName   char(4),                                 -- 분류
    price      int         not null,                        -- 단가
    amount      smallint   not null,                        -- 수량
    foreign key (userID) references usertbl(userID)
);

show tables;

INSERT INTO usertbl VALUES('LSG', '이승기', 1987, '서울', '011', '1111111', 182, '2008-8-8');
INSERT INTO usertbl VALUES('KBS', '김범수', 1979, '경남', '011', '2222222', 173, '2012-4-4');
INSERT INTO usertbl VALUES('KKH', '김경호', 1971, '전남', '019', '3333333', 177, '2007-7-7');
INSERT INTO usertbl VALUES('JYP', '조용필', 1950, '경기', '011', '4444444', 166, '2009-4-4');
INSERT INTO usertbl VALUES('SSK', '성시경', 1979, '서울',  null,  NULL    , 186, '2013-12-12');
INSERT INTO usertbl VALUES('LJB', '임재범', 1963, '서울', '016', '6666666', 182, '2009-9-9');
INSERT INTO usertbl VALUES('YJS', '윤종신', 1969, '경남',  NULL,  NULL    , 170, '2005-5-5');
INSERT INTO usertbl VALUES('EJW', '은지원', 1972, '경북', '011', '8888888', 174, '2014-3-3');
INSERT INTO usertbl VALUES('JKW', '조관우', 1965, '경기', '018', '9999999', 172, '2010-10-10');
INSERT INTO usertbl VALUES('BBK', '바비킴', 1973, '서울', '010', '0000000', 176, '2013-5-5');
INSERT INTO buytbl VALUES(NULL, 'KBS', '운동화',  NULL, 30,   2);
INSERT INTO buytbl VALUES(NULL, 'KBS', '노트북', '전자', 1000,   1);
INSERT INTO buytbl VALUES(NULL, 'JYP', '모니터', '전자', 200,   1);
INSERT INTO buytbl VALUES(NULL, 'BBK', '모니터', '전자', 200,   5);
INSERT INTO buytbl VALUES(NULL, 'KBS', '청바지', '의류', 50,   3);
INSERT INTO buytbl VALUES(NULL, 'BBK', '메모리', '전자', 80,   10);
INSERT INTO buytbl VALUES(NULL, 'SSK', '책'   , '서적', 15,   5);
INSERT INTO buytbl VALUES(NULL, 'EJW', '책'   , '서적', 15,   2);
INSERT INTO buytbl VALUES(NULL, 'EJW', '청바지', '의류', 50,   1);
INSERT INTO buytbl VALUES(NULL, 'BBK', '운동화',  NULL, 30,   2);
INSERT INTO buytbl VALUES(NULL, 'EJW', '책'   , '서적', 15,   1);
INSERT INTO buytbl VALUES(NULL, 'BBK', '운동화',  NULL, 30,   2);


 -- 프로시저 생성 
 
delimiter $$
create procedure userproc1(in username varchar(10))	-- in 입력 매개 변수
begin
	select * from usertbl where name = username;
end $$
delimiter ;

call userproc1('조관우');

drop procedure if exists userproc2;

delimiter $$
create procedure userproc2(in userbirth int, in userheight int)		-- in 입력 매개 변수 2개
begin
	select * from usertbl
		where birthyear > userbirth and height > userheight;
end $$
delimiter ;

call userproc2(1970, 175);

-- 출력 매개 변수 사용(in 1, out 1)
drop procedure if exists userproc3;

delimiter $$
create procedure userproc3(in txtvalue char(10), out outValue int)		-- txtvalue 변수를 들고들어가서 int형 outvalue를 출력
begin
	insert into testTBL value(null, txtvalue);
    select max(id) into outvalue from testtbl;
end $$
delimiter ;

create table if not exists testtbl (
	id int auto_increment primary key,
    txt char(10)
);

call userproc3 ('테스트값2', @myvalue);
select concat('현재 입력된 ID 값 ==>', @myvalue);

-- IF ... ELSE 문
drop procedure if exists ifelseproc;

delimiter $$
create procedure ifelseproc(in username varchar(10))
begin
	declare byear int;	-- 변수선언
    select birthyear into byear from usertbl
		where name = username;
	if (byear >= 1980) then
		select '아직 젊군요...';
	else 
		select '나이가 지긋하시네요...';
	end if;
end $$
delimiter ;

call ifelseproc('이승기');

-- -----------------
drop procedure if exists caseproc;
delimiter $$
create procedure caseproc(
	in username varchar(10)
)
begin
	declare byear int;
    declare tti char(3);	-- 띠
    select birthyear into byear from usertbl
		where name = username;
	case
		when (byear%12 = 0) then set tti = '원숭이';
		when (byear%12 = 1) then set tti = '닭';
		when (byear%12 = 2) then set tti = '개';
		when (byear%12 = 3) then set tti = '돼지';
		when (byear%12 = 4) then set tti = '쥐';
		when (byear%12 = 5) then set tti = '소';
		when (byear%12 = 6) then set tti = '호랑이';
		when (byear%12 = 7) then set tti = '토끼';
		when (byear%12 = 8) then set tti = '용';
		when (byear%12 = 9) then set tti = '뱀';
		when (byear%12 = 10) then set tti = '말';
		else set tti = '양';
	end case;
    select concat(username, '의 띠 ==>', tti);
end $$
delimiter ;

drop procedure if exists caseproc;

call caseproc ('김범수');

-- 구구단을 문자열로 생성해서 테이블에 이볅하는 스토어드 프로시저 생성
drop table if exists gugutbl;

create table gugutbl (txt varchar(100)); -- 구구단 저장용 테이블

drop procedure if exists whileproc;

delimiter $$
create procedure whileproc()
begin
	declare str varchar(100);	-- 각 단을 문자열로 저장
    declare i int;	-- 구구단 앞자리
    declare k int;	-- 구구단 뒷자리
    set i = 2;	-- 2단부터 계산
    
    while (i <10) do	-- 바깥 반복문. 2~9단 까지
		set str = ''; 	-- 각 단의 결과를 저장할 문자열 초기화
		set k = 1;		-- 구구단 뒷자리는 항상 1부터 9까지
        while (k < 10) do
			set str = concat(str, ' ', i, 'x', k, '=', i*k);	-- 문자열 만들기
			set k = k +1;	-- 뒷자리 증가
		end while;
        set i = i + 1;		-- 앞자리 증가
        insert into gugutbl values(str);	-- 각 단의 결과를 테이블에 입력
	end while;
end $$
delimiter ;

call whileproc();
select * from gugutbl;

-- 사용자가 단을 입력을 하면 입력 단에 구구단을 출력 (입력 1)

drop table if exists guguselect;

create table guguselect (txt varchar(100));

drop procedure if exists guguselect;

delimiter $$
create procedure guguselect(in i int)
begin
	declare str varchar(100);
    declare j int;
	
		set str = '';
        set j = 1;        
        while (j<10) do
			set str = concat(str, ' ', i, 'x', j, '=', i * j);
            set j = j + 1;
		end while;
        select (str);	-- 각 단의 결과를 테이블에 입력
end $$
delimiter ;
    
call guguselect(3);
select * from guguselect;

-- 사용자가 단의 범위 (3 ~ 5 단)을 지정해서 단이 출력. 프로시저명(3,5)


drop table if exists gugutbl3;

create table gugutbl3 (txt varchar(100)); -- 구구단 저장용 테이블

drop procedure if exists whileproc3;

delimiter $$
create procedure whileproc3(in i int, in j int)
begin
	declare str varchar(100);	-- 각 단을 문자열로 저장
    declare k int;	-- 구구단 뒷자리
    
    while (i <= j) do	-- 바깥 반복문. 2~9단 까지
		set str = ''; 	-- 각 단의 결과를 저장할 문자열 초기화
		set k = 1;		-- 구구단 뒷자리는 항상 1부터 9까지
        while (k < 10) do
			set str = concat(str, ' ', i, 'x', k, '=', i*k);	-- 문자열 만들기
			set k = k +1;	-- 뒷자리 증가
		end while;
        set i = i + 1;		-- 앞자리 증가
        insert into gugutbl3 values(str);	-- 각 단의 결과를 테이블에 입력
	end while;
end $$
delimiter ;

call whileproc3(3, 5);
select * from gugutbl3;

-- 프로시저 예외 처리
drop procedure if exists errorproc;

delimiter $$
create procedure errorproc()
begin
	declare i int;	-- 값을 1씩 증가
    declare hap int;	-- 합계(정수형), 오버플로어 발생
    declare savehap int; -- 합계(정수형), 오버플로어 발생 직전 값
    
    declare exit handler for 1264	-- int형 오버플로어
    begin
		select concat('int 오버플로어 직전의 합계 --> ', savehap);
        select concat('1+2+3+...+', i, '=오버플로어');
	end;
    
    set i = 1;
    set hap = 0;
    
    while (true) do
		set savehap = hap;	-- 오버플로어 발생 직전의 합계 savehap
        set hap = hap + i;
        set i = i + 1;
	end while;
end $$
delimiter ;

call errorproc();

-- 저장된 프로시저에 이름 내용 확인
-- routine_name = 프로시저 이름, routine_definition = 프로시저 내용
select routine_name, routine_definition from information_schema.routines
	where routine_schema = 'sqldb' and routine_type = 'PROCEDURE';	-- 프로시저는 대문자로 입력해야 합니다. 자바의 라이브러리 클래스같은 느낌?
    
-- 파라미터 확인
select parameter_mode, parameter_name from information_schema.parameters
	where specific_name = 'userproc3';
    
-- 테이블의 이름을 파라미터로 전달
drop procedure if exists nameproc;

delimiter $$
create procedure nameproc(in tblname varchar(20))
begin
	set @sqlQuery = concat('select * from', tblname);
    prepare myQuery from @sqlQuery;		-- 메모리에 myquery 이름으로 저장(준비)
    execute myQuery;					-- myQuery 실행
    deallocate prepare myQuery;			-- 메모리에서 myQuery 해제
end $$
delimiter ;

call nameproc('buytbl');

-- 프로시저 삭제
-- drop procedure 프로시저 이름;
-- 프로시저 : alter 로는 procedure가 수정 되지 않습니다.
728x90

'MySQL' 카테고리의 다른 글

커서(Cursor).MySQL  (0) 2023.02.10
스토어드 함수(Stored Function)  (0) 2023.02.10
인덱스 생성/ 변경 / 삭제.MySQL  (0) 2023.02.09
인덱스의 내부 작동.MySQL  (0) 2023.02.09
인덱스(Index).MySQL  (0) 2023.02.09