본문 바로가기
Database

[MySql] 문자열 분리해서 LOOP 돌리는 프로시저(LOOP, FETCH, CURSOR 사용)

by jn4624 2021. 4. 29.
반응형

 

 

stu_subject, stu_score, stu_grade 속성의 데이터 값이 다중이고 CONCAT된 갯수만큼 정보를 각각 INSERT해야 하는데 도저히 쿼리로는 반복문을 해결할 수 없을 것 같아 프로시저를 만들어보기로 했다.

BEGIN
    DECLARE stuSeq int(11);
    DECLARE stuName varchar(50);
    DECLARE stuSubject varchar(50);
    DECLARE stuScore varchar(50);
    DECLARE stuGrade varchar(50);
    
    DECLARE stuSubject1 varchar(50);
    DECLARE stuScore1 varchar(50);
    DECLARE stuGrade1 varchar(50);
    
    DECLARE DEL char(1) DEFAULT ',';
    DECLARE DONE int DEFAULT FALSE;
    DECLARE CNT int DEFAULT -1;
    
    -- SELECT한 결과를 CURSOR1로 정의
    DECLARE CURSOR1 CURSOR FOR
    SELECT
        stu_seq
        , stu_name
        , stu_subject
        , stu_score
        , stu_grade
    FROM student;
    
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET DONE = TRUE;
    
    OPEN CURSOR1;
    
    START_LOOP: LOOP
    
    -- LOOP하며 CURSOR1의 데이터를 해당 변수에 
    FETCH CURSOR1
    INTO
        stuSeq
        , stuName
        , stuSubject
        , stuScore
        , stuGrade;
    
    SET CNT = CNT + 1;
    
    -- 반복이 끝나면 LOOP 빠져 나가기
    IF DONE THEN
        LEAVE START_LOOP;
    END IF;
    
    WHILE IFNULL(stuSubject, '') != '' AND IFNULL(stuScore, '') != '' AND IFNULL(stuGrade, '') != '' DO
        -- CONCAT되어 있는 데이터를 구분자를 기준으로 SPLIT하여 해당 변수에 하나씩 초기화
        SET stuSubject1 = SUBSTRING_INDEX(stuSubject, DEL, 1);
        SET stuScore1 = SUBSTRING_INDEX(stuScore, DEL, 1);
        SET stuGrade1 = SUBSTRING_INDEX(stuGrade, DEL, 1);
        
        -- 초기화된 데이터는 기존 CONCAT된 데이터에서 제거
        SET stuSubject = SUBSTRING(stuSubject, CHAR_LENGTH(stuSubject1) + CHAR_LENGTH(DEL)+1);
        SET stuScore = SUBSTRING(stuScore, CHAR_LENGTH(stuScore1) + CHAR_LENGTH(DEL)+1);
        SET stuGrade = SUBSTRING(stuGrade, CHAR_LENGTH(stuGrade1) + CHAR_LENGTH(DEL)+1);
        
        INSERT INTO subject (
            stu_seq
            , stu_name
            , sub_name
            , sub_score
            , sub_grade
        ) VALUES (
            stuSeq
            , stuName
            , stuSubject1
            , stuScore1
            , stuGrade1
        );
    END WHILE;
    
    END LOOP;
    
    SELECT CNT;
    
    CLOSE CURSOR1;
END

요약해 설명하면 SELECT한 결과를 미리 선언해놓은 변수들에 초기화한 뒤

속성값이 다중인 오리지널 데이터는 WHILE문을 통해 구분자를 기준으로 분리해 하나씩 변수에 초기화해주고

분리된 데이터는 오리지널 데이터에서 제거해가며 INSERT하는 방식이다.

WHILE문은 오리지널 데이터가 공백이 될 때까지 반복된다.

 

WHILE문의 로직 중 오리지널 데이터 분리하는 쿼리와 오리지널 데이터에서 분리된 데이터를 제거하는 쿼리를 따로 실행해보면 WHILE문이 어떻게 실행되는지 알 수 있다.

 

 

위 프로시저를 호출하면 STUDENT 테이블의 열의 갯수만큼 LOOP가 실행되었다는 COUNT가 RETURN 되고 

 

 

SUBJECT 테이블에는 분리된 문자열만큼 각 데이터가 INSERT된 걸 확인할 수 있다.

 

 

 

🙏 참조 ::

반응형