hoony's web study

728x90
반응형

1. 개요

 

본 글은 MariaDB 10.5.11 을 기준으로 작성되었음을 알려드립니다.

 

Procedure를 만들어 작업 처리를 하다보면 Cursor를 여러개 사용하여

 

다중 반복문을 돌려야할 때가 있습니다.

 

그때 우리는 크게 2가지의 해결책을 사용해볼 수 있습니다.

 

2. Block Statement

 

MariaDB 에는 block 이라는 예약어를 통해 statement를 지정해줄 수 있습니다.

 

아래 예시와 함께 보도록 하겠습니다.

 

DELIMITER $$
CREATE PROCEDURE PR_TEST_EXAMPLE()
BLOCK_1:
BEGIN
    DECLARE done_1 boolean DEFAULT false;
    DECLARE v_col1 varchar(100);
    DECLARE v_col2 varchar(100);
    DECLARE cur1 cursor for select idx, data
                            FROM tb_dummy_one;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done_1 := true;

    DECLARE EXIT HANDLER FOR SQLEXCEPTION
        BEGIN
            ROLLBACK ;
        END;

    START TRANSACTION;

    OPEN cur1;

    LOOP1:
    LOOP
        -- // FETCH
        FETCH cur1 INTO v_col1,
            v_col2;

        -- // LOOP CONDITION CHECKSUM
        IF done_1 THEN
            CLOSE cur1;
            LEAVE LOOP1;
        END IF;
        -- // COMMAND (CRUD, ETC ...)
        BLOCK_2:
        BEGIN
            DECLARE done_2 boolean DEFAULT false;
            DECLARE v_col3 varchar(100);
            DECLARE v_col4 varchar(100);
            DECLARE cur2 CURSOR FOR SELECT idx, data_2
                                    FROM tb_dummy_two;
            DECLARE CONTINUE HANDLER FOR NOT FOUND SET done_2 := true;
            OPEN cur2;
            LOOP2:
            LOOP
                -- // FETCH
                FETCH cur2 INTO v_col3,
                    v_col4;

                -- // LOOP CONDITION CHECKSUM
                IF done_2 THEN
                    CLOSE cur2;
                    LEAVE LOOP2;
                END IF;
                -- // COMMAND (CRUD, ETC ...)

            END LOOP LOOP2;
        END BLOCK_2;
    END LOOP LOOP1;
    COMMIT;
END BLOCK_1;
$$
DELIMITER ;

 

3. Reset Loop Condition Variable

 

각자의 장단점이 있어, 무엇이 더 낫다 라고 딱 잘라 말씀 드리기엔 어렵습니다.

 

본인의 쿼리 및 개발 취향에 맞는 방법을 채택하여 사용하시면 됩니다.

 

Loop 탈출 조건을 위한 변수의 값을 통제하여, 반복문을 제어합니다.

 

DELIMITER $$
CREATE PROCEDURE PR_TEST_EXAMPLE()
BEGIN
    DECLARE done boolean DEFAULT false;
    DECLARE v_col1 varchar(100);
    DECLARE v_col2 varchar(100);
    DECLARE v_col3 varchar(100);
    DECLARE v_col4 varchar(100);
    DECLARE cur1 cursor for select idx, data
                            FROM tb_dummy_one;
    DECLARE cur2 CURSOR FOR SELECT idx, data_2
                            FROM tb_dummy_two;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := true;

    DECLARE EXIT HANDLER FOR SQLEXCEPTION
        BEGIN
            ROLLBACK ;
        END;

    START TRANSACTION;

    OPEN cur1;

    LOOP1:
    LOOP
        -- // FETCH
        FETCH cur1 INTO v_col1,
            v_col2;
        
        -- // LOOP CONDITION CHECKSUM
        IF done THEN
            CLOSE cur1;
            LEAVE LOOP1;
        END IF;
        -- // COMMAND (CRUD, ETC ...)
        
        OPEN cur2;
        LOOP2:
        LOOP
            -- // FETCH
            FETCH cur2 INTO v_col3,
                v_col4;

            -- // LOOP CONDITION CHECKSUM
            IF done THEN
                set done := false;
                CLOSE cur2;
                LEAVE LOOP2;
            END IF;
            -- // COMMAND (CRUD, ETC ...)
            
        END LOOP LOOP2;
    END LOOP LOOP1;
    COMMIT;
END;
$$
DELIMITER ;

 

 

4. 주의할점

 

위 예시들을 보시면 주석을 달아놓은 부분이 있습니다.

 

작업을 진행하시다 보면, 길어진 쿼리양에 의해 가독성이 많이 떨어지는데요.

 

그에 따라, Fetch와, 작업수행 및 반복문 탈출 조건의 체크가

 

꼬이게 되면, 원치 않는 방향으로 반복문이

 

한번 더 수행된다던지 하는 경우가 있습니다.

 

이때, 저 순서만 기억해주시면 Cursor 와 Loop 사용 중 그러한 불상사를 피할 수 있습니다.

728x90

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading