Database/MySQL

프로시저 중복 Cursor

Jeffrey Oh 2023. 6. 15. 23:42
반응형

procedure multiple cursor 처리 하는 방법을 매번 까먹어서 정리해둔다.

CREATE DEFINER=`user`@`%` PROCEDURE `database_name`.`method_name`()
BEGIN
    DECLARE outer_done BOOLEAN DEFAULT FALSE; # cursor1 종료 처리를 위한 논리값
    DECLARE v_count INT DEFAULT -1; # 전체 처리 수 확인용
    DECLARE v_idx INT DEFAULT 1; # inner_loop index 증가용
    DECLARE v_student_id BINARY(16); # cursor1 select column

    # 2023 년 측정 결과 중 student_id 기준으로 group by 해서 조회
    DECLARE cursor1 CURSOR FOR
        SELECT student_id FROM measured_result mr2 WHERE YEAR(measured_date) = 2023 GROUP BY student_id;

    # cursor1 loop 종료 처리를 위한 변수
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET outer_done = TRUE;

    # cursor1 시작
    OPEN cursor1;

    # outer_loop 시작
    outer_loop: LOOP
        # cursor1 에서 전달받은 student_id 를 v_student_id 지역변수에 할당
        FETCH cursor1 INTO v_student_id;
        # 시작과 동시에 + 1 처리
        # 데이터 없으면 최종적으로 0이 찍힘 (디폴트가 -1이라서)
        # 데이터 있으면 처리후 다음 반복문 시작 시 1 이상
        SET v_count = v_count + 1;

        # outer_done 이 TRUE 이면 loop 종료
        IF outer_done THEN
            # cursor1 종료
            CLOSE cursor1;
            # outer_loop 나감
            LEAVE outer_loop;
        END IF;

        # 내부 프로시저 블럭 시작
        block_inner: BEGIN
            # cursor2 종료 처리를 위한 논리값
            DECLARE inner_done BOOLEAN DEFAULT FALSE;
            # cursor2 에서 사용할 내부 index 지역변수
            DECLARE v_idx INT DEFAULT 1;
            # cursor2 에서 조회한 id 를 v_idx 지역변수에 할당
            DECLARE v_id BINARY(16); # inner_cursor

            # 2023 년 측정 결과 중 id 를 student_id 로 조회
            DECLARE cursor2 CURSOR FOR
                SELECT id FROM measured_result mr WHERE YEAR(measured_date) = 2023 AND student_id = v_student_id ORDER BY measured_date, measured_number;

            # cursor2 loop 종료 처리를 위한 변수
            DECLARE CONTINUE HANDLER FOR NOT FOUND SET inner_done = TRUE;

            # cursor2 시작
            OPEN cursor2;

            # inner_loop 시작
            inner_loop: LOOP
                # cursor2 에서 전달받은 id 를 v_id 지역변수에 할당
                FETCH cursor2 INTO v_id;

                # inner_done 이 TRUE 이면 loop 종료
                IF inner_done THEN
                    # cursor2 종료
                    CLOSE cursor2;
                    # inner_lop 나감
                    LEAVE inner_loop;
                END IF;

                # 순서대로 측정 년도 기준 차수 UPDATE 처리
                UPDATE measured_result SET measured_number_year = v_idx WHERE id = v_id;

                # 차수 증가를 위한 인덱스 증감연산
                SET v_idx = v_idx + 1;
            # inner_loop 끝
            END LOOP inner_loop;
        # 지역 변수 초기화
        SET v_idx = 1;
       # block_inner 끝 
       END block_inner;
    # outer_loop 끝
    END LOOP outer_loop;

    # 전체 처리한 수 조회
    SELECT v_count;

END
반응형