수색…


소개

오라클은 다양한 예외를 만들어냅니다. 불분명 한 메시지로 코드를 중지하는 것이 얼마나 지루한 지 놀라실 수 있습니다. PL / SQL 코드의 기능을 쉽게 개선하려면 가장 낮은 레벨에서 예외를 처리해야합니다. 카펫 아래에 예외를 숨기지 마십시오. 코드를 유지하고 다른 사람이 유지할 수 없으면 예외가 아닙니다.

미리 정의 된 오류 .

예외 처리

  1. 예외 란 무엇입니까?

    PL / SQL의 예외는 프로그램 실행 중에 작성되는 오류입니다.

    예외 유형은 세 가지입니다.

    • 내부적으로 정의 된 예외
    • 미리 정의 된 예외
    • 사용자 정의 예외
  1. 예외 처리 란 무엇입니까?

    예외 처리는 예를 들어 코딩 실수, 하드웨어 오류로 인해 런타임 오류가 발생하더라도 프로그램을 계속 실행하는 가능성이 있습니다. 갑자기 종료되는 것을 피합니다.

통사론

예외 섹션의 일반 구문 :

declare
    declaration Section
begin
    some statements

exception
    when exception_one then
        do something
    when exception_two then
        do something
    when exception_three then
        do something
    when others then
        do something
end;

예외 섹션은 PL / SQL 블록의 끝에 있어야합니다. PL / SQL은 블록을 중첩 할 수있는 기회를 제공하며, 각 블록에는 다음과 같은 자체 예외 섹션이있을 수 있습니다.

create or replace procedure nested_blocks
is
begin
    some statements
    begin
        some statements
        
    exception
        when exception_one then
            do something
    end;
exception 
    when exception_two then
        do something
end;

중첩 된 블록에서 예외가 발생할 경우 내부 예외 섹션에서 처리해야하지만 내부 예외 섹션에서이 예외를 처리하지 않으면이 예외는 외부 블록의 예외 섹션으로 이동합니다.

내부적으로 정의 된 예외

내부적으로 정의 된 예외에는 이름이 없지만 자체 코드가 있습니다.

그것을 언제 사용합니까?

데이터베이스 조작이 이름이없는 특정 예외를 발생시킬 수있는 경우, 이름을 부여하여 특별히 예외 핸들러를 작성할 수 있습니다. 그렇지 않으면, 당신은 단지 그들을 사용할 수있는 others 예외 핸들러.

통사론

declare 
    my_name_exc exception;
    pragma exception_init(my_name_exc,-37);
begin
    ...
exception 
    when my_name_exc then
        do something
end;

my_name_exc exception; 그것은 예외 이름 선언입니다.

pragma exception_init(my_name_exc,-37); 내부적으로 정의 된 예외의 오류 코드에 이름을 지정하십시오.

우리는 emp 테이블의 기본 키인 emp_id와 dept 테이블의 외래 키를 가지고 있습니다. 하위 레코드가있을 때 emp_id를 제거하려고 시도하면 코드 -2292가 발생하여 예외가 발생합니다.

create or replace procedure remove_employee
is
    emp_exception exception;
    pragma exception_init(emp_exception,-2292);
begin
    delete from emp where emp_id = 3;
exception
    when emp_exception then
        dbms_output.put_line('You can not do that!');
end;
/

Oracle 문서에서는 "사용자가 선언 한 이름을 가진 내부적으로 정의 된 예외는 여전히 사용자 정의 예외가 아니라 내부적으로 정의 된 예외입니다."

미리 정의 된 예외

미리 정의 된 예외는 내부적으로 정의 된 예외이지만 이름은 있습니다. Oracle 데이터베이스는 이러한 유형의 예외를 자동으로 발생시킵니다.

create or replace procedure insert_emp
is
begin
    insert into emp (emp_id, ename) values ('1','Jon');

exception
    when dup_val_on_index then
        dbms_output.put_line('Duplicate value on index!');
end;
/

다음은 예제 코드의 코드 예입니다.

예외 이름 에러 코드
데이터가 없습니다 -1403
ACCESS_INTO_NULL -6530
CASE_NOT_FOUND -6592
ROWTYPE_MISMATCH -6504
TOO_MANY_ROWS -1422
ZERO_DIVIDE -1476

Oracle 웹 사이트에서 예외 이름과 해당 코드의 전체 목록.

사용자 정의 예외

이름에서 알 수 있듯이 사용자가 정의한 예외는 사용자가 만듭니다. 자신의 예외를 만들려면 다음을 수행해야합니다.

  1. 예외 선언
  2. 귀하의 프로그램에서 그것을 높이십시오.
  3. 그를 잡으려면 적절한 예외 처리기를 만듭니다.

근로자의 모든 급여를 갱신하고 싶습니다. 그러나 근로자가없는 경우에는 예외를 제기하십시오.

create or replace procedure update_salary
is
    no_workers exception;
    v_counter number := 0;
begin
    select count(*) into v_counter from emp;
    if v_counter = 0 then
        raise no_workers;
    else
        update emp set salary = 3000;
    end if;

    exception
        when no_workers then
            raise_application_error(-20991,'We don''t have workers!');                
end;
/

raise 한다는 것은 무엇을 의미합니까?

필요가있을 때 자동으로 예외가 데이터베이스 서버에 의해 제기되지만, 당신이 원한다면, 당신은 사용하여 명시 적으로 예외를 발생시킬 수 있습니다 raise .

프로 시저 raise_application_error(error_number,error_message);

  • error_number는 -20000에서 -20999 사이 여야합니다.
  • 오류가 발생할 때 표시 할 error_message 메시지입니다.

커스텀 예외를 정의하고, 그것을 올리고 그것이 어디에서 왔는지를 봅니다.

이것을 설명하기 위해 여기에 3 가지 "잘못된"동작을 갖는 함수가 있습니다.

  • 매개 변수는 완전히 바보입니다. 우리는 사용자 정의 표현식을 사용합니다.
  • 매개 변수에는 오타가 있습니다. Oracle 표준 NO_DATA_FOUND 오류를 사용합니다.
  • 처리되지 않은 다른 케이스

자유롭게 표준에 맞게 조정하십시오.

DECLARE
  this_is_not_acceptable EXCEPTION;
  PRAGMA EXCEPTION_INIT(this_is_not_acceptable, -20077);
  g_err varchar2 (200) := 'to-be-defined';
  w_schema all_tables.OWNER%Type;

  PROCEDURE get_schema( p_table in Varchar2, p_schema out Varchar2)
  Is 
    w_err varchar2 (200) := 'to-be-defined';
  BEGIN
    w_err := 'get_schema-step-1:';
    If (p_table = 'Delivery-Manager-Is-Silly') Then
      raise this_is_not_acceptable;
    end if;
    w_err := 'get_schema-step-2:';
    Select owner Into p_schema 
      From all_tables
     where table_name like(p_table||'%');
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    -- handle Oracle-defined exception
     dbms_output.put_line('[WARN]'||w_err||'This can happen. Check the table name you entered.');
  WHEN this_is_not_acceptable THEN
    -- handle your custom error
     dbms_output.put_line('[WARN]'||w_err||'Please don''t make fun of the delivery manager.');
  When others then
     dbms_output.put_line('[ERR]'||w_err||'unhandled exception:'||sqlerrm);
     raise;    
  END Get_schema;  

BEGIN
  g_err := 'Global; first call:';
  get_schema('Delivery-Manager-Is-Silly', w_schema);
  g_err := 'Global; second call:';
  get_schema('AAA', w_schema);
  g_err := 'Global; third call:';
  get_schema('', w_schema);
  g_err := 'Global; 4th call:';
  get_schema('Can''t reach this point due to previous error.', w_schema);
  
EXCEPTION
  When others then
     dbms_output.put_line('[ERR]'||g_err||'unhandled exception:'||sqlerrm);
  -- you may raise this again to the caller if error log isn't enough.
--  raise;
END;
/

정규 데이터베이스 제공 :

[WARN]get_schema-step-1:Please don't make fun of the delivery manager.
[WARN]get_schema-step-2:This can happen. Check the table name you entered.
[ERR]get_schema-step-2:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows
[ERR]Global; third call:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows

드문 경우를 처리하기 위해 예외가 있음을 기억하십시오. 모든 액세스에서 예외를 발생시킨 응용 프로그램을 보았습니다. 단지 사용자 암호를 요청하고 "연결되지 않았습니다"라고 말하면서 계산 낭비가 너무 많았습니다.

연결 오류 예외 처리

각 표준 Oracle 오류는 오류 번호와 연관됩니다. 코드에서 무엇이 잘못 될 수 있는지 예측하는 것이 중요합니다. 다음은 다른 데이터베이스에 연결하는 경우입니다.

  • -28000 계정이 잠김
  • -28001 암호가 만료되었습니다.
  • -28002 유예 기간
  • -1017 잘못된 사용자 / 암호

다음은 데이터베이스 링크에서 사용되는 사용자의 문제를 테스트하는 방법입니다.

declare
  v_dummy number;
begin
  -- testing db link
  execute immediate 'select COUNT(1) from dba_users@pass.world' into v_dummy ;
  -- if we get here, exception wasn't raised: display COUNT's result
  dbms_output.put_line(v_dummy||' users on PASS db');

EXCEPTION
  -- exception can be referred by their name in the predefined Oracle's list
    When LOGIN_DENIED 
    then  
        dbms_output.put_line('ORA-1017 / USERNAME OR PASSWORD INVALID, TRY AGAIN');
    When Others 
    then 
  -- or referred by their number: stored automatically in reserved variable SQLCODE    
        If  SQLCODE = '-2019'
        Then    
          dbms_output.put_line('ORA-2019 / Invalid db_link name');
        Elsif SQLCODE = '-1035'
        Then
          dbms_output.put_line('ORA-1035 / DATABASE IS ON RESTRICTED SESSION, CONTACT YOUR DBA');        
        Elsif SQLCODE = '-28000'
        Then
          dbms_output.put_line('ORA-28000 / ACCOUNT IS LOCKED. CONTACT YOUR DBA');
        Elsif SQLCODE = '-28001'
        Then
          dbms_output.put_line('ORA-28001 / PASSWORD EXPIRED. CONTACT YOUR DBA FOR CHANGE');
        Elsif SQLCODE  = '-28002'
        Then
          dbms_output.put_line('ORA-28002 / PASSWORD IS EXPIRED, CHANGED IT');
        Else
   -- and if it's not one of the exception you expected
          dbms_output.put_line('Exception not specifically handled');
          dbms_output.put_line('Oracle Said'||SQLCODE||':'||SQLERRM);
        End if;
END;
/


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow