안녕하세요. SQLER의 코난 김대우입니다. 
이번 강좌에서는, 9-1. 커서(CURSOR) - 커서 소개을 진행 하겠습니다.


SQLER에서 진행되는, 챗GPT와 함께 배우는 SQL Server 강좌 목록

 

이번에 진행할 강좌는 커서(CURSOR) 소개입니다.

 

 

 

TL;DR

커서는 개별 로우(행) 단위로 데이터를 다룰 때 사용되는 SQL Server의 도구입니다. 

 


커서란 무엇이고 왜 사용하나요?

SQL Server는 결과셋 단위로 작업을 수행하는 SQL 구문을 사용합니다. 하지만, 가끔 프로그래밍 언어에서 결과셋을 다루는 형식인, 개별 로우(행) 단위로 데이터를 사용할 필요가 있습니다. SQL Server에서 이러한 로우 단위 작업이 필요할 때, 커서를 사용합니다.


조금 더 풀어서 이야기해 보면, 
오래 전, 후배님 중에 공익 근무 요원으로 우체국에서 근무한 후배님이 있습니다. 이 후배님은 우체국에서 쌓여있는 우편물의 우편번호와 주소에 따라 정해진 박스에 우편물을 넣는 작업을 수행했습니다. 이 후배님은 놀랍게도 실제 전국 주소의 우편번호를 거의 다 정확히 암기하고 있었습니다. 이 후배님의 일과 작업 순서는 다음과 같습니다.

 

우편물 분류 작업 순서

1. 쌓여있는 우편물 확인
2. 하나의 우편물을 손으로 들고
3. 우편물의 주소와 우편번호를 확인
3-1. 우편물의 주소와 우편번호가 같으면 우편번호 박스에 우편물을 넣음
3-2. 우편물의 주소와 우편번호가 다르면 우편번호를 네임펜으로 수정하고 박스에 우편물을 넣음
4. 이 과정을 모든 우편물이 없을 때까지 반복


당시 18개월이라는 시간을 우체국에서 공익 근무 요원으로 근무한 후배님은 1년 중 가장 싫어하는 시즌이 크리스마스, 추석, 설 연휴 기간이었다고 합니다.

커서와 우체국 후배님이 무슨 상관입니까?

커서가 위의 우편물 분류 작업 순서와 매우 유사합니다. 쌓여있는 우편물을 테이블의 개별 로우라고 가정해 보세요. 우편물(개별 로우)을 가져와서 우편번호 체크 작업(로우 처리 작업)을 하고 모든 우편물이 없을 때까지(모든 로우 단위 작업이 완료될 때까지) 수행합니다.


“로우 단위 작업”을 생각하면서 아래 예제 SQL 쿼리를 실행하겠습니다.

 

USE AdventureWorks;
GO

-- 우체국에 도착한 우편물 테이블 생성.
CREATE TABLE Mails(
mail_idx INT IDENTITY(1,1) PRIMARY KEY
, mail_num NVARCHAR(3)
, mail_address NVARCHAR(6)
);

INSERT INTO Mails(mail_num, mail_address) 
VALUES (N'001', N'청담동'),
        (N'002', N'삼성동'),
        (N'003', N'대치동'),
        (N'009', N'논현동'),  -- 값 실수
        (N'', N'청담동'),  -- 값 실수
        (N'', N'대치동');  -- 값 실수
GO

-- 우편번호 테이블 생성
CREATE TABLE MailsNumer(
mails_num_idx INT IDENTITY(1,1) PRIMARY KEY
, mail_num NVARCHAR(3)
, mail_address NVARCHAR(6)
);
GO

INSERT INTO MailsNumer
VALUES (N'001', N'청담동'),
        (N'002', N'삼성동'),
        (N'003', N'대치동'),
        (N'004', N'논현동');
GO

-- 테스트 조회
SELECT * FROM Mails;
SELECT * FROM MailsNumer;
GO

 

우편물 테이블을 살펴보면, 주소와 우편번호가 일치하는 로우도 있고, 오류가 있는 로우도 있습니다. 우편물 테이블 개별 로우를 하나씩 읽어 우편번호 테이블과 비교해 주소에 맞는 우편번호로 UPDATE 해야 합니다. 


커서로 아래 SQL 구문처럼 진행합니다.

--커서 선언
DECLARE curMailTask CURSOR FAST_FORWARD
FOR
SELECT mail_idx, mail_num, mail_address FROM Mails;

--커서 오픈
OPEN curMailTask

--변수 선언
DECLARE @mail_idx INT
DECLARE @mail_num NVARCHAR(3)
DECLARE @mail_address NVARCHAR(6)

DECLARE @fetched_num NVARCHAR(3)

--첫 로우 FETCH
FETCH NEXT FROM curMailTask INTO @mail_idx, @mail_num, @mail_address

WHILE @@FETCH_STATUS = 0
BEGIN
    -- FETCH 된 우편물의 정확한 우편물 번호를 가져옴
    SET @fetched_num = (SELECT mail_num FROM MailsNumer WHERE mail_address LIKE @mail_address)
    -- 만약 우편번호 테이블에서 가져온 정확한 우편번호와 우편물의 우편번호가 다르면 UPDATE 수행
    IF @fetched_num <> @mail_num
    BEGIN
        UPDATE Mails SET mail_num = @fetched_num
        WHERE mail_idx = @mail_idx
    END

--다음 로우 FETCH - 루프
FETCH NEXT FROM curMailTask INTO @mail_idx, @mail_num, @mail_address
END

--커서 CLOSE
CLOSE curMailTask;

--커서 DEALLOCATE
DEALLOCATE curMailTask;
GO


-- 테스트 조회
SELECT * FROM Mails;

결과
mail_idx    mail_num mail_address
----------- -------- ------------
1           001      청담동
2           002      삼성동
3           003      대치동
4           004      논현동
5           001      청담동
6           003      대치동

 

실행 후 결과를 확인해 보면, 이렇게 주소에 맞는 우편번호로 모두 업데이트가 잘 수행된 것을 볼 수 있습니다.


커서 구문을 처음에 보면, 길고 복잡해 보입니다. 하지만, 핵심만 잘 이해하면 되니 걱정 마세요, 다음 강좌에서는 커서에 대해 단계별로 상세히 살펴보겠습니다.
 

 

SQL 강좌 책 구매

강좌가 도움이 되셨다면, 책으로 구매 가능합니다. 책 판매 수익금은 전액 코딩 교육 사회공헌 활동에 기부되며, 아래 링크에서 구매하시면 더 많은 금액이 기부됩니다. 

 

책구매 링크: 챗GPT와 함께하는 마이크로소프트 SQL Server 2022 

책구매링크.png

No. Subject Author Date Views
Notice SQL강좌: 챗GPT와 함께 배우는 SQL Server 무료 강좌 목차와 소개 (2023년 9월 업데이트) 코난(김대우) 2023.08.18 40013
Notice Python 무료 강좌 - 기초, 중급, 머신러닝(2023년 6월 업데이트) 코난(김대우) 2021.01.01 21950
2294 SQL강좌: 12-1. 인덱스 생성과 관리 - 인덱스(Index) 소개 file 코난(김대우) 2023.08.18 125
2293 SQL강좌: 11-8. 관계형 데이터베이스 이해 - 데이터베이스 구현 코난(김대우) 2023.08.18 58
2292 SQL강좌: 11-7. 관계형 데이터베이스 이해 - 데이터베이스 물리적 설계 코난(김대우) 2023.08.18 64
2291 SQL강좌: 11-6. 관계형 데이터베이스 이해 - 데이터베이스 논리적 설계 코난(김대우) 2023.08.18 51
2290 SQL강좌: 11-5. 관계형 데이터베이스 이해 - 데이터베이스 설계 요구사항(Requirements) 분석과 개념적 설계 코난(김대우) 2023.08.18 57
2289 SQL강좌: 11-4. 관계형 데이터베이스 이해 - 데이터베이스 설계 목표와 고려사항 코난(김대우) 2023.08.18 51
2288 SQL강좌: 11-3. 관계형 데이터베이스 이해 - 데이터베이스 설계 단계 file 코난(김대우) 2023.08.18 64
2287 SQL강좌: 11-2. 관계형 데이터베이스 이해 - 데이터베이스 생명주기 file 코난(김대우) 2023.08.18 57
2286 SQL강좌: 11-1. 관계형 데이터베이스 이해 - 관계형 모델 코난(김대우) 2023.08.18 83
2285 SQL강좌: 10-4. T-SQL 프로그래밍 - 공통 테이블 식(CTE-Common Table Expression) 코난(김대우) 2023.08.18 105
2284 SQL강좌: 10-3. T-SQL 프로그래밍 - 변수, 조건문(IF-ELSE), 반복문(WHILE), CASE 표현식 코난(김대우) 2023.08.18 92
2283 SQL강좌: 10-2. T-SQL 프로그래밍 - 일괄처리(Batch) 코난(김대우) 2023.08.18 69
2282 SQL강좌: 10-1. T-SQL 프로그래밍 - 소개 코난(김대우) 2023.08.18 72
2281 SQL강좌: 9-3. 커서 - 현업에서 커서 사용 및 주의사항 코난(김대우) 2023.08.18 105
2280 SQL강좌: 9-2. 커서 - 커서 구문 코난(김대우) 2023.08.18 72
» SQL강좌: 9-1. 커서(CURSOR) - 커서 소개 코난(김대우) 2023.08.18 105
2278 SQL강좌: 8-7. 저장 프로시저 - 프로시저 캐시와 RECOMPILE 코난(김대우) 2023.08.18 89
2277 SQL강좌: 8-6. 저장 프로시저 - 종속성(Dependency) 확인 코난(김대우) 2023.08.18 102
2276 SQL강좌: 8-5. 저장 프로시저 - OUTPUT 파라미터 코난(김대우) 2023.08.18 93
2275 SQL강좌: 8-4. 저장 프로시저 - 동적 SQL(Dynamic SQL)과 SQL 주입(Injection) 공격 코난(김대우) 2023.08.18 125





XE Login