Zoeken…


Invoering

Oracle produceert verschillende uitzonderingen. Het zal je misschien verbazen hoe vervelend het kan zijn om je code te laten stoppen met een onduidelijk bericht. Om het vermogen van uw PL / SQL-code om gemakkelijk te repareren te verbeteren, is het noodzakelijk om uitzonderingen op het laagste niveau af te handelen. Verberg nooit een uitzondering "onder het tapijt", tenzij u hier bent om uw stukje code alleen voor u te bewaren en voor niemand anders te onderhouden.

De vooraf gedefinieerde fouten .

Uitzondering afhandeling

  1. Wat is een uitzondering?

    Uitzondering in PL / SQL is een fout die is gemaakt tijdens het uitvoeren van een programma.

    We hebben drie soorten uitzonderingen:

    • Intern gedefinieerde uitzonderingen
    • Vooraf gedefinieerde uitzonderingen
    • Door de gebruiker gedefinieerde uitzonderingen
  1. Wat is een uitzonderingsbehandeling?

    Uitzonderingsafhandeling is een mogelijkheid om ons programma draaiende te houden, zelfs als een runtime-fout optreedt als gevolg van bijvoorbeeld coderingsfouten, hardwarefouten. We voorkomen dat het abrupt wordt afgesloten.

Syntaxis

De algemene syntaxis voor uitzonderingssectie:

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;

Een uitzonderingssectie moet zich aan het einde van het PL / SQL-blok bevinden. PL / SQL geeft ons de mogelijkheid om blokken te nesten, dan kan elk blok zijn eigen uitzonderingssectie hebben, bijvoorbeeld:

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;

Als de uitzondering in het geneste blok wordt opgeworpen, moet dit in de interne uitzonderingssectie worden verwerkt, maar als de interne uitzonderingssectie deze uitzondering niet verwerkt, gaat deze uitzondering naar de uitzonderingssectie van het externe blok.

Intern gedefinieerde uitzonderingen

Een intern gedefinieerde uitzondering heeft geen naam, maar heeft zijn eigen code.

Wanneer gebruiken?

Als u weet dat uw databasebewerking specifieke uitzonderingen kan veroorzaken die geen namen hebben, dan kunt u ze namen geven zodat u uitzonderingshandlers specifiek voor hen kunt schrijven. Anders kunt u ze alleen gebruiken met others uitzonderingshandlers.

Syntaxis

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; dat is de uitzonderingsnaamverklaring.

pragma exception_init(my_name_exc,-37); wijs een naam toe aan de foutcode van een intern gedefinieerde uitzondering.

Voorbeeld

We hebben een emp_id die een primaire sleutel is in de emp-tabel en een externe sleutel in dept-tabel. Als we proberen emp_id te verwijderen wanneer het onderliggende records heeft, wordt er een uitzondering gegenereerd met code -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-documentatie zegt: "Een intern gedefinieerde uitzondering met een door de gebruiker opgegeven naam is nog steeds een intern gedefinieerde uitzondering, geen door de gebruiker gedefinieerde uitzondering."

Vooraf gedefinieerde uitzonderingen

Vooraf gedefinieerde uitzonderingen zijn intern gedefinieerde uitzonderingen, maar ze hebben namen. Oracle-database verhoogt dit soort uitzonderingen automatisch.

Voorbeeld

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;
/

Hieronder staan voorbeelden van uitzonderingsnamen met hun codes:

Naam uitzondering Foutcode
GEEN DATA GEVONDEN -1403
ACCESS_INTO_NULL -6530
CASE_NOT_FOUND -6592
ROWTYPE_MISMATCH -6504
TOO_MANY_ROWS -1422
ZERO_DIVIDE -1476

Volledige lijst met uitzonderingsnamen en hun codes op de Oracle-website.

Door de gebruiker gedefinieerde uitzonderingen

Zoals de naam suggereert, worden door de gebruiker gedefinieerde uitzonderingen gemaakt door gebruikers. Als u uw eigen uitzondering wilt maken, moet u:

  1. Verklaar de uitzondering
  2. Haal het uit uw programma
  3. Maak een geschikte uitzonderingshandler om hem te vangen.

Voorbeeld

Ik wil alle salarissen van werknemers bijwerken. Maar als er geen werknemers zijn, maak dan een uitzondering.

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;
/

Wat betekent raise ?

Uitzonderingen worden automatisch gegenereerd door de databaseserver wanneer dat nodig is, maar als je wilt, kun je elke uitzondering expliciet raise met behulp van raise .

Procedure raise_application_error(error_number,error_message);

  • foutnummer moet tussen -20000 en -20999 liggen
  • error_message bericht om weer te geven wanneer er een fout optreedt.

Definieer aangepaste uitzondering, verhoog het en kijk waar het vandaan komt

Om dit te illustreren, hier is een functie die 3 verschillende "verkeerde" gedragingen heeft

  • de parameter is helemaal dom: we gebruiken een door de gebruiker gedefinieerde uitdrukking
  • de parameter heeft een typefout: we gebruiken de standaardfout NO_DATA_FOUND Oracle
  • een andere, maar niet afgehandelde zaak

Pas het aan uw normen aan:

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;
/

Geven op een regelmatige database:

[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

Vergeet niet dat uitzonderingen hier zijn om zeldzame gevallen te behandelen. Ik zag applicaties die bij elke toegang een uitzondering opriepen, gewoon om het gebruikerswachtwoord te vragen en zeiden "niet verbonden" ... zoveel computerverspilling.

Behandeling van uitzonderingen op verbindingsfouten

Elke standaard Oracle-fout is gekoppeld aan een foutnummer. Het is belangrijk om te anticiperen op wat er mis kan gaan in uw code. Hier voor een verbinding met een andere database kan dit zijn:

  • -28000 account is vergrendeld
  • -28001 wachtwoord verlopen
  • -28002 respijtperiode
  • -1017 verkeerde gebruiker / wachtwoord

Hier is een manier om te testen wat er misgaat met de gebruiker die door de databasekoppeling wordt gebruikt:

declare
  v_dummy number;
begin
  -- testing db link
  execute immediate 'select COUNT(1) from [email protected]' 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow