Szukaj…


Wprowadzenie

Oracle tworzy szereg wyjątków. Możesz być zaskoczony, jak żmudne może być zatrzymanie kodu z niejasną wiadomością. Aby poprawić zdolność kodu PL / SQL do łatwej naprawy, należy obsługiwać wyjątki na najniższym poziomie. Nigdy nie ukrywaj wyjątku „pod dywan”, chyba że jesteś tutaj, aby zachować swój kod tylko dla siebie i dla nikogo innego.

Predefiniowane błędy .

Obsługa wyjątków błędów połączenia

Każdy standardowy błąd Oracle jest powiązany z numerem błędu. Ważne jest, aby przewidzieć, co może pójść nie tak w twoim kodzie. Tutaj w przypadku połączenia z inną bazą danych może to być:

  • -28000 konto jest zablokowane
  • -28001 hasło wygasło
  • -28002 okres karencji
  • -1017 zły użytkownik / hasło

Oto sposób przetestowania, co poszło nie tak z użytkownikiem używanym przez łącze do bazy danych:

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

Zdefiniuj niestandardowy wyjątek, podnieś go i zobacz, skąd pochodzi

Aby to zilustrować, oto funkcja, która ma 3 różne „złe” zachowania

  • parametr jest całkowicie głupi: używamy wyrażenia zdefiniowanego przez użytkownika
  • parametr ma literówkę: używamy standardowego błędu NO_DATA_FOUND Oracle
  • kolejna, ale nieobsługiwana sprawa

Dostosuj go do swoich standardów:

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

Podanie w regularnej bazie danych:

[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

Pamiętaj, że wyjątek dotyczy rzadkich przypadków. Widziałem aplikacje, które zgłaszały wyjątek przy każdym dostępie, tylko po to, aby prosić o hasło użytkownika, mówiąc „brak połączenia” ... tyle marnotrawstwa obliczeniowego.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow