수색…
소개
오라클은 다양한 예외를 만들어냅니다. 불분명 한 메시지로 코드를 중지하는 것이 얼마나 지루한 지 놀라실 수 있습니다. PL / SQL 코드의 기능을 쉽게 개선하려면 가장 낮은 레벨에서 예외를 처리해야합니다. 카펫 아래에 예외를 숨기지 마십시오. 코드를 유지하고 다른 사람이 유지할 수 없으면 예외가 아닙니다.
예외 처리
예외 란 무엇입니까?
PL / SQL의 예외는 프로그램 실행 중에 작성되는 오류입니다.
예외 유형은 세 가지입니다.
- 내부적으로 정의 된 예외
- 미리 정의 된 예외
- 사용자 정의 예외
예외 처리 란 무엇입니까?
예외 처리는 예를 들어 코딩 실수, 하드웨어 오류로 인해 런타임 오류가 발생하더라도 프로그램을 계속 실행하는 가능성이 있습니다. 갑자기 종료되는 것을 피합니다.
통사론
예외 섹션의 일반 구문 :
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 웹 사이트에서 예외 이름과 해당 코드의 전체 목록.
사용자 정의 예외
이름에서 알 수 있듯이 사용자가 정의한 예외는 사용자가 만듭니다. 자신의 예외를 만들려면 다음을 수행해야합니다.
- 예외 선언
- 귀하의 프로그램에서 그것을 높이십시오.
- 그를 잡으려면 적절한 예외 처리기를 만듭니다.
예
근로자의 모든 급여를 갱신하고 싶습니다. 그러나 근로자가없는 경우에는 예외를 제기하십시오.
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;
/