1) SELECT문 또는 데이터 조작어 같은 SQL문을 실행했을 때 해당 SQL문을 처리하는 정보를 저장한 메모리 공간
(메모리 공간은 Private SQL Area라고 부르며 정확히 표현하자면 커서는 이 메모리의 포인터를 말합니다.)
2) 커서는 사용 방법에 따라 명시적(explicit) 커서와 묵시적(implicit) 커서로 나뉩니다.
SELECT 컬럼1, 컬럼2, ...INTO 변수1, 변수2 ...1) 단계
2) 작성법
DECLARE
CURSOR 커서이름 IS SQL문; -- 커서 선언(Declaration)
BEGIN
OPEN 커서 이름; - 커서 열기(open)
FETCH 커서이름 INTO 변수 -- 커서로부터 읽어온 데이터 사용(Fetch)
CLOSE 커서이름; -- 커서 닫기(Close)
END;

3) 하나의 행만 조회되는 경우

4) 여러 행이 조회되는 경우 사용하는 LOOP문
DECLARE
V_DEPT DEPT%ROWTYPE;
CURSOR C1 IS
SELECT * FROM DEPT;
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO V_DEPT;
-- 커서의 값 중 %NOTFOUND가 참일때 더 이상 읽을 레코드가 없다.
EXIT WHEN C1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('DEPTNO: '|| V_DEPT.DEPTNO);
DBMS_OUTPUT.PUT_LINE('DNAME: '|| V_DEPT.DNAME);
DBMS_OUTPUT.PUT_LINE('LOC: '|| V_DEPT.LOC);
DBMS_OUTPUT.PUT_LINE('------------------------');
END LOOP;
CLOSE C1;
END;

5) 여러 개의 행이 조회되는 경우(FOR LOOP문)
DECLARE
CURSOR C1 IS
SELECT * FROM DEPT;
BEGIN
FOR d IN C1 LOOP
DBMS_OUTPUT.PUT_LINE('DEPTNO: '|| d.DEPTNO);
DBMS_OUTPUT.PUT_LINE('DNAME: '|| d.DNAME);
DBMS_OUTPUT.PUT_LINE('LOC: '|| d.LOC);
DBMS_OUTPUT.PUT_LINE('~~~~~~~~~~~~~');
END LOOP;
END;

6) 커서에 파라미터 사용하기
CURSOR 커서명(변수명 자료형, ...) IS
SELECT ...변수는 SELECT문 내에서 사용 가능
OPEN 커서명(값,...);
DECLARE
V_DEPT DEPT%ROWTYPE;
CURSOR C1 IS
SELECT * FROM DEPT;
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO V_DEPT;
-- 커서의 값중 %NOTFOUND가 참 -> 더이상 읽을 레코드가 없다.
EXIT WHEN C1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('DEPTNO : ' || V_DEPT.DEPTNO);
DBMS_OUTPUT.PUT_LINE('DNAME : ' || V_DEPT.DNAME);
DBMS_OUTPUT.PUT_LINE('LOC : ' || V_DEPT.LOC);
DBMS_OUTPUT.PUT_LINE('----------------------------');
END LOOP;
CLOSE C1;
END;
3) 묵시적 커서의 속성 사용하기
EXCEPTION
WHEN 예외 이름1 [OR 예외 이름2 - ] THEN
예외 처리에 사용할 명령어;
WHEN 예외 이름3 [OR 예외 이름4 - ] THEN
예외 처리에 사용할 명령어;
...
WHEN OTHERS THEN
예외 처리에 사용할 명령어;


예외를 처리하는 PL/SQL(예외 처리 추가)

예외 발생 후의 코드 실행 여부 확인하기

예외 종류



DECLARE
--V_DNAME NUMBER;
V_DNAME VARCHAR2(20);
V_NUM NUMBER := 10;
BEGIN
SELECT DNAME INTO V_DNAME FROM DEPT WHERE DEPTNO=10;
--예외 발생하면 하단 코드 실행 안되고 예외처리 문으로 넘어간다.
DBMS_OUTPUT.PUT_LINE(V_NUM / 0);
EXCEPTION
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('수치 또는 값 오류');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('여러행 조회 오류');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('기타 오류');
END;
--기타 오류

DECLARE
--V_DNAME NUMBER;
V_DNAME VARCHAR2(20);
V_NUM NUMBER := 10;
BEGIN
SELECT DNAME INTO V_DNAME FROM DEPT WHERE DEPTNO=10;
--예외 발생하면 하단 코드 실행 안되고 예외처리 문으로 넘어간다.
DBMS_OUTPUT.PUT_LINE(V_NUM / 0);
EXCEPTION
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('수치 또는 값 오류');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('여러행 조회 오류');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('기타 오류');
DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || TO_CHAR(SQLCODE));
DBMS_OUTPUT.PUT_LINE('SQLERRM: '|| SQLERRM);
END;
