PL/SQL - 커서(CURSOR)
- SELECT 문장을 실행하면 조건에 따른 결과 집합이 추출 되고, 해당 쿼리에 따른 결과가 메모리 상 위치
- 커서를 통해서 해당 결과의 각 개별 데이터에 접근
커서의 사용
- DECLARE(커서 선언)
-- CURSOR 커서명 IS select문;
DECLARE CURSOR cursor_name IS select_statement;
- OPEN(커서 열기)
- 질의를 실행하기 위해 커서를 열고 Active set 설정
- 질의 수행 후 반환되는 행이 없더라도 에러가 발생하지 않는다.
- Cursor attribute를 이용해서 추출 후 수행결과를 확인할 수 있다.
--OPEN 커서명;
OPEN CURSOR_NAME;
- FETCH(커서 인출)
- 현재 행의 값을 출력변수로 할당
- 컬럼과 변수의 개수가 같도록 한다.
--FETCH 커서명 INTO 변수;
FETCH cursor_name INTO variable1, variable2,.....;
- CLOSE(커서 닫기)
- 행들의 처리가 끝난후 커서를 닫는다.
-- CLOSE 커서명;
CLOSE cursor_name;
커서 사용 예시
CREATE OR REPLACE PROCEDURE p_emp_info (p_dept_id s_emp.dept_id%TYPE)
-- p_emp_info 프로시저이고 %TYPE변수로 s_emp테이블의 dept_id컬럼 데이터타입을 가진다.
IS
CURSOR c_emp_sal IS
SELECT last_name, salary FROM s_emp
WHERE dept_id = p_dept_id;
-- 커서로 c_emp_sal을 선언, s_emp테이블에서 매개변수로 받은 p_dept_id와 같은 조건
-- 을 가지는 last_name과 salary 컬럼을 가지고 온다.
v_sal s_emp.salary%TYPE;
v_last_name s_emp.last_name%TYPE; -- 값을 할당할 변수 선언
BEGIN
OPEN c_emp_sal; -- 커서의 수행시작
LOOP
FETCH c_emp_sal INTO v_last_name, v_sal ; -- 루프문을 하면서 커서에 데이터를 할당한다.
IF c_emp_sal%NOTFOUND THEN -- 더이상 FETCH할 행이 없으면
EXIT; -- 종료
END IF;
DBMS_OUTPUT.PUT_LINE(c_emp_sal%rowcount || ' ' || v_last_name || ' ' || v_sal);
-- 데이터 출력
END LOOP;
CLOSE c_emp_sal; -- 커서 종료
END;
/
CURSOR FOR 루프
- 커서 FOR루프는 OPEN, FETCH, CLOSE를 자동으로 처리해 주어 커서 사용을 용이하게 해준다.
CREATE OR REPLACE PROCEDURE p_emp_info (p_dept_id s_emp.dept_id%TYPE)
IS
CURSOR c_emp_sal IS
SELECT last_name, salary FROM s_emp
WHERE dept_id = p_dept_id;
BEGIN
FOR emp_record IN c_emp_sal LOOP
DBMS_OUTPUT.PUT_LINE(emp_record.last_name || ' ' || emp_record.salary);
END LOOP;
END;
/
- FOR루프를 사용해서 코드를 많이 줄여서 LOOP문을 사용할 수 있다.
예외(Exception)
예외 처리부
EXCEPTION
WHEN expr1 [OR expr2..]THEN
statement1;
statement2;
...
[WHEN expr3 [OR expr4..]THEN
statement1;
statement2;
...]
[WHEN OTHERS THEN
statement1;
statement2;
...]
- 에러가 발생하면 더이상 블록의 BODY를 수행하지 않고 EXCEPTION 처리부로 넘어간다.
- WHEN 뒤의 EXCEPTION 이름을 차례로 비교하면서 에러를 확인하는데, 처리되지 않은 에러는 마지막 WHEN OTHERS 예외 처리부로 넘어오게 된다.
예외 유형
- Predefined 오라클 서버 예외 : PL/SQL에서 이름을 미리 정의한 오류
- Non-Predefined 오라클 서버 예외 : 미리 정의되어 있지 않은 오라클 서버오류
- User-Defined 예외 : 개발자가 정한 조건을 만족하지 못하는 오류
Predefined 오라클 서버 예외 처리
EXCEPTION
WHEN NO_DATA_FOUND THEN -- select문이 데이터가 없는 경우
v_message := TO_CHAR(v_production_id) || 'is invalid.';
WHEN TOO_MANY_ROWS THEN -- select문이 두 행 이상을 반환하는 경우
v_message := 'Data corruption in S_PRODUCT';
WHEN OTHERS THEN
v_message := 'Other error occurred.';
END
Non-predefined 예외 처리
예외 처리 방법
-- 1. 예외 이름을 선언부에 선언
exception_name EXCEPTION;
-- 2. PRAGMA EXCEPTION_INIT문을 이용해서 오라클 서버 에러번호와 선언한 예외를 연관시킨다.
PRAGMA EXCEPTION_INIT (exception, error_number);
--3. 예외처리부에서 선언된 예외를 참조
예외 처리 예시
DECLARE
v_emp_record s_emp%ROWTYPE;
e_too_many_rows EXCEPTION;
PRAGMA EXCEPTION_INIT(e_too_many_rows, -1422); -- 1422번호 에러를 e_too_many_rows와 연관
BEGIN
SELECT * INTO v_emp_record FROM s_emp;
EXCEPTION
WHEN e_too_many_rows THEN
DBMS_OUTPUT.PUT_LINE(‘There are too many rows');
END;
/
User-defined 예외 처리
예외 처리 방법
-- 1. 예외 이름을 선언부에 선언
exception_name EXCEPTION;
-- 2. RAISE문을 써서 실행부에서 명시적으로 예외를 발생
RAISE exception_name;
예외 처리 예시
DECLARE
e_1 EXCEPTION;
e_2 EXCEPTION;
e_3 EXCEPTION; -- EXCEPTION 변수 3개
v_1 NUMBER ;
BEGIN
v_1 := 10;
IF v_1 = 10 THEN DBMS_OUTPUT.PUT_LINE(v_1); -- v_1이 10이면 EXCEPTION e_1 실행
RAISE e_1;
ELSE IF v_1 = 20 THEN DBMS_OUTPUT.PUT_LINE(v_1); -- v_2이 20이면 EXCEPTION e_2 실행
RAISE e_2;
ELSE DBMS_OUTPUT.PUT_LINE(v_1); RAISE e_3; -- v_3이 30이면 EXCEPTION e_3 실행
END IF;
DBMS_OUTPUT.PUT_LINE('LAST STATEMENT');
EXCEPTION
WHEN e_1 THEN DBMS_OUTPUT.PUT_LINE('E_1: Value is 10');
WHEN e_2 THEN DBMS_OUTPUT.PUT_LINE('E_2: Value is 20');
WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('E_3: Value is not 10 or 20');
END;
/
반응형