멈추지 않는 기록

[혼자공부하는SQL] 19강 본문

웹 개발/MySQL

[혼자공부하는SQL] 19강

pangil_kim 2025. 3. 1. 07:33
728x90

07-2. 스토어드 함수와 커서

1. 스토어드 함수

  • 스토어드 함수는 앞에서 배운 스토어드 프로시저와 비슷하다.
  • 하지만 사용 방법이나 용도가 조금 다르니, 별개로 알아둘 필요가 있다.

1) 스토어드 함수의 개념과 형식

  • MySQL에서 제공하는 함수 외에, 사용자가 원하는 함수를 직접 만들 수 있다.
  • 이를 스토어드 함수라고 한다.

(1) 생성 형식

DELIMITER $$
CREATE FUNCTION 스토어드_함수_이름(매개변수)
    RETURNS 반환형식
BEGIN

    - 이 부분에 프로그래밍 코딩
    RETURN 반환값;

END $$
DELIMITER ;

SELECT 스토어드_함수_이름();
  • RETURNS 문으로 반환할 값의 데이터 형식을 지정한다.
  • 본문 안에서는 RETURN 문으로 하나의 값을 반환해야 한다.
  • 스토어드 함수의 매개변수는 모두 입력 매개변수이며, IN을 붙이지 않는다.
  • 스토어드 프로시저는 CALL로 호출하지만, 스토어드 함수는 SELECT 문 안에서 호출된다.
  • 스토어드 프로시저 안에서는 SELECT 문을 사용할 수 있지만, 스토어드 함수 안에서는 SELECT를 사용할 수 없다.
  • 스토어드 프로시저는 여러 SQL 문이나 숫자 계산 등의 다양한 용도로 사용하지만, 스토어드 함수는 어떤 계산을 통해서 하나의 값을 반환하는데 주로 사용한다.

2) 스토어드 함수의 사용

  • 스토어드 함수를 사용하기 위해서는 먼저 SQL로 스토어드 함수 생성 권한을 허용해야 한다.
SET GLOBAL log_bin_trust_function_creators = 1;

(1) 예시1 : 두 수의 합계

DROP FUNCTION IF EXISTS sumFunc;

DELIMITER $$
CREATE FUNCTION sumFunc(number1 INT, number2 INT)
    RETURNS INT
BEGIN
    RETURN number1 + number2;
end $$
DELIMITER ;

SELECT sumFunc(100, 200) AS '합계';

(2) 예시2 : 활동햇수 구하기

DROP FUNCTION IF EXISTS calcYearFunc;

DELIMITER $$
CREATE FUNCTION calcYearFunc(dYear INT)
    RETURNS INT
BEGIN
    DECLARE runYear INT; -- 활동기간 (연도)
    SET runYear = YEAR(CURDATE()) - dYear;
    RETURN runYear;
end $$
DELIMITER ;

SELECT calcYearFunc(2010) AS '활동햇수';

-- 검색 결과를 변수에 대입
SELECT calcYearFunc(2007) INTO @debut2007;
SELECT calcYearFunc(2013) INTO @debut2013;
SELECT @debut2007-@debut2013 AS '2007과 2013 차이';

SELECT mem_id, mem_name, calcYearFunc(YEAR(debut_date)) AS '활동 햇수'
    FROM member;

2. 커서로 한 행씩 처리하기

  • 커서는 테이블에서 한 행씩 처리하기 위한 방식이다.

1) 커서의 기본 개념

(1) 개념

  • 커서는 첫 번째 행을 처리한 후에 마지막 행까지 한 행씩 접근해서 값을 처리한다.
  • 처음에는 커서가 행의 시작을 가리킨 후에 한 행씩 차례대로 접근한다.
  • Ex) 커서를 통해 테이블의 전체 인원 수를 알고 싶은 경우

(2) 커서의 작동 과정

  • 커서는 대부분 스토어드 프로시저와 함께 사용된다.

2) 커서의 단계별 실습

(1) 사용할 변수 준비하기

DECLARE memNumber INT; -- 회원의 인원수
DECLARE cnt INT DEFAULT 0; -- 읽은 행의 수
DECLARE toNumber INT DEFAULT 0; -- 전체 인원의 합계
-- 행의 끝을 파악하기 위한 변수
DECLARE endOfRow BOOLEAN DEFAULT FALSE;

(2) 커서 선언하기

DECLARE memberCursor CURSOR FOR
    SELECT mem_number FROM member;

(3) 반복 조건 선언하기

: 행의 끝에 다다르면, 앞에서 선언한 endOfRow 변수를 TRUE로 설정한다.

DECLARE CONTINUE HANDLER
    FOR NOT FOUND SET endOfRow = TRUE;

(4) 커서 열기

OPEN memberCursor;

(5) 행 반복하기

cursor_loop : LOOP
    이 부분을 반복
END LOOP cursor_loop    
-- 반복문을 빠져나갈 조건
IF endOfRow THEN
    LEAVE cursor_loop;
END IF;
  • LEAVE는 반복할 이름을 빠져나간다.
cursor_loop : LOOP
    FETCH memberCursor INTO memNumber;

    IF endOfRow THEN
        LEAVE cursor_loop;
    END IF;

    SET cnt = cnt + 1;
    SET totNumber = totNumber + memNumber;

END LOOP cursor_lopp;
SELECT (totNumber / cnt) AS '회원의 평균 인원 수';

(6) 커서 닫기

CLOSE memberCursor;

3) 전체 코드

USE market_db;
DROP PROCEDURE IF EXISTS cursor_proc;
DELIMITER $$
CREATE PROCEDURE cursor_proc()
BEGIN
    DECLARE memNumber INT; -- 회원의 인원수
    DECLARE cnt INT DEFAULT 0; -- 읽은 행의 수
    DECLARE totNumber INT DEFAULT 0; -- 인원의 합계
    DECLARE endOfRow BOOLEAN DEFAULT FALSE; -- 행의 끝 여부(기본을 FALSE)

    DECLARE memberCuror CURSOR FOR-- 커서 선언
        SELECT mem_number FROM member;

    DECLARE CONTINUE HANDLER -- 행의 끝이면 endOfRow 변수에 TRUE를 대입
        FOR NOT FOUND SET endOfRow = TRUE;

    OPEN memberCuror;  -- 커서 열기

    cursor_loop: LOOP
        FETCH  memberCuror INTO memNumber;

        IF endOfRow THEN
            LEAVE cursor_loop;
        END IF;

        SET cnt = cnt + 1;
        SET totNumber = totNumber + memNumber;
    END LOOP cursor_loop;

    SELECT (totNumber/cnt) AS '회원의 평균 인원 수';

    CLOSE memberCuror;
END $$
DELIMITER ;

CALL cursor_proc();
728x90

'웹 개발 > MySQL' 카테고리의 다른 글

[혼자공부하는SQL] Summary1  (0) 2025.03.28
[혼자공부하는SQL] 20강  (0) 2025.03.01
[혼자공부하는SQL] 18강  (0) 2025.03.01
[혼자공부하는SQL] 17강  (0) 2025.02.26
[혼자공부하는SQL] 16강  (0) 2025.02.26