본문 바로가기
DATABASE/MsSQL

[MSSQL] 커서(CURSOR) - 행(ROW) 단위 처리의 사용 법

by DANEW 2023. 9. 6.

Intro

안녕하세요.

초보 DBA 다뉴입니다.

 

처음 Database로 업무를 하고 제일 많이 사용했던 것이 오늘 소개할 커서라는 것 인거 같은데요.

나중에 알고보니 커서를 사용하기에 느려지는 트랜잭션들이 많다는 것을 알게되고,

최대한 줄이려고 노력한 것도 이 커서입니다.

 

하지만 필요할 때 사용해야 하는 커서(cursor)에 대해서 알아두면 좋으니 한번 알아보도록 하죠.


Cursor

커서(Cursor) 란?

커서는 데이터의 처리를 집합단위가 아닌 행 (ROW)단위로 처리하기 위해 사용합니다.

일종의 반복문이죠.

 

데이터를 행단위로 처리하기에 행단위 작업에 대한 장점이 있지만,

일괄 처리를 하지않고 각 행의 조회, 처리, 커밋 등의 단위작업이 포함되게 되므로 속도가 느려질 수 있습니다.

BOF (Begin Of File) : 파일의 시작
ROW1
ROW2
ROW3
....
EOF (End Of File) : 파일의 끝

 

커서는 기본적으로 BOF ~ EOF 까지 커서를 이동하며 행단위의 처리를 합니다.

커서(CURSOR) 사용법

MsSQL의 커서는 아래와 같이 선언하여 사용합니다.

DECLARE Cursor_Name CURSOR
FOR select * from TBTestTable

OPEN Cursor_Name

FETCH NEXT FROM Cursor_Name
INTO @column1, @column2 ...

CLOSE Cursor_Name
DEALLOCATE Cursor_Name

DECLARE [커서이름] CURSOR : [커서이름]의 커서를 선언 
FOR [쿼리] : 커서가 바라볼 쿼리를 작성

OPEN [커서이름] : 사용할 커서를 오픈

FETCH NEXT FROM [커서이름] : 오픈된 커서의 다음행을 읽음
INTO [변수1], [변수2] ... : 읽어온 행의 컬럼을 변수에 담는다. (읽어올 컬럼 개수만큼 변수 선언 및 지정)

CLOSE [커서이름] : 사용한 커서를 닫음
DEALLOCATE [커서이름] : 커서 제거


Cursor 활용의 예제

예제 테이블

아래와 같은 내용의 예제 테이블을 생성하였습니다

create table TBNameList(
    seq int not null,
    name varchar(50) not null,
    tel varchar(13)
)

-------------------------

insert into TBNameList values(1, '김수현', NULL)
insert into TBNameList values(1, '배수지', NULL)
insert into TBNameList values(1, '배수지', '000-4567-9874')
insert into TBNameList values(1, '홍길동', '000-1234-5678')
insert into TBNameList values(2, '김윤아', '000-5678-3456')
insert into TBNameList values(2, '임꺽정', NULL)
insert into TBNameList values(3, '박보검', '000-1234-6543')
insert into TBNameList values(4, '김동현', NULL)
insert into TBNameList values(4, '이지은', '000-0025-2054')

생성 후 조회 하면 아래와 같습니다.

반응형
select *
from TBNameList
order by Seq, name, Tel

--------------------------------

Seq	Name	Tel
1	김수현	NULL
1	배수지	NULL
1	배수지	000-4567-9874
1	홍길동	000-1234-5678
2	김윤아	000-5678-3456
2	임꺽정	NULL
3	박보검	000-1234-6543
4	김동현	NULL
4	이지은	000-0025-2054

위의 예제 테이블을 활용하여 Name컬럼을 구분자로 나누어 붙이도록 하는 예제를 진행합니다.

 

3번째 이름 뒤에 구분자는 -을 사용, 그 외 구분자는 / 를 사용합니다. 

커서 예제

DECLARE @Seq int, @Name nvarchar(30), @Tel nvarchar(20)
DECLARE @String nvarchar(4000)
DECLARE @CNT int

set @CNT = 0

DECLARE CS_NameList cursor for
select *
from TBNameList
order by Seq, name, Tel

open CS_NameList
FETCH NEXT FROM CS_NameList
into @Seq, @Name, @Tel

while @@FETCH_STATUS = 0
begin
	if @CNT = 0
	begin
		set @String = @Name
	end
	else if @CNT%3 = 0
	begin
		set @String = @String + '-' + @Name
	end
	else if @CNT%3 <> 0
	begin
		set @String = @String + '/' + @Name
	end

	set @CNT = @CNT +1

	FETCH NEXT FROM CS_NameList
	into @Seq, @Name, @Tel

end

CLOSE CS_NameList
DEALLOCATE CS_NameList

select @String as NameList

 

 

while문에 조건으로 들어가있는 @@FETCH_STATUS 는 현재 커서의 상태값을 반환합니다.

커서의 상태값을 활용하여 Loop문을 작동 시킵니다.

0 : 구문성공
1 : 구문실패 또는 반환 결과가 없음
2 : 반환 Row가 없음

while문 내부에 있는 FETCH NEXT FROM 문을 통해 커서가 다음 행을 가르키며,

해당 결과가 없을 시 while문이 종료됩니다.


Outro

이와 같이 커서를 통하여 Loop문을 동작시켜 원하는 순서로의 행단위 작업을 실행하는 방법에 대해서 알아봤습니다.

 

위 예제는 뭔가 조금 애매한 설명이 될 수도 있겠지만,

앞에 행을통해 다음행에 영향을 주는 작업등을 하게될때 많은 도움이 된다고 생각합니다.

 

한번 쯤 활용해보시는 것을 추천드리네요 :)

 

감사합니다.

반응형