[PL/SQL] 커서(CURSOR), 예외(Exception)

2022. 7. 19. 11:34·Back-End/PL SQL

PL/SQL - 커서(CURSOR)

  • SELECT 문장을 실행하면 조건에 따른 결과 집합이 추출 되고, 해당 쿼리에 따른 결과가 메모리 상 위치
  • 커서를 통해서 해당 결과의 각 개별 데이터에 접근

커서의 사용

  1. DECLARE(커서 선언)
-- CURSOR 커서명 IS select문;
DECLARE CURSOR cursor_name IS select_statement;
  1. OPEN(커서 열기)
    • 질의를 실행하기 위해 커서를 열고 Active set 설정
    • 질의 수행 후 반환되는 행이 없더라도 에러가 발생하지 않는다.
    • Cursor attribute를 이용해서 추출 후 수행결과를 확인할 수 있다.
--OPEN 커서명;
OPEN CURSOR_NAME;
  1. FETCH(커서 인출)
    • 현재 행의 값을 출력변수로 할당
    • 컬럼과 변수의 개수가 같도록 한다.
--FETCH 커서명 INTO 변수;
FETCH cursor_name INTO variable1, variable2,.....;
  1. 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 예외 처리부로 넘어오게 된다.

예외 유형

  1. Predefined 오라클 서버 예외 : PL/SQL에서 이름을 미리 정의한 오류
  2. Non-Predefined 오라클 서버 예외 : 미리 정의되어 있지 않은 오라클 서버오류
  3. 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;
/
반응형
'Back-End/PL SQL' 카테고리의 다른 글
  • [PL/SQL] 변수 선언
  • [PL/SQL] 프로시저(Procedure)란?
LightSource
LightSource
어제보단 발전한 오늘의 나를 위한 블로그
    반응형
  • LightSource
    LightSourceCoder
    LightSource
  • 전체
    오늘
    어제
    • 분류 전체보기 (152)
      • Git (4)
      • Language (6)
        • Java (6)
      • Back-End (63)
        • Spring Boot (4)
        • MyBatis (1)
        • Oracle (1)
        • PL SQL (3)
        • JPA (26)
        • Spring Data JPA (5)
        • Spring MVC (8)
        • Spring (12)
        • Spring Security (2)
        • Redis (1)
      • Front-End (38)
        • 아이오닉 (2)
        • JSP (7)
        • JavaScript (4)
        • React (16)
        • TypeScript (3)
        • Angular (6)
      • AWS (1)
      • CI & CD (1)
      • 개발지식 (13)
        • 네트워크 (9)
        • CS 지식 (4)
      • 데이터모델링 (2)
      • Tool (1)
      • 프로젝트 (5)
      • 독후감 (2)
      • 잡생각 (0)
      • 면접 준비 (1)
      • 알고리즘 (14)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    리액트
    배열요소삭제
    배열요소수정
    react
    배요소열추가
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
LightSource
[PL/SQL] 커서(CURSOR), 예외(Exception)
상단으로

티스토리툴바