상세 컨텐츠

본문 제목

T-SQL - Cursor (커서)

본문

오늘은 커서에 대해서 알아보도록 하겠습니다.  어떤 리스트에서 루프로 돌리면서 한 루프에 몇 가지 데이터를 저장하여 사용할 때 커서가 많이 쓰입니다.  SQL (시퀄)에서는 테이블을 불러와서 각 Row 당 처리를 하는 방법이 많지는 않아서 커서가 대표적으로 쓰이죠.  하지만 커서는 서버의 리소스를 이용하는 기능이라 잘못 이용하다가는 서버 과부하가 되니 꼭 알아둬야 할 몇 가지가 있습니다.
 

반응형

왜 이름이 커서가 됐을까요.  영어로는 커서라는 뜻이 어떤 곳을 지정하는 물체 정도의 뜻이 되거든요.  그래서 데이터중 어떤 곳의 위치를 지정한다는 뜻으로 이 단어가 쓰이는 것입니다.  마우스의 커서도 그 뜻이 있지요.
 
아래의 코드로 설명드릴게요


우선 커서와 루프에 이용될 변수들을 지정합니다

-- 변수 지정
DECLARE @city_name VARCHAR(128);
DECLARE @country_name VARCHAR(128);
DECLARE @city_id INT;
 
-- 커서 지정
DECLARE cursor_city_country CURSOR FOR
  SELECT city.id, TRIM(city.city_name), TRIM(country.country_name)
  FROM city
  INNER JOIN country ON city.country_id = country.id;

 
지정된 커서를 아래와 같이 오픈합니다

-- 커서 오픈
OPEN cursor_city_country;

 
루프 구동전에 아래같이 FETCH라는 커맨드로 커서를 이용하여 변수에 데이터를 넣습니다.

FETCH NEXT FROM cursor_city_country INTO @city_id, @city_name, @country_name;

 
그리고 루프를 구동합니다.  @@FETCH_STATUS 변수는 커서에 데이터가 없으면 0이라는 값이 리턴이 되므로 루프의 컨디션을 WHILE @@FETH_STATUS = 0로 넣는 거죠.  그러면 루프가 끝나는 시기는 커서에 지정된 값이 없을 때죠.   그리고 루프 마지막에 다시 FETCH를 써서 계속 값을 지정시킵니다.  테이블 마지막이 지나면 자동적으로 값이 지정이 되지 않습니다.

WHILE @@FETCH_STATUS = 0
    BEGIN
    PRINT CONCAT('city id: ', @city_id, ' / city name: ', @city_name, ' / country name: ', @country_name);
    FETCH NEXT FROM cursor_city_country INTO @city_id, @city_name, @country_name;
    END;

 

728x90

 
마지막으로 쓰고 있는 서버 리소스를 커서를 닫으면서 다시 돌려놓습니다.  이 부분이 아주 중요합니다.  CLOSE와 DEALLOCATE둘다 쓰셔야 하죠.  오픈된 커서를 닫고 (Close), Allocate 된 서버의 리소스를 Deallocate 한다는 커맨드입니다.  이걸 안 쓰면 커서에 쓰이던 메모리가 계속 이 커서에 축적이 되어서 나중엔 크래시가 되는 거죠.

-- 커서 닫기
CLOSE cursor_city_country;
DEALLOCATE cursor_city_country;

아래가 완전체 코드 블록입니다.

-- 변수 지정
DECLARE @city_name VARCHAR(128);
DECLARE @country_name VARCHAR(128);
DECLARE @city_id INT;
 
-- 커서 지정
DECLARE cursor_city_country CURSOR FOR
  SELECT city.id, TRIM(city.city_name), TRIM(country.country_name)
  FROM city
  INNER JOIN country ON city.country_id = country.id;
 
-- 커서 오픈
OPEN cursor_city_country;
 
-- 커서를 이용한 루프
FETCH NEXT FROM cursor_city_country INTO @city_id, @city_name, @country_name;
WHILE @@FETCH_STATUS = 0
    BEGIN
    PRINT CONCAT('city id: ', @city_id, ' / city name: ', @city_name, ' / country name: ', @country_name);
    FETCH NEXT FROM cursor_city_country INTO @city_id, @city_name, @country_name;
    END;
 
-- 커서 닫기
CLOSE cursor_city_country;
DEALLOCATE cursor_city_country;

수고하셨습니다.  즐거운 코딩되세요!


도움이 되셨거나 즐거우셨다면 아래의 ❤️공감버튼이나 구독버튼을 눌러 주세요~  감사합니다

 

 

728x90
반응형

관련글 더보기