본문 바로가기

DB

MS-SQL CURSOR

 

출처 : 뭉충닷컴 

 

커서란 무엇인가? 이런것 물어보지 말기 바란다. -_-; 책 찾아서 적기 귀찮다. 자세한 사항은 책 사서 보기 바란다. 아무튼 커서에 대해서 간략하게 알아보자.

 

왜 커서를 사용해야하는지 언제 사용해야 하는지 아는것이 중요하다. 아무리 좋은 기술이라도 사용할줄 모르면 정말 헛것이다.

 

나의 경우 예를 들어보겠다. 일전에 회사에서 일을 한가지 시켰는데 중복된 주민등록번호를가진 명단을 가져오라는 것이였다. 뭐 일일이 찾아서 하면 간단하고 머리쓸일 없지만 언제 그러고 앉아있나 -_-; 그래서 이리저리 생각해서 사용한 구문이 서브쿼리였다.(참고로 서브쿼리 사용하면 속도 느리다. -_- )

 

select (select jumin from jumin where jumin=a.jumin) from tb_usr a

 

아마도 위와 비슷한 구문으로 한것같다. (오래전 일이라서 기억이 잘 안난다. -_-;) 실행시켜 보면 상당히 느리다. -_- 왜냐면 tb_usr 테이블의 회원이 만명 이라면 만명 x 만명의 구분을 실행하는 경우가 되기 때문이다. -_-;; 회원이 십만명이면 십만 x 십만 -_-;;;; 장난 아니다. -_-;;;;; 땀만 난다.

 

그래서 아래와 같이 커서를 사용하는것이 속도 면에서 좋다. (물론 그 외에 여러 다른 좋은점이 있다) 참고로 커서를 사용하면 속도가 느린것은 마찬가지다. 아무래도 레코드셋 하나하나 가져오다 보면 속도면에서는 조금 떨어질수 있다 하지만 십만 x 십만 보다는 속도가 아무래도 빠르다. -_-;

 

커서에 대한 사용 방법은 아래를 참조하면 된다. 뭐 더 설명할것 없다. -_-;

 
--## 변수 선언 @Jumin, crsJumin(커서 변수)
DECLARE @Jumin varchar(255)
DECLARE crsJumin CURSOR FOR
    SELECT usr_soc_no1 + '-' + usr_soc_no2 as soc_no FROM tb_usr


--## 선언한 변수를 명시적으로 열어준다.
OPEN crsJumin


--## FETCH를 이용해서 레코드를뽑는다. 뽑은 레코드 값은 @Jumin 변수에 들어간다.
FETCH NEXT FROM crsJumin INTO @Jumin


--## WHILE 문으로 모든 레코드의 값을 출력한다.
--@@FETCH_STATUS : 0=성공, -1=실패(커서 위치 잘못), -2=실패(레코드가 없다)
WHILE @@FETCH_STATUS = 0
BEGIN
   
PRINT @Jumin
    -- 커서를 다음칸으로 이동 시킨다.
    FETCH NEXT FROM crsJumin INTO @Jumin
END


--## 커서를 닫는다.(잠금 해제)
CLOSE crsJumin


--## 자원해제(메모리 완전 해제)
DEALLOCATE crsJumin
 
 

아마 어떤 사람들은 커서를 사용하느니 차라리 간단한 위의 서브쿼리 구문을 사용하는것이 낳다고 할 수도 있다. 물론 틀린 말을 아니다. 사실 주민등록번호가 중복된 사람들의 명단을 뽑는 일은 그냥 한줄짜리 서브쿼리 구문을 쓰는것이 더 낳을수도 있다.

 

근데 만약 회사에서 "주민등록 번호가 중복되어있는 회원의 명단을 삭제하라" 하면 어찌할텐가? 서브쿼리로는 어림도 없다. 이때 커서(Cursor)을 사용하는 것이다. 다음 아래의 구문을 보면 쉽게 이해할 수 잇을 것이다. (그냥 쉽게 생각해서 커서는 asp 에서 데이타 가져올때 쓰는 RecordSet 라고 생각하면 된다)


DECLARE @Jumin varchar(255)
DECLARE crsJumin CURSOR FOR
    SELECT usr_soc_no1 + '-' + usr_soc_no2 as soc_no FROM tb_usr

 

OPEN crsJumin
FETCH NEXT FROM crsJumin INTO @Jumin

 

WHILE @@FETCH_STATUS=0
BEGIN
 
    DELETE FROM tb_usr WHERE usr_soc_no1 + '-' + usr_soc_no2 as soc_no = @Jumin
    PRINT @Jumin + '를 삭제했습니다'
 
 FETCH NEXT FROM crsJumin INTO @Jumin

END

 

CLOSE crsJumin
DEALLOCATE crsJumin