Oracle PL/SQL Tutorial/PL SQL Programming/User Defined Exceptions

Материал из SQL эксперт
Перейти к: навигация, поиск

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>