2014-12-19 15 views
21

To jest pytanie, które często mnie pyta. Ponieważ nie mogłem znaleźć żadnego dokładnego duplikatu na stackoverflow, pomyślałem, że zamieściłem to jako odniesienie.Obsługa wyjątków PL/SQL: nic nie rób (zignoruj ​​wyjątek)

Pytanie: W języku PL/SQL, wiem, jak wychwycić wyjątki i wykonać kod, gdy są one przechwytywane, i jak je propagować do bloku wywołującego. Na przykład w poniższej procedurze, wyjątek NO_DATA_FOUND jest obsługiwany bezpośrednio, podczas gdy wszystkie inne wyjątki są podniesione do bloku wywołującego:

CREATE OR REPLACE PROCEDURE MY_PROCEDURE() 
IS 
BEGIN 
    do_stuff(); 

EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
     -- Do something 
     handle_exception(); 

    WHEN OTHERS THEN 
     -- Propagate exception 
     RAISE; 
END; 

Ale co polecenia należy użyć do ignorowania jednego lub wszystkich podniesionych wyjątków i powrócić wykonanie kontrolować z powrotem do bloku wywołującego?

Odpowiedz

37

Podczas gdy zgadzam się, że 99% przypadków to zła praktyka, aby po cichu zignorować wyjątki, nie rejestrując ich gdzieś, istnieją szczególne sytuacje, w których jest to całkowicie dopuszczalne.

W takich sytuacjach, NULL jest twoim przyjacielem:

[...] 
EXCEPTION 

    WHEN OTHERS THEN 
     NULL; 
END; 

dwie typowe sytuacje, w których ignorowanie wyjątki mogą być pożądane są:

1) Kod zawiera oświadczenie, które znasz nie powiedzie się sporadycznie i ty nie chcę, aby ten fakt przerywał twój przepływ programu. W tym przypadku należy załączyć Ci oświadczenie w zagnieżdżonego bloku, jak w poniższym przykładzie:

CREATE OR REPLACE PROCEDURE MY_PROCEDURE() 
IS 
    l_empoyee_name EMPLOYEES.EMPLOYEE_NAME%TYPE; 
BEGIN 
    -- Catch potential NO_DATA_FOUND exception and continue 
    BEGIN 
     SELECT EMPLOYEE_NAME 
     INTO l_empoyee_name 
     FROM EMPLOYEES 
     WHERE EMPLOYEE_ID = 12345; 
    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
      NULL; 
     WHEN OTHERS THEN 
      RAISE; 
    END; 

    do_stuff(); 

EXCEPTION 

    WHEN OTHERS THEN 
     -- Propagate exception 
     RAISE; 
END; 

Zauważ, że PL/SQL na ogół nie pozwalają na On Error Resume Next rodzaj obsługi wyjątków znany z Visual Podstawowy, w którym wszystkie wyjątki są ignorowane, a program nadal działa, jak gdyby nic się nie stało (patrz On error resume next type of error handling in PL/SQL oracle). Należy jawnie dołączyć potencjalnie niedziałające instrukcje w zagnieżdżonym bloku.

2) Twoja procedura jest tak nieważna, że ​​zignorowanie wszystkich wyjątków, które rzuca, nie wpłynie na logikę głównego programu. (Jest to jednak bardzo rzadko sprawa i często może prowadzić do koszmaru debugowania w dłuższej perspektywie)

BEGIN 

    do_stuff(); 

EXCEPTION 

    WHEN OTHERS THEN 
     -- Ignore all exceptions and return control to calling block 
     NULL; 
END; 
+3

Być może warto dodać, że "gdy inne niż zero" jest uważane za kiepską praktykę, z wyjątkiem bardzo specyficznych bloków, w których naprawdę nie obchodzi cię, czy krok działał, czy nie, oraz "kiedy inni następnie podnoszą" po prostu wyrzuca informacje o błędzie . –

1

Inny scenariusz, gdy ma sensu cicho zignorować wyjątek: Po wywołaniu skryptu, który jest oczekiwany aby utworzyć obiekt, jeśli nie istnieje, i nie masz składni create-or-replace dla tego obiektu. Obiekty PLSQL mają składnię create-or-replace, ale tabele i indeksy nie. Następnie możemy umieścić takie skrypty w bloku i zignorować podniesiony wyjątek.