[MySQL] CURSOR

참고

MySQL Documentation 13.6.6 Cursors

설명

  • stored programs 내부에서 사용된다.
  • BEGIN ... END블록에서 DECLARE로 선언되는데 그 위치는 variablehandler의 사이에 위치한다.
  • 다음과 같은 특성을 가진다.
  • Asensitive: 서버가 결과 테이블의 복사본을 만들 수도 있고 만들지 않을 수도 있다
  • Read only: Not updatable
  • Nonscrollable: 한 방향으로만 이동할 수 있으며 row를 건너뛸 수 없음

syntax

BEGIN
  DECLARE cursor_done_variable INT DEFAULT FALSE;
  DECLARE var_name1 type [DEFAULT value];
  [DECLARE var_name2 type [DEFAULT value];]
  DECLARE cursor_name CURSOR FOR select_statement;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET cursor_done_variable = TRUE;

  OPEN cursor_name;

  loop_name: LOOP
    FETCH cursor_name INTO var_name1 [, var_name2];
    IF cursor_done_variable THEN
      LEAVE loop_name;
    END IF;

    statement_list;
  END LOOP;

  CLOSE cursor_name;
END;

DECLARE

DECLARE cursor_name CURSOR FOR select_statement
  • CURSOR를 선언하고 select_statementcursor_name에 rows를 넣는다.
  • select_statementINTO clause를 사용할 수 없다.
  • BEGIN ... END블록 내에 복수의 CURSOR가 존재할 수 있음(고유한 cursor_name을 가져야 함)

OPEN

OPEN cursor_name
  • 선언된 CURSOR를 연다.

FETCH

FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...
  • CURSOR cursor_name를 선언할 때 사용한 select_statement의 컬럼 수에 맞춰 var_name수가 작성되어야 함
  • cursor_name의 모든 rows가 fetch 되면 SQLSTATE값이 '02000'인 No Data condition이 발생한다.
  • 이 condition를 감지하기 위해서 NOT FOUND HANDLER를 사용하여 처리할 수 있다.

CLOSE

CLOSE cursor_name
  • 이전에 열린 CURSOR를 닫는다.
  • 만약 CURSOR가 열리지 않았다면 error 발생
  • 만약 CLOSE로 명시적으로 cursor가 닫히지 않는다면 *BEGIN .. END 블록이 끝날 때 닫힌다.

예시

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b; -- 하나 이상의 CURSOR가 fetch 되는 경우
    FETCH cur2 INTO c;  -- 이 둘 중 하나에서 더이상 fetch될 rows가 없는 경우 위에서 선언한 NOT FOUND 핸들러가 작동한다.
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;

links

social