[PL/SQL] 커서(CURSOR) (1) : 명시적 커서와 묵시적 커서
[PL/SQL] 커서(CURSOR) (2) : 커서와 FOR문
[PL/SQL] 커서(CURSOR) (3) : 커서변수
커서(CURSOR)
특정 SQL 문장을 처리한 결과를 담고있는 영역을 가리키는 일종의 포인터로, 커서를 사용하면 처리된 SQL문장의 결과 집합에 접근할 수 있다.
(커서선언(명시적커서))-커서열기-패치-커서닫기 3단계로 진행된다.
묵시적 커서
오라클 내부에서 자동으로 생성되어 사용하는 커서로, PL/SQL 블록에서 실행하는 문장(INSERT, UPDATE, MERGE, DELETE, SELECT INTO)이 실행될 때마다 자동으로 만들어져 사용된다.
개발자 입장에서는 이러한 커서의 동작을 관여할 수는 없지만, 커서 속성을 이용하면 해당 커서에 대한 여러가지 정보를 얻어낼 수 있다.
명시적 커서
사용자가 직접 정의해서 사용하는 커서를 말한다.
묵시적 커서
묵시적커서 속성
1 2 3 4 5 | SQL%FOUND 결과 집합의 패치 로우 수가 1개 이상이면 TRUE, 아니면 FALSE를 반환 SQL%NOTFOUND 결과 집합의 패치 로우수가 0이면 TRUE, 아니면 FALSE를 반환 SQL%ROWCOUNT 영향 받은 결과 집합의 로우 수 반환, 없으면 0을 반환 SQL%ISOPEN 묵시적 커서는 항상 FALSE를 반환 (이 속성으로 참조할 때는 이미 해당 묵시적 커서는 닫힌 상태 이후이기 때문) | cs |
예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | DECLARE VN_DEPARTMENT_ID EMPLOYEES.DEPARTMENT_ID%TYPE := 80; BEGIN -- 80번 부서의 사원이름을 자신의 이름으로 갱신 UPDATE EMPLOYEES SET EMP_NAME = EMP_NAME WHERE DEPARTMENT_ID = VN_DEPARTMENT_ID; -- 몇 건의 데이터가 갱신됬는지 출력 DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT); COMMIT; END; | cs |
명시적 커서
1. 커서 선언
사용할 커서에 이름을 부여하고 이 커서에 대한 쿼리를 선언해야한다.
명시적 커서란 것이 결과 데이터 집합을 로우별로 참조해서 무언가 작업을 하기위한 용도이므로 당연히 커서를 정의해 사용하는 문장은 SELECT이다.
1 2 3 | CURSOR 커서명[(매개변수1, 매개변수2, ...)] IS SELECT 문장; | cs |
매개변수는 생략이 가능한데, 매개변수를 명시하면 SELECT 문장의 WHERE절에서 조건을 체크하는 변수로 사용된다.
2. 커서 열기
1 | OPEN 커서명 [(매개변수1, 매개변수2, ...)]; | cs |
3. 패치 단계에서 커서 사용
결과 집합의 로우 수는 보통 1개 이상이므로 개별 로우에 접근하기 위해서는 반복문을 사용한다.
1 2 3 4 5 | LOOP FETCH 커서명 INTO 변수1, 변수2, ...; EXIT WHEN 커서명%NOTFOUND; END LOOP; | cs |
FETCH INTO를 통해 커서에서 반환되는 각 컬럼 값을 변수에 할당할 수 있다. 이쌔, 변수는 반환된 컬럼 수와 타입이 일치해야한다.
반복문을 사용하므로 해당 커서의 참조가 모두 끝났을 때 반복문을 빠져나와야하는데, 이때 '커서명%NOTFOUND' 커서 속성을 사용해 루프를 벗어난다.
4.커서 닫기
1 | CLOSE 커서명; | cs |
예제
1234567891011121314151617181920212223242526 DECLARE -- 사원명을 받아오기 위한 변수 선언 VS_EMP_NAME EMPLOYEES.EMP_NAME%TYPE; -- 커서 선언, 매개변수로 부서코드를 받기 CURSOR CUR_EMP_DEP ( CP_DEPARTMENT_ID EMPLOYEES.DEPARTMENT_ID%TYPE ) IS SELECT EMP_NAME FROM EMPLOYEES WHERE DEPARTMENT_ID = CP_DEPARTMENT_ID;BEGIN -- 커서 오픈 OPEN CUR_EMP_DEP(90); -- 반복문을 통한 커서 패치 작업 LOOP -- 커서 결과로 나온 로우를 패치함 FETCH CUR_EMP_DEP INTO VS_EMP_NAME; -- 패치된 참조 로우가 더 없으면 LOOP 탈출 EXIT WHEN CUR_EMP_DEP%NOTFOUND; -- 사원명을 출력 DBMS_OUTPUT.PUT_LINE(VS_EMP_NAME); END LOOP; CLOSE CUR_EMP_DEP;END; cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | DECLARE -- 사원명을 받아오기 위한 변수 선언 VS_EMP_NAME EMPLOYEES.EMP_NAME%TYPE; -- 커서 선언, 매개변수로 부서코드를 받기 CURSOR CUR_EMP_DEP ( CP_DEPARTMENT_ID EMPLOYEES.DEPARTMENT_ID%TYPE ) IS SELECT EMP_NAME FROM EMPLOYEES WHERE DEPARTMENT_ID = CP_DEPARTMENT_ID; BEGIN -- 커서 오픈 OPEN CUR_EMP_DEP(90); -- 반복문을 통한 커서 패치 작업 LOOP -- 커서 결과로 나온 로우를 패치함 FETCH CUR_EMP_DEP INTO VS_EMP_NAME; -- 패치된 참조 로우가 더 없으면 LOOP 탈출 EXIT WHEN CUR_EMP_DEP%NOTFOUND; -- 사원명을 출력 DBMS_OUTPUT.PUT_LINE(VS_EMP_NAME); END LOOP; CLOSE CUR_EMP_DEP; END; | cs |
주의할 점
커서를 사용할 때는 반드시 먼저 커서를 열고 사용이 끝나면 닫아야한다. ('닫는다'는 것은 메모리상에 존재하는 커서의 쿼리 결과를 소멸시키는 것을 의미한다.)
[PL/SQL] 커서(CURSOR) (1) : 명시적 커서와 묵시적 커서
'📃 DATABASE > ORACLE' 카테고리의 다른 글
[PL/SQL] 커서(CURSOR) (3) : 커서 변수 (0) | 2018.02.01 |
---|---|
[PL/SQL] 커서(CURSOR) (2) : 커서와 FOR문 (0) | 2018.02.01 |
[PL/SQL] 트랜잭션 (0) | 2018.01.29 |
[PL/SQL] 예외처리(3) : 효율적인 예외처리 (2) | 2018.01.26 |
[PL/SQL] 예외처리(2) : 시스템 예외와 사용자정의 예외 (0) | 2018.01.25 |