* CURSOR
CURSOR란 시스템 글로벌 영역의 공유 풀 내에 저장공간을 사용하여 사용자가 SQL문을 실행시키면 결과 값을 저장공간에 가지고 있다가 원하는 시기에 순차적으로 FETCH 처리하여 해당결과 셋을 프로그래밍적으로 접근할 수 있도록 도와주는 기능입니다.
* CURSOR 사용이유
- 커서를 사용시 SQL구문을 다시 돌리지 않으므로 보다 빠르고 간단히 처리가 가능합니다.
- SELECT 절의 결과가 하나의 행일 경우는 INTO절에 들어가지만, 결과가 여러개일 경우에는 INTO절로 처리 불가능하므로 이럴때 사용하는것이 CURSOR입니다.
* FETCH
커서에서 원하는 결과값을 출력하는 것을 뜻합니다.
* 커서의 속성
- %Found : 할당할 에코드가 있는경우 true를 값을 반환
- %isOpen : 커서가 오픈상태일 경우 true 값을 반환
- %NotFound : 할당할 레코드가 없는경우 true 값을 반환
- %RowCount : 카운터 역할, 커서가 오픈됐을 경우 0, 패치가 발생할 때마다 1씩 증가
----------------------------------------------------------------------
커서는 크게 묵시적커서와 명시적커서 이렇게 둘로 나뉘어집니다.
묵시적커서와 명시적커서 각각 설명과 사용예제를 보여드리며 설명하도록 하겠습니다!
----------------------------------------------------------------------
* 묵시적커서
- 오라클 DB에서 실행되는 모든 SQL문장은 암시적인 커서가 생성되며, 커서 속성을 알 수 없습니다.
- 묵시적인 커서는 오라클이나 SQL실행 메커니즘에 의해 처리되는 SQL문장이 처리되는 곳에 대한 익명주소입니다.
- ORACLE 서버에서 SQL문을 처리하기 위해 내부적으로 생성하고 관리합니다.
- 묵시적커서는 SQL문이 실행되는 순간 자동으로 OPEN과 CLOSE를 실행합니다.
- SQL커서 속성을 사용하면 SQL문의 결과를 테스트 할 수 있습니다.
묵시적커서를 사용하기 위해 간단하게 테이블을 만들고 데이터를 인서트하였습니다.


각각 사원번호,사원명,직업이며 데이터 인서트후에 전체조회한 결과값입니다
그 후 간단한 프로시저를 작성하여 SELECT문을 돌렸습니다.

처음 보시면 뭔가 복잡해 보일수 있지만 커서의 속성을 사용하여 SQL결과를 테스트할수 있도록 표현하였습니다
한줄씩 차례로 설명드리겠습니다.
SET SERVEROUTPUT - 결과출력명령어
SET TIMING ON - 걸린시간출력명령어
위에서 작성한 커서의 속성인 Found, isOpen, NotFound, RowCount 를 확인하기 위하여 변수선언하여 DECLARE부분에 작성하였습니다
그리고 BEGIN 부분에서
기본적으로 사용하는 조회문인 SELECT * FROM EMP_TEST 쿼리를 실행하였습니다.
마지막으로 DBMS_OUTPUT.PUT_LINE 명령어로 결과값을 보여줄수 있도록 작성하였습니다.

묵시적커서 프로시저 결과
그 결과
총 결과값이 민수,맹구,유리 세명이므로 V_CNT는 3이 나왔고,
패치는 한번사용했으므로 V_ROWCOUNT는 1,
실행문이 모두 끝났으므로 자동르로 커서가 CLOSE되어 V_ISOPEN은 FALSE
값이 있었으므로 V_FOUND는 TRUE , V_NOTFOUND는 반대로 FALSE가 나왔습니다.
--------------------------------------------------------------------
* 명시적커서
- 사용자가 선언해서 생성한 수에 사용하는 SQL 커서, 주로 여려개의 행을 처리할 때 사용
- 결과값을 글로벌영역에 저장 후 순차적으로 FETCH하여 이용
- 묵시적커서와는 다르게 명시적으로 CURSOR라고 선언하고 사용해서 명시적커서라고 부릅니다.
- 자바로 따지면 만들어논 메소드를 가져와서 필요할때마다 사용한다고 생각하시면 쉽습니다.
명시적 커서를 사용할때는 문법과 순서가 있습니다.
1. DECLARE를 통해서 SQL 영역을 생성
2. OPEN을 이용하여 만든커서명을 작성
3. FETCH를 통하여 현재행을 변수에 로드
4. CLOSE를 통해서 결과 행 집합을 해제
DECLARE
CURSOR [커서이름] IS [SELECT 구문];
BEGIN
OPEN [커서이름];
FETCH [커서이름] INTO [변수];
CLOSE [커서이름];
END;


위에서 묵시적커서와 같은 테이블을 이용하겠습니다.

명시적커서를 이용한 프로시저입니다.
보기 어려운 분들을 위에서부터 한줄씩 이해하시면서 내려오시면 쉽습니다.
- DELCARE 부분
결과 값을 보기위해 V_RESULT_MSG 변수를 선언하였고,
CUR1 이라는 커서를 만들었습니다. 전에 만든 테이블을 조회하는 SELECT문을 입력하였습니다.
사원번호(EMPL_NUMB), 사원명(EMPL_NAME), 직업(EMPL_JOB)을 각각 변수로 선언하여 결과값을 볼수 있도록 하였습니다.
- BEGIN 부분
위에서 선언한 CUR1 을 OPEN 하였습니다.
FETCH CUR1 을 적음으로서
SELECT문이 한번 실행되었습니다.
거기서 나온 값을 각각 V_EMPL_NUMB, V_EMPL_NAME, V_EMPL_JOB에 넣었습니다.
값이 없으면 커서를 종료하도록 %NotFound를 사용하였습니다.
결과 값이 한개의 행이 였으면 상관없지만 민수,맹구,유리 총 세명이기 때문에 LOOP문법으로 여러번 돌렸습니다.
마지막은 CLOSE로 커서를 닫았습니다.
자바로 따지면 LOOP가 for문이고 NotFound가 break라고 생각하시면 될 것 같습니다.

명시적커서 프로시저 결과문입니다.
----------------------------------------------------------------------
CURSOR를 사용하면 SQL문을 여러번 돌리지 않고 위에 선언한 구문을 기억했다가 그대로 실행하므로 보다 빠르게 프로시저 문을 돌릴 수 있습니다.
그리고 보통 SELECT후, 변수에 INTO하여 그 값을 인서트 하는 구문을 작성할 때,
SELECT한 값이 두개 이상이면 오류가 납니다.
그럴때 이런식으로 커서를 사용하거나 루프문을 돌려서 사용하시면 오류나지 않고 사용가능합니다.
읽어주셔서 감사합니다.
'데이터베이스 > ORACLE' 카테고리의 다른 글
[ORACLE] 오라클 LPAD, RPAD (0) | 2023.01.13 |
---|---|
[ORACLE] 오라클 비교연산자 <> ! = (0) | 2023.01.13 |
[ORACLE] 오라클 정규표현식 REGEXP 함수 사용 (1) | 2023.01.13 |
[ORACLE] 오라클 SYSDATE 사용법(현재시간값) (0) | 2021.04.12 |
[ORACLE] 오라클 NVL(NVL2) 사용법 (0) | 2021.04.12 |