Oracle PL/SQL Tutorial/PL SQL Programming/User Defined Exceptions
Содержание
Adding User-Defined Exceptions
Before raising a user-defined exception, you must first declare the exception.
The syntax is
<exception_name> exception;
A User-Defined Exception
SQL>
SQL>
SQL> -- create demo table
SQL> create table Employee(
2 ID VARCHAR2(4 BYTE) NOT NULL,
3 First_Name VARCHAR2(10 BYTE),
4 Last_Name VARCHAR2(10 BYTE),
5 Start_Date DATE,
6 End_Date DATE,
7 Salary Number(8,2),
8 City VARCHAR2(10 BYTE),
9 Description VARCHAR2(15 BYTE)
10 )
11 /
Table created.
SQL>
SQL> -- prepare data
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values ("01","Jason", "Martin", to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto", "Programmer")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("02","Alison", "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("03","James", "Smith", to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("04","Celia", "Rice", to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("05","Robert", "Black", to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("06","Linda", "Green", to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York", "Tester")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("07","David", "Larry", to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York", "Manager")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("08","James", "Cat", to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
3 /
1 row created.
SQL>
SQL>
SQL>
SQL> -- display data in the table
SQL> select * from Employee
2 /
ID FIRST_NAME LAST_NAME START_DAT END_DATE SALARY CITY DESCRIPTION
---- -------------------- -------------------- --------- --------- ---------- ---------- ---------------
01 Jason Martin 25-JUL-96 25-JUL-06 1234.56 Toronto Programmer
02 Alison Mathews 21-MAR-76 21-FEB-86 6661.78 Vancouver Tester
03 James Smith 12-DEC-78 15-MAR-90 6544.78 Vancouver Tester
04 Celia Rice 24-OCT-82 21-APR-99 2344.78 Vancouver Manager
05 Robert Black 15-JAN-84 08-AUG-98 2334.78 Vancouver Tester
06 Linda Green 30-JUL-87 04-JAN-96 4322.78 New York Tester
07 David Larry 31-DEC-90 12-FEB-98 7897.78 New York Manager
08 James Cat 17-SEP-96 15-APR-02 1232.78 Vancouver Tester
8 rows selected.
SQL>
SQL>
SQL>
SQL> create or replace function f_ValidateSalary(i_empNo VARCHAR, i_new_Sal NUMBER)
2 return VARCHAR2
3 is
4 v_current_Sal NUMBER;
5 e_increaseTooLarge exception;
6 begin
7 select salary into v_current_Sal
8 from employee
9 where id=i_empNo;
10
11 if (i_new_Sal/v_current_Sal) * 100 > 300 then
12 raise e_increaseTooLarge;
13 end if;
14
15 return "Y";
16 exception
17 when e_increaseTooLarge then
18 DBMS_OUTPUT.put_line("increaseTooLarge");
19 return "N";
20 end;
21 /
Function created.
SQL>
SQL>
SQL> select f_ValidateSalary("01", 10000) from dual;
F_VALIDATESALARY("01",10000)
--------------------------------------------------------------------------
N
increaseTooLarge
SQL>
SQL>
SQL> -- clean the table
SQL> drop table Employee
2 /
Table dropped.
SQL>
SQL>
Including error messages in user-defined exceptions
SQL>
SQL>
SQL>
SQL> -- create demo table
SQL> create table Employee(
2 ID VARCHAR2(4 BYTE) NOT NULL,
3 First_Name VARCHAR2(10 BYTE),
4 Last_Name VARCHAR2(10 BYTE),
5 Start_Date DATE,
6 End_Date DATE,
7 Salary Number(8,2),
8 City VARCHAR2(10 BYTE),
9 Description VARCHAR2(15 BYTE)
10 )
11 /
Table created.
SQL>
SQL> -- prepare data
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values ("01","Jason", "Martin", to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto", "Programmer")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("02","Alison", "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("03","James", "Smith", to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("04","Celia", "Rice", to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("05","Robert", "Black", to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("06","Linda", "Green", to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York", "Tester")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("07","David", "Larry", to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York", "Manager")
3 /
1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
2 values("08","James", "Cat", to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
3 /
1 row created.
SQL>
SQL>
SQL>
SQL> -- display data in the table
SQL> select * from Employee
2 /
ID FIRST_NAME LAST_NAME START_DAT END_DATE SALARY CITY DESCRIPTION
---- -------------------- -------------------- --------- --------- ---------- ---------- ---------------
01 Jason Martin 25-JUL-96 25-JUL-06 1234.56 Toronto Programmer
02 Alison Mathews 21-MAR-76 21-FEB-86 6661.78 Vancouver Tester
03 James Smith 12-DEC-78 15-MAR-90 6544.78 Vancouver Tester
04 Celia Rice 24-OCT-82 21-APR-99 2344.78 Vancouver Manager
05 Robert Black 15-JAN-84 08-AUG-98 2334.78 Vancouver Tester
06 Linda Green 30-JUL-87 04-JAN-96 4322.78 New York Tester
07 David Larry 31-DEC-90 12-FEB-98 7897.78 New York Manager
08 James Cat 17-SEP-96 15-APR-02 1232.78 Vancouver Tester
8 rows selected.
SQL>
SQL>
SQL>
SQL> create or replace procedure p_validateSalary(i_empNo VARCHAR, i_new_sal NUMBER)
2 is
3 v_current_sal Number(8,2);
4 e_increaseTooLarge EXCEPTION;
5 pragma exception_init (e_increaseTooLarge, -20999);
6 begin
7 select salary into v_current_sal
8 from employee
9 where id=i_empNo;
10 if (i_new_sal/v_current_sal)*100>300
11 then
12 raise_application_error (-20999, "Cannot triple salary for employee #"||i_empNo);
13 end if;
14 exception
15 when e_increaseTooLarge then
16 DBMS_OUTPUT.put_line("increaseTooLarge");
17 raise;
18 end;
19 /
Procedure created.
SQL>
SQL> call p_validateSalary("01", 10000);
increaseTooLarge
call p_validateSalary("01", 10000)
*
ERROR at line 1:
ORA-20999: Cannot triple salary for employee #01
ORA-06512: at "sqle.P_VALIDATESALARY", line 17
SQL>
SQL> -- clean the table
SQL> drop table Employee
2 /
Table dropped.
SQL>
SQL>
Propagation of Exceptions between Program Units
SQL>
SQL> create or replace function f_makeAddress (i_address VARCHAR2,i_city VARCHAR2,i_state VARCHAR2,i_zip VARCHAR2)
2 return VARCHAR2
3 is
4 e_badZip EXCEPTION;
5 pragma EXCEPTION_init(e_badZip,-20998);
6 v_out VARCHAR2(256);
7 begin
8 p_validateZip (i_zip);
9 v_out:= i_address||", "||i_city ||", "||i_state ||", "||i_zip;
10 return v_out;
11 exception
12 when e_badZip then
13 return i_zip || ": Invalid zip code.";
14 end;
15 /
Function created.
SQL>
SQL> create or replace procedure p_validateZip (i_zipCode VARCHAR2)
2 is
3 e_tooShort EXCEPTION;
4 e_tooLong EXCEPTION;
5 e_badZip EXCEPTION;
6 pragma exception_init(e_badZip, -20998);
7 v_tempZip NUMBER;
8 Begin
9 if length(i_zipCode)< 5 then
10 Raise e_tooShort;
11 elsif length(i_zipCode)> 6 then
12 Raise e_tooLong;
13 end if;
14
15 v_tempZip := to_number(i_zipCode);
16
17 exception
18 when e_tooLong then
19 DBMS_OUTPUT.put_line("long zip");
20 raise e_badZip;
21 when e_tooShort then
22 DBMS_OUTPUT.put_line("short zip");
23 -- raise e_badZip SHOULD be here
24 when value_error then
25 DBMS_OUTPUT.put_line("non-numeric zip");
26 raise; -- re-raising the same exception
27 end;
28 /
Procedure created.
SQL> --Scenario 1: No rule violations
SQL>
SQL> declare
2 v_out VARCHAR2(2000);
3 begin
4 v_out:=f_makeAddress("AA","City","CA","94061");
5 DBMS_OUTPUT.put_line(v_out);
6 end;
7 /
AA, City, CA, 94061
PL/SQL procedure successfully completed.
SQL>
SQL>
SQL> --Scenario 2: Short ZIP code
SQL>
SQL>
SQL> declare
2 v_out VARCHAR2(2000);
3 begin
4 v_out:=f_makeAddress("A","City", "CA","940");
5 DBMS_OUTPUT.put_line(v_out);
6 end;
7 /
short zip
A, City, CA, 940
PL/SQL procedure successfully completed.
SQL> --Scenario 3: Non-numeric ZIP code
SQL>
SQL> declare
2 v_out VARCHAR2(2000);
3 begin
4 v_out:=f_makeAddress("A","City" , "CA","9406A");
5 DBMS_OUTPUT.put_line(v_out);
6 end;
7 /
non-numeric zip
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "sqle.P_VALIDATEZIP", line 26
ORA-06512: at "sqle.F_MAKEADDRESS", line 8
ORA-06512: at line 4
SQL> -- Long ZIP code
SQL>
SQL> declare
2 v_out VARCHAR2(2000);
3 begin
4 v_out:=f_makeAddress("A","City","CA","940612345");
5 DBMS_OUTPUT.put_line(v_out);
6 end;
7 /
long zip
940612345: Invalid zip code.
PL/SQL procedure successfully completed.
SQL>