MySQL에서 커서(Cursor)를 사용하면 쿼리 결과 집합의 행(row)을 하나씩 순회하며 처리할 수 있습니다. 이번 글에서는 student_info 테이블의 Name 컬럼에 저장된 레코드를 커서로 읽어오는 저장 프로시저를 직접 만들어 보겠습니다.
예제용 테이블 데이터
먼저 아래와 같은 구조와 데이터를 가진 student_info 테이블이 준비되어 있다고 가정합니다.
mysql> Select * from Student_info;
+-----+---------+------------+------------+
| id | Name | Address | Subject |
+-----+---------+------------+------------+
| 101 | YashPal | Amritsar | History |
| 105 | Gaurav | Chandigarh | Literature |
| 125 | Raman | Shimla | Computers |
| 127 | Ram | Jhansi | Computers |
+-----+---------+------------+------------+
4 rows in set (0.00 sec)
커서를 활용한 저장 프로시저 작성하기
아래 저장 프로시저는 커서를 선언하고, student_info 테이블의 Name 컬럼 값을 한 행씩 읽어들이며 마지막 값을 OUT 파라미터로 반환합니다.
mysql> Delimiter //
mysql> CREATE PROCEDURE cursor_defined(OUT val VARCHAR(20))
-> BEGIN
-> DECLARE a,b VARCHAR(20);
-> DECLARE cur_1 CURSOR for SELECT Name from student_info;
-> DECLARE CONTINUE HANDLER FOR NOT FOUND
-> SET b = 1;
-> OPEN CUR_1;
-> REPEAT
-> FETCH CUR_1 INTO a;
-> UNTIL b = 1
-> END REPEAT;
-> CLOSE CUR_1;
-> SET val = a;
-> END//
Query OK, 0 rows affected (0.04 sec)
mysql> Delimiter ;
mysql> Call cursor_defined(@val);
Query OK, 0 rows affected (0.11 sec)
mysql> Select @val;
+------+
| @val |
+------+
| Ram |
+------+
1 row in set (0.00 sec)
프로시저 코드 단계별 설명
- 변수 선언:
DECLARE a,b VARCHAR(20);— 컬럼 값을 임시로 담을 변수a와 반복 종료 조건으로 사용할 변수b를 선언합니다. - 커서 선언:
DECLARE cur_1 CURSOR for SELECT Name from student_info;—Name컬럼 전체를 조회하는 SELECT 문과 커서cur_1을 연결합니다. - 핸들러 선언:
DECLARE CONTINUE HANDLER FOR NOT FOUND— 더 이상 읽어올 행이 없을 때 변수b를 1로 설정해 반복문을 종료할 수 있게 합니다. - 커서 열기:
OPEN CUR_1;— 커서를 열고 결과 집합을 메모리에 로딩합니다. - 행 가져오기:
FETCH CUR_1 INTO a;— REPEAT 블록 안에서 커서가 가리키는 현재 행의 값을 변수a에 하나씩 대입하며 커서를 앞으로 이동시킵니다. - 커서 닫기:
CLOSE CUR_1;— 모든 행을 읽은 후 커서를 닫아 할당된 리소스를 해제합니다. - 값 반환:
SET val = a;— 마지막으로 읽은 값을 OUT 파라미터val에 저장해 호출자에게 돌려줍니다.
실행 결과 확인
위 실행 결과에서 확인할 수 있듯이, OUT 파라미터인 val에는 'Ram'이라는 값이 저장되었습니다. 커서가 Name 컬럼의 모든 행을 끝까지 순회한 후 마지막 행의 값이 남아 있기 때문입니다. 즉, 이 프로시저는 반복적으로 행을 가져오되 최종적으로 마지막 레코드의 값을 반환하는 동작을 수행합니다.
정리
MySQL 저장 프로시저에서 커서를 사용하려면 선언(DECLARE) → 열기(OPEN) → 가져오기(FETCH) → 닫기(CLOSE)의 순서를 지켜야 하며, 더 이상 읽을 행이 없을 때를 처리하기 위한 NOT FOUND 핸들러 선언도 필수적입니다. 이 패턴을 응용하면 결과 집합의 각 행에 대해 조건 처리, 누적 계산 등 다양한 절차형 로직을 구현할 수 있습니다.