hyeonga_code

Database_86_PL/SQL_제어 구조_예외 처리 본문

Oracle Database

Database_86_PL/SQL_제어 구조_예외 처리

hyeonga 2023. 8. 31. 08:59
반응형

-- PL/SQL 제어 구조

    -- 예외 처리
        -- 예외 : 프로그램 실행 중 발생한 오류입니다.
        -- 발생하는 경우
            -- 시스템 예외 : Oracle Server에 의해 암시적으로 발생합니다.
            -- 사용자 정의 예외 : 프로그램에 의해 명시적으로 발생합니다.
        -- 처리 방법
            -- 처리기로 트랩
            -- 호출 환경으로 전달
        -- 예외를 프로그래밍하면 실행 중단을 방지할 수 있습니다.
    
-- 오류 발생 시 출력되는 기본 메세지를 확인합니다.
DECLARE
    v_lname VARCHAR2(15);
BEGIN
    SELECT last_name INTO v_lname 
    FROM employees
    WHERE department_id = 50;
    DBMS_OUTPUT.PUT_LINE ('John''s last name is :' ||v_lname);
END;

    /*
        -----<오류>---------------------------------------------------------------------
        오류 보고 -
        ORA-01422: exact fetch returns more than requested number of rows
        ORA-06512: at line 4
        01422. 00000 -  "exact fetch returns more than requested number of rows"
        *Cause:    The number specified in exact fetch is less than the rows returned.
        *Action:   Rewrite the query or change number of rows requested
        --------------------------------------------------------------------------------
    */

-- 오류 발생 시 원하는 메세지를 출력할 수 있습니다.
SET SERVEROUTPUT ON;
DECLARE
    v_lname VARCHAR2(15);
BEGIN
    SELECT last_name INTO v_lname 
    FROM employees
    WHERE department_id = 50;
    DBMS_OUTPUT.PUT_LINE ('John''s last name is :' ||v_lname);
    EXCEPTION
        WHEN TOO_MANY_ROWS THEN
        DBMS_OUTPUT.PUT_LINE ('Your select statement retrieved multiple 
                                rows.Consider using a cursor.');
END;
/
    /*
    Your select statement retrieved multiple rows. 
    Consider using a cursor.
    
    PL/SQL 프로시저가 성공적으로 완료되었습니다.
    */
    
        -- 구문
            /*
            EXCEPTION --미리 정의된 예외의 표준 이름 또는 사용자가 선언 부분에 정의한 예외의 이름
                WHEN exception1 [OR exception2 . . .] THEN
                    statement1; --하나 이상의 PL/SQL 또는 SQL 문
                    statement2;
                    . . .
                [WHEN exception3 [OR exception4 . . .] THEN
                    statement1;
                    statement2;
                    . . .]
                [WHEN OTHERS THEN --지정되지 않은 예외를 트랩하는 선택적 예외 처리 절
                    statement1;
                    statement2;
                    . . .]
            */
            -- PL/SQL 블록의 예외 처리 부분에 해당 루틴을 포함시켜 오류를 트랩할 수 있습니다.
            -- 각 처리기는 예외를 지정하는 WHEN 절과 예외 발생 시 실행될 일련의 명령문으로 구성됩니다.
            -- 주의 사항
                -- 예외 처리 섹션은 EXCEPTION 키워드로 시작합니다.
                -- 블록에 대해 각각 고유의 작업 집합을 가진 여러 개의 예외 처리기를 정의합니다.
                -- 예외가 발생하면 PL/SQL은 하나의 처리기만 거친 뒤 블록을 종료합니다.
                -- WHEN OTHERS는 마지막 절입니다.
        -- 예외 유형    
            -- 미리 정의된 Oracle Server 오류
                /*
                BEGIN
                . . .
                EXCEPTION
                    WHEN NO_DATA_FOUND THEN
                        statement1; 
                        statement2; 
                    WHEN TOO_MANY_ROWS THEN
                        statement1;
                    WHEN OTHERS THEN
                        statement1; 
                        statement2; 
                        statement3;
                END;
                */
                -- PL/SQL 코드에서 자주 발생하는 약 20가지 오류 중 하나입니다.
                -- Oracle Server가 암시적으로 실행하므로 선언하지 않습니다.
                -- 예제
                    -- 항상 처리하는 것이 좋은 예제
                        -- NO_DATA_ROUND
                        -- TOO_MANY_ROWS
                        -- INVALID_CURSOR
                        -- ZERO_DIVIDE
                        -- DUP_VAL_ON_INDEX
            -- 미리 정의되지 않은 Oracle Server 오류
                -- 다른 표준 Oracle Server 오류입니다.
                -- 선언 부분에서 선언합니다.
                -- Oracle Server가 암시적으로 발생시킵니다.
                -- 오류를 먼저 선언하거나 OTHERS 처리기를 사용합니다.
            -- 사용자가 정의한 오류
                -- 개발자가 비정상이라고 판단하는 조건입니다.
                -- 선언 부분에서 선언합니다.
                -- 명시적으로 발생시킵니다.

    -- 미리 정의되지 않은 Oracle Server 오류 트랩
-- 다음 PL/SQL은 Oracle Server 오류 01400 (“cannot insert NULL”)을 트랩합니다.
DECLARE
    e_insert_excep EXCEPTION; --선언 부분에 예외의 이름을 선언
    --앞에서 선언한 예외와 표준 Oracle Server 오류 번호를 연결
    PRAGMA EXCEPTION_INIT(e_insert_excep, -01400); 
BEGIN
    INSERT INTO departments 
    (department_id, department_name) VALUES (280, NULL);
    EXCEPTION
        WHEN e_insert_excep THEN --선언한 예외를 해당 예외 처리 루틴에서 참조
        DBMS_OUTPUT.PUT_LINE('INSERT OPERATION FAILED');
        DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/      
    /*
    INSERT OPERATION FAILED
    ORA-01400: cannot insert NULL into ("HR"."DEPARTMENTS"."DEPARTMENT_NAME")
        
    PL/SQL 프로시저가 성공적으로 완료되었습니다
    */   

            
        -- 예외 트랩 관련 함수
            -- 발생한 예외 정보를 참조하기 위한 수단입니다.
            -- SQLCODE : 오류 코드의 숫자 값을 반환합니다.
            -- SQLERRM : 오류 번호와 연관된 메세지를 반환합니다.
-- SQLCODE는 “-1476”을, SQLERRM은 “ORA-01476: divisor is equal to zero”를 반환합니다.
DECLARE
    vi_num NUMBER := 0;
BEGIN
    vi_num := 10 / 0;
    DBMS_OUTPUT.PUT_LINE('Success!');
    EXCEPTION WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('오류가 발생했습니다');
        DBMS_OUTPUT.PUT_LINE('SQL ERROR CODE:' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('SQL ERROR MESSAGE:' || SQLERRM); 
END;
/
    /*
    오류가 발생했습니다
    SQL ERROR CODE:-1476
    SQL ERROR MESSAGE:ORA-01476: divisor is equal to zero
    
    PL/SQL 프로시저가 성공적으로 완료되었습니다.
    */

        -- RAISE 문
            /*
            RAISE exception_name;
            */
            -- PL/SQL 블록이나 서브 프로그램의 정상적인 실행을 정지하고 컨트롤을 예외 처리기로 전달합니다.
            -- 미리 정의된 예외나 유저가 정의한 예외를 명시적으로 발생시킵니다.
            -- 예외를 발생시키면 자동으로 제어권이 EXCEPTION 절로 넘어옵니다.
                -- 시스템 예외와 동일한 방식으로 처리합니다.
            -- RAISE_APPLICATION_ERROR
                /*
                RAISE_APPLICATION_ERROR ( error_number, message[, { TRUE | FALSE } ] );
                    -- error_number : 사용자가 예외에 지정하는 번호입니다.
                    -- message : 사용자가 예외에 지정하는 메세지입니다.
                    -- TRUE | FALSE(기본값)
                        -- TRUE : 이전 오류 스텍에 해당 오류가 추가됩니다.
                        -- FALSE : 모든 오류를 해당오류로 대체합니다.
                */
                -- 사용 위치
                    -- PL/SQL 프로그램의 실행 부분
                    -- EXCEPTION_예외 섹션
                    
DECLARE 
v_deptno NUMBER := 500;
v_name VARCHAR2(20) := 'Testing';
e_invalid_department EXCEPTION; --사용자가 정의한 예외의 이름을 선언 부분에서 선언
BEGIN
UPDATE departments
SET department_name = v_name
WHERE department_id = v_deptno;
IF SQL%NOTFOUND THEN
RAISE e_invalid_department; --실행 부분에서 RAISE 문을 사용하여 예외를 명시적으로 발생
END IF;
COMMIT;
EXCEPTION
WHEN e_invalid_department THEN --선언한 예외를 해당 예외 처리 루틴에서 참조
DBMS_OUTPUT.PUT_LINE('No such department id.');
END;
/
    /*
    No such department id.

    PL/SQL 프로시저가 성공적으로 완료되었습니다.
    */

DECLARE 
v_deptno NUMBER := 500;
v_name VARCHAR2(20) := 'Testing';
BEGIN
UPDATE departments
SET department_name = v_name
WHERE department_id = v_deptno;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR (-20000, 'No such department id.');
DBMS_OUTPUT.PUT_LINE('Department updated successfully.');
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
    /*
    ORA-20000: No such department id.

    PL/SQL 프로시저가 성공적으로 완료되었습니다.
    */

반응형