728x90

CURSOR : 테이블을 한 줄씩 읽어서 다른 작업을 진행할 때 사용

 

커서 구문

-- FOR SELECT문 -> 한 줄씩 읽을 타겟 데이터를 SELECT함
DECLARE 커서이름 CURSOR FOR
SELECT문

OPEN 커서이름
-- FETCH문 : 한 줄 읽음
FETCH NEXT FROM 커서이름 INTO @SELECT된컬럼들, ...

WHILE(@@FETCH_STATUS = 0)
	BEGIN
   		작업 진행(ex. SELECT, INSERT, UPDATE, DELETE, ... )

    		-- 다음 줄 읽음
    		FETCH NEXT FROM 커서이름 INTO @SELECT된컬럼들, ...
	END

CLOSE 커서이름
DEALLOCATE 커서이름

 

이중 커서 예시

예시로 이런 헤더, 디테일 테이블이 있다고 가정.

헤더 테이블의 PK는 CODE

디테일 테이블의 PK는 CODE, SEQ 로 헤더의 내역을 관리할 수 있음 → 헤더의 CODE = 디테일의 CODE 임

 

두 테이블을 모두 조회하도록 CURSOR  작성

-- 임시 테이블 생성
CREATE TABLE #HDR (
	CODE		NVARCHAR(1)	NOT NULL,	-- PK용
	FLAG			NVARCHAR(1)	NULL

CREATE TABLE #DTL (
	CODE		NVARCHAR(1)	NOT NULL,	-- PK용
	SEQ			INT			NOT NULL,	-- PK용
	CONTENT		NVARCHAR(20)	NULL
)

INSERT INTO #HDR VALUES('A', 'Y')
INSERT INTO #HDR VALUES('B', 'N')
INSERT INTO #DTL VALUES('A', 1, 'TEST')
INSERT INTO #DTL VALUES('A', 2, 'CONTENT')
INSERT INTO #DTL VALUES('A', 3, 'EXAMPLE')
INSERT INTO #DTL VALUES('B', 1, 'PRACTICE')
INSERT INTO #DTL VALUES('B', 2, 'SLEEPY')

-- 변수 선언 ----------------------------------------
DECLARE
	-- 커서로 읽을 SELECT문의 모든 컬럼을 선언
	@CODE		NVARCHAR(1),
	@FLAG		NVARCHAR(1),
	@SEQ		INT,
	@CONTENT	NVARCHAR(20),
	-- 결과 담을 변수
	@RESULT		NVARCHAR(100),
	@HDR_TEMP	NVARCHAR(50),
	@DTL_TEMP	NVARCHAR(50)
    
-- 헤더의 커서 --------------------------------------
-- FOR SELET문 -> 한 줄씩 읽을 타겟 데이터를 SELECT함
DECLARE HDR_CURSOR CURSOR FOR
SELECT CODE, FLAG FROM #HDR

SELECT @RESULT = ''

-- 헤더 반복시작
OPEN HDR_CURSOR
-- FETCH문 : 한 줄 읽음
FETCH NEXT FROM HDR_CURSOR INTO @CODE, @FLAG -- SELET문에서 조회한 컬럼들과 동일하게 맞춰야함
-- @@FETCH_STATUS = 0  : FETCH문 수행됨
-- @@FETCH_STATUS = -1 : FETCH문 수행 실패
-- @@FETCH_STATUS = -2 : FETCH문 수행됐으나 행 없음

WHILE (@@FETCH_STATUS = 0) -- 한 줄 읽는거 성공 시 WHILE 반복
	BEGIN
		-- 헤더에 대해 다른 작업 진행
		SELECT @HDR_TEMP = ''
		SELECT @HDR_TEMP = @CODE + '(' + @FLAG + ') { '
		 
		-- 디테일 커서 선언
		DECLARE DTL_CURSOR CURSOR FOR
		SELECT SEQ, CONTENT FROM #DTL 
        	WHERE CODE = @CODE -- 헤더의 PK로 조회함
		
        	-- 디테일 반복시작
		OPEN DTL_CURSOR
		SET @DTL_TEMP = ''
        
		FETCH NEXT FROM DTL_CURSOR INTO @SEQ, @CONTENT 
        
		WHILE (@@FETCH_STATUS = 0) 
			BEGIN
				-- 디테일에 대해 다른 작업 진행
            			SELECT @DTL_TEMP = @DTL_TEMP + @CODE + CAST(@SEQ AS VARCHAR) + '(' + @CONTENT + ') '

            			-- 디테일 다음 줄 읽음 
				FETCH NEXT FROM DTL_CURSOR INTO @SEQ, @CONTENT 
			END
        	-- 디테일 반복끝
		CLOSE DTL_CURSOR		-- 커서 닫기
		DEALLOCATE DTL_CURSOR	-- 커서 할당 해제

		SELECT @RESULT = @RESULT + @HDR_TEMP + @DTL_TEMP + '} '

		-- 헤더 다음 줄 읽음
        	FETCH NEXT FROM HDR_CURSOR INTO @CODE, @FLAG
	END

-- 헤더 반복끝
CLOSE HDR_CURSOR
DEALLOCATE HDR_CURSOR

-- 임시 테이블 삭제
DROP TABLE #HDR
DROP TABLE #DTL

-- 결과 ----------------------------------------------
SELECT '실행순서 : ' + @RESULT

 

실행결과

 

728x90