멋쟁이v의 개발일지

[DB] Stored Program(프로시저) 본문

0년차/DB

[DB] Stored Program(프로시저)

멋쟁이v 2023. 6. 11. 17:37
728x90
320x100

[목차]


01. Stored Program

💡
내장식 프로그램, 프로그램 내장 방식, 저장 프로그램

MySQL 전용 언어.

➡️ SQL문에 변수, 제어문, 입출력 등 프로그래밍 기능을 추가해서 SQL문으로 처리하기 어려운 문제를 해결할 수 있다.

  • 저장 프로그램은 우리가 작성하는 프로그램 로직을 프로시저로 구현해서 사용한다.
  • 일반적인 프로그래밍 언어에서 사용하는 함수와 비슷한 개념.
  • 작업 순서가 정해진 독립된 프로그램의 수행 단위.
  • DBMS에 저장되기 때문에 저장 프로그램이라고 부른다.
  • 특징
    👉🏻
    MySQL 성능 향상

    ➡️ 긴 쿼리의 내용을 전송하지 않고 프로시저의 이름과 매개 변수 등 전송하여 네트워크 부하를 줄일 수 있다.

    유지 관리가 간편

    ➡️ 직접 SQL문을 작성하지 않고, 생성한 이름만 호출하여 일관된 작업을 진행할 수 있다.

    모듈식 프로그래밍

    ➡️ 저장 프로그램을 한번 생성해서 쿼리 수정, 삭제 등 관리가 수월하고, 모듈처럼 자주 사용하는 구문을 재사용할 수 있다.

    보안 강화

    ➡️ 사용자 별 테이블에 접근 권한을 주지 않고, 저장 프로그램에 접근 권한을 줘서 보안을 강화한다.

  • 종류
    👉🏻
    저장 루틴(프로시저, 함수)

    트리거

    커서

  • 스토어드 프로시저(Procedure)
    👉🏻
    SQL문을 하나로 묶어서 편리하게 사용하는 기능.

    어떤 동작을 일괄 처리하기 위한 용도로 사용

    SQL문을 하나씩 매번 수행하는 것이 아닌, 프로시저로 만들어 놓은 후, 호출하는 방식으로 주로 사용한다.

    ➡️ 생성

    👉🏻
    CREATE PROCEDURE 프로시저_이름

    ➡️ 구성

    👉🏻
    선언부와 실행부로 구성

    (BEGIN ~ END)

    • 선언부 : 변수와 매개 변수를 선언한다.
    • 실행부 : 프로그램 로직을 작성한다.
    • 변수 : 저장 프로시저나 트리거 안에서 사용되는 값
    • 매개변수 : 저장 프로시저가 호출될 때, 호출되는 프로시저로 전달되는 값.

    ➡️ 형식

    👉🏻
    프로시저 묶어주기

    DELIMITER $$(@@, // 도 가능) → 종결 문자를 $$로 변경

    CREATE PROCEURE sp_프로시저_이름(IN 또는 OUT Parameter)

    BEGIN

    SQL문(프로시저 내용)

    END $$

    DELIMITER ; → 다시 ;으로 종결 문자 변경

    • DELIMITER : 종결 문자 변경
      • SQL문을 작성했을 때 종결 문자는 ;인데, 헷갈리지 않도록 종결 문자를 정한다.
      • $$말고 다른 문자도 가능하지만, 다른 기호화 중복되지 않도록 하고, 2개를 연속해서 사용하는 것이 좋다.

    ➡️ 매개 변수의 사용

    👉🏻
    IN 입력매개변수이름 데이터형식 (IN은 생략 가능)

    OUT 출력매개변수이름 데이터형식 (OUT은 생략 불가능)

    • OUT 매개변수는 출력매개변수에 값을 대입하기 위해 SELECT ~ INTO 구문을 사용한다.
    • SELECT ~ INTO 구문은 MySQL에서 사용자가 정의한 변수에 SELECT에서 조회할 열에 값을 대입하기 위해 사용. 주로 프로시저에서 사용한다.

    ➡️ 프로시저 호출

    • CALL 프로시저_이름(전달 값);

    ➡️ 프로시저 삭제

    • DROP PROCEDURE 프로시저_이름;

    ➡️ 예제

    회원의 이름으로 정보를 조회하는 프로시저

    -- 프로시저 생성
    DELIMITER $$
    CREATE PROCEDURE sp_member_info(IN mName VARCHAR(20))
    BEGIN
    	SELECT
    		*
    	FROM
    		tb_member AS m
    	WHERE
    		m.m_name = mName; -- 매개변수가 들어가는 자리
    END $$
    DELIMITER ;
    
    -- 프로시저 호출
    CALL sp_member_info('홍07');

    회원의 아이디와 비밀번호를 입력 받아서 회원의 이메일을 조회하는 프로시저를 만들고, 호출하시오

    -- 프로시저 생성
    DELIMITER $$
    CREATE PROCEDURE sp_member_email(IN m_id VARCHAR(20), IN m_pw VARCHAR(20))
    -- 코멘트 작성
    COMMENT '회원의 아이디와 비밀번호를 입력 받아 이메일을 조회하는 프로시저'
    BEGIN
    	SELECT
    		m.m_email
    	FROM
    		tb_member AS m
    	WHERE
    		m.m_id = m_id
    		AND
    		m.m_pw = m_pw;
    END $$
    DELIMITER ;
    
    -- 프로시저 호출
    CALL sp_member_email('id003', 'pw003');

    ➡️ 제어문 예제

    -- 프로시저 생성
    DELIMITER $$
    CREATE PROCEDURE sp_if_test()
    BEGIN
    
    	DECLARE num INT; -- num이라는 변수 선언
    	SET num := 300; -- 변수에 값 대입
    
    	IF num = 300 THEN
    		SELECT '300이 맞습니다.';
    	ELSE
    		SELECT '300이 아닙니다.';
    	END IF;
    
    END $$
    DELIMITER ;
    • :=
      • = 기호는 비교 연산 대입 연산 SET 다음에 작성하는 이퀄 기호는 값을 대입하는게 맞는데, 혼동할 수 있으니 구분을 위해 := 로 작성함.
    • DECLATE num INT DEFAULT 300;
      • 변수 선언과 초기화를 동시에 가능.

    회원의 아이디를 입력 받아 권한을 조회하는 프로시저를 작성하시오.

    -- sp_member_level라는 프로시저가 존재하면 삭제
    DROP PROCEDURE IF EXISTS sp_member_level;
    
    -- 프로시저 생성
    DELIMITER $$
    CREATE PROCEDURE sp_member_level(IN m_id VARCHAR(50))
    BEGIN
    
    	DECLARE mLevel INT; -- 변수 선언
    	SET mLevel := 0; -- 값 세팅
    
    	SELECT
    		m.m_level INTO mLevel
    	FROM
    		tb_member AS m
    	WHERE
    		m.m_id = m_id;
    
    	IF mLevel = 1 THEN
    		SELECT '관리자' AS '권한';
    	ELSEIF mLevel = 2 THEN
    		SELECT '판매자' AS '권한';
    	ELSE
    		SELECT '구매자' AS '권한';
    	END IF;
    
    END $$
    DELIMITER ;
    
    -- 프로시저 호출
    CALL cp_member_level('id002');

  • 실습
    1. JOIN으로 m.*의 내용만 확인 가능
    1. DELETE 시, 컬럼 이름을 명시할 필요 없는데, tb_goods의 내용을 지운다.

      ➡️ (tb_goods AS g) 컬럼 자리에 g를 명시하면 g에 해당하는 내용을 삭제할 수 있다.

    1. 가장 중요한 내용은 UPDATE, DELETE 전 반드시 SELECT를 진행한다.
    1. IF 조건문을 사용하여, 회원의 아이디를 입력 받으면 모든 테이블의 내용이 삭제되도록 프로시저를 작성하시오. (단, 회원 레벨 1은 삭제 할 수 없다.)
      1. 테이블 ERD를 보면서 테이블간 연결을 확인하면서 순차적으로 삭제해야 된다.
    -- 프로시저가 존재하면 삭제
    DROP PROCEDURE IF EXISTS sp_mem_all_delete;
    
    -- 프로시저 생성
    DELIMITER $$
    CREATE PROCEDURE sp_mem_all_delete(IN memId VARCHAR(50))
    BEGIN
    	-- 변수 선언
    	DECLARE memLv INT;
    	
    	-- tb_member에서 조회한 회원 레벨을 memLv에 대입해서 조회
    	SELECT
    		m.m_level INTO memLv
    	FROM
    		tb_member AS m
    	WHERE
    		m.m_id = memId;
    
    	
    	-- 레벨에 따라서 조건문
    	IF(memLv <> 1) THEN -- 1이 아니라면
    		IF(memLv = 2) THEN -- 2인 경우
    			DELETE
    				o
    			FROM
    				tb_order AS o
    				INNER JOIN
    				tb_goods AS g
    			WHERE
    				g.g_seller_id = memId;
    
    			DELETE
    				g
    			FROM
    				tb_goods AS g
    			WHERE
    				g.g_seller_id = memId;
    		END IF;
    
    		IF(memLv = 3) THEN -- 3인 경우
    			DELETE
    				o
    			FROM
    				tb_order AS o
    			WHERE
    				o.o_id = memId;
    		END IF;
    
    		-- member 테이블을 삭제하기 위해 로그인 테이블을 먼저 삭제
    		DELETE
    			l
    		FROM
    			tb_login AS l
    		WHERE
    			l.login_id = memId;
    
    		-- 최종적으로 member테이블의 매개변수로 받은 id의 회원 정보 삭제
    		DELETE
    			m
    		FROM
    			tb_member AS m
    		WHERE
    			m.m_id = memId;
    	END IF;
    
    END $$
    DELIMITER ;
    
    -- 프로시저 호출
    CALL sp_mem_all_delete('id008');

    🗣 프로시저를 단계별로 나눠서 all 프로시저를 만들고 그 프로시저에서 단계별 프로시저를 순서대로 call 하는 방법도 있다.

    ➡️ ex) sp_all → CALL sp_1, CALL sp_2, CALL sp_3 …


tag : #데이터베이스 #DB #Stored Program #프로시저


Uploaded by N2T

728x90
320x100
Comments