DB

커서

sdafdq 2023. 11. 15. 11:59

커서는 테이블의 한 행씩 처리하기 위한 방법.

이번엔 스토어드 프로시저에서 한 행씩 처리하는 방법

커서는 대부분 스토어드 프로시저와 함께 사용 됨

이게 커서

저 화살표

하나씩 처리하는

 

delimiter $$
create procedure cursor_proc()
begin
    declare memnumber int;
    declare cnt int default 0;
    declare totNumber int default 0;
    declare endofrow boolean default false;
    
    declare memcursor cursor for select mem_number from member;
    
    declare continue handler for not found set endofrow = true;
    
    open memcursor;
    
    cursor_loop: loop
        fetch memcursor 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) '회원의 평균 인원 수';
    close memcursor;
    
end $$
delimiter ;

call cursor_proc();

좀 길긴한데,

 

일단 memNumber(팀의 멤버수), cnt(그냥 카운트. 루프 한번 지날 때 마다 올림), totNumber(전체 팀의 멤버수)

로, 커서와는 직접적으로 관계 없는 녀석들.

 

declare endofrow boolean default false 이 녀석도 직접적인 커서보다, 행 끝났을 때 파악하기 위해.

 

이제부터 직접적인 커서

declare memCursur cursor for select mem_number from member;

실제로 있는 커서 기능을 선언 한거임. 이름은 memCursur로 하고, mem_number from member를 가르키는 커서임.

 

declare continue handler for not found set endOfRow = true

이거는 뭐냐면, 커서에 대한 반복 조건을 설정하는 거임.

continue handler 

지속하는 것을 다루다 (커서는 안써져 있지만 커서에 대해 다루는 거임.)

for not found set

커서가 not found 이면, endOfRow를 true로 둔다. 

반복문과는 연관이 없다. 커서와 연관이 있는거다.

 

루프를 도는데, fetch 해서 커서를 memnumber로 가져옴. fetch는 한 행씩 읽어오는 거임. 이렇게 읽어오면 다음번째 커서로 가면서 값을 읽어옴.

커서는 현재의 위치, 위에 사진 보면 알겠지만 저렇게 테이블에서 현재위 위치, 값을 말하는 거임. 거기에 접근해서 memNumber에다가 넣음.

 

endOfRow가 true면 루프를 떠나도록 함. 위를 보면 cursur가 not found면 true로 설정됨. 

 

루프를 한번 돌 때마다 cnt를 올리고,

totNumber에 더함.

그걸 반복하는 거임.

 

다 반복이 되면, 즉 커서가 not found가 나와서 endOfRow가 true가 되고 반복문이 그걸 보고 빠져나와서,

totNumber를 cnt만큼 나눔. 그러면 평균 멤버 수.

그 다음 커서 닫아줌.

이걸 커서와 관련있는 것만 만들어 보면

delimiter $$
create procedure cursor_proc()
begin
    declare endofrow boolean default false;
    
    declare memcursor cursor for select mem_number from member;
    declare continue handler for not found set endofrow = true;
    
    open memcursor;
    
    cursor_loop: loop
        fetch memcursor into memnumber;
        
        if endofrow then
            leave cursor_loop;
        end if;

    end loop cursor_loop;

    close memcursor;
    
end $$
delimiter ;

endOfRow는 커서와 직접적인 연관은 없지만 커서의 끝을 알기 위해 정의해 둔거.

memcursor와 다음 줄이 직접적으로 커서와 관계 있음.

memcursor는 저렇게 memcursor라는 이름으로 cursor를 가져오는 거임, member테이블의 mem_number열인 한 테이블을 가져오는 거라고 보면 됨. 커서는 그 테이블 중 현재위치, 현재 row의 위치고.

 

declare continue handler 이거는 커서의 지속 조건을 정의하는 건데,

not found면 endOfRow를 true로 바꾸도록 정의함.

 

그 다음 커서 열고, 이제 그 member 테이블에서 mem_number가져온 테이블을 열고 거기에 커서를 다는 거임.

 

루프를 돌며,

fetch 커서 하면 한단계 아래로 가면서 하면 그 행의 값을 가져옴. memNumber로 가져왔음.

 

반복문 빠져나가는 조건을 if문으로 endOfRow에 따라 달음.

 

모든 반복문이 끝났을 때 더이상 메모리에 있을 필요가 없으니 close 커서 함.

 

delimiter $$
create procedure 커서를다룰프로시저명()
begin
    declare 현재행을담을변수 int;
    declare 커서끝깃발 boolean default false;
    
    declare 커서명 cursor for select 가져올값 from 원본테이블;
    declare continue handler for not found set 커서끝깃발 = true;
    
    open 커서;
    
    반복문명: loop
        fetch 커서 into 현재행을담을변수;
        
        if 커서끝깃발 then
            leave 반복문명;
        end if;

    end loop 반복문명;

    close 커서;
    
end $$
delimiter ;

이런 식인데,

declare continue handler for not found set 커서끝깃발 = true;

이거는 아마 not found 말고도 여러가지 조건을 할 수 있겠지만, 보통 커서와 관련된 거니 커서의 끝 조건을 대부분 쓸거임.

 

실질적으로 커서와 관련있는 명령어는

    declare 커서명 cursor for select 가져올값 from 원본테이블;
    declare continue handler for not found set 커서끝깃발 = true;

이거 2개와

open 커서, close 커서임.

 

 

프로시저니 call로 실행.

 

'DB' 카테고리의 다른 글

트리거  (0) 2023.11.15
스토어드 함수  (0) 2023.11.15
스토어드 프로시저2  (0) 2023.11.14
인덱스  (0) 2023.11.10
뷰 가상테이블  (0) 2023.11.09