출처| https://www.youtube.com/watch?v=85Zg0HUv_Eo&list=PLVsNizTWUw7Hox7NMhenT-bulldCp9HP9&index=38
https://daegwonkim.tistory.com/177
스토어드 프로시저(stored procedure)란 MySQL에서 제공하는 프로그래밍 기능이다. C, 자바, 파이썬 등의 프로그래밍과는 조금 차이가 있지만, MySQL 내부에서 사용할 때 적절한 프로그래밍 기능을 제공한다.
또한 스토어드 프로시저는 쿼리 문의 집합으로도 볼 수 있으며, 어떠한 동작을 일괄 처리하기 위한 용도로도 사용된다. 자주 사용하는 일반적인 쿼리를 반복하는 것보다는 스토어드 프로시저로 묶어 놓고, 필요할 때마다 간단히 호출만 하면 훨씬 편리하게 MySQL을 운영할 수 있다
스토어드 프로시저의 기본적인 형식은 다음과 같다.
DELIMITER $$
CREATE PROCEDURE 스토어드_프로시저_이름(IN 또는 OUT 매개변수)
BEGIN
SQL 프로그래밍 코드가 들어가는 부분
END $$
DELIMITER ;
스토어드 프로시저를 호출하는 형식은 다음과 같다. 필요하다면 괄호 안에 매개변수를 넣어서 사용할 수도 있다.
ALTER PROCEDURE
DROP PROCEDURE
IN 입력_매개변수_이름 데이터_형식
CALL 프로시저_이름(전달 값);
OUT 출력_매개변수_이름 데이터_형식
-- 출력 매개 변수 지정
추가적으로 매개 변수에 값을 대입하기 위해서
주로 SELECT ~ INTO 문도 많이 사용한다.
DECLARE 액션 HANDLER FOR 오류조건 처리할_문장
USE market_db;
DELIMITER $$
CREATE PROCEDURE user_proc()
BEGIN
SELECT * FROM member;
END $$
DELIMITER ;
CALL user_proc();
DELIMITER $$
CREATE PROCEDURE user_proc1(IN userName VARCHAR(10))
BEGIN
SELECT * FROM member WHERE mem_name = userName;
END $$
DELIMITER ;
CALL user_proc1('에이핑크');
DELIMITER $$
CREATE PROCEDURE user_proc2(IN userNumber INT, IN userHeight INT)
BEGIN
SELECT * FROM member WHERE mem_number > userNumber AND height > userHeight;
END $$
DELIMITER ;
CALL user_proc2(6, 165);
DELIMITER $$
CREATE PROCEDURE user_proc3(IN txtValue CHAR(10), OUT outValue INT)
BEGIN
INSERT INTO noTable VALUES(NULL, txtValue);
SELECT MAX(id) INTO outValue FROM noTable; -- SELECT ~ INTO 문을 통해 MAX(id) 값이 outValue에 저장됨
END $$
DELIMITER ;
CREATE TABLE IF NOT EXISTS noTable (
id INT AUTO_INCREMENT PRIMARY KEY,
txt CHAR(10)
);
CALL user_proc3('Test 1', @myValue);
SELECT CONCAT('입력된 ID 값 ==> ', @myValue);
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 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;
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+4+...+',i ,'=오버플로');
END;
SET i = 1; -- 1부터 증가
SET hap = 0; -- 합계를 누적
WHILE (TRUE) DO -- 무한 루프.
SET saveHap = hap; -- 오버플로 직전의 합계를 저장
SET hap = hap + i; -- 오버플로가 나면 11, 12행을 수행함
SET i = i + 1;
END WHILE;
END $$
DELIMITER ;
CALL errorProc();
SELECT routine_name, routine_definition FROM INFORMATION_SCHEMA.ROUTINES
WHERE routine_schema = 'sqldb' AND routine_type = 'PROCEDURE';
-파라미터를 보고 싶으면
SELECT parameter_mode, parameter_name, dtd_identifier
FROM INFORMATION_SCHEMA.PARAMETERS
WHERE specific_name = 'userProc3';
SHOW CREATE PROCEDURE sqldb.userProc3;
DROP PROCEDURE IF EXISTS nameProc;
DELIMITER $$
CREATE PROCEDURE nameProc(
IN tblName VARCHAR(20)
) -- 테이블 이름을 넘겨받음
BEGIN
SELECT * FROM tblName;
END $$
DELIMITER ;
CALL nameProc ('userTBL');
나은 방법
DROP PROCEDURE IF EXISTS nameProc;
DELIMITER $$
CREATE PROCEDURE nameProc(
IN tblName VARCHAR(20)
)
BEGIN
SET @sqlQuery = CONCAT('SELECT * FROM ', tblName);
PREPARE myQuery FROM @sqlQuery;
EXECUTE myQuery;
DEALLOCATE PREPARE statement;
END $$
DELIMITER ;
CALL nameProc ('userTBL');