Obsługa wyjątków Oracle PL/SQL (przykłady)

⚡ Inteligentne podsumowanie

Obsługa wyjątków w Oracle Język PL/SQL przechwytuje błędy czasu wykonania, które zatrzymują wykonywanie bloku, umożliwiając silnikowi przekazanie kontroli do sekcji WYJĄTKÓW, w której wstępnie zdefiniowane, zdefiniowane przez użytkownika i inne procedury obsługi reagują, zgłaszają lub bezpiecznie propagują błędy.

  • ⚙️ Błędy w czasie wykonywania: Wyjątek powstaje, gdy silnik PL/SQL napotyka instrukcję, której nie może wykonać, np. podzielenie liczby przez zero.
  • 🧱 Struktura blokowa: Wyjątki obsługuje się w sekcji EXCEPTION za pomocą klauzul WHEN, przy czym klauzula WHEN OTHERS jest zawsze umieszczana na końcu.
  • 📚 Predefiniowane wyjątki: Oracle wymienia typowe błędy, takie jak NO_DATA_FOUND i ZERO_DIVIDE w pakiecie STANDARD, gotowe do bezpośredniego wychwycenia.
  • 🛠️. Wyjątki zdefiniowane przez użytkownika: Programiści deklarują własne zmienne EXCEPTION i jawnie zgłaszają je za pomocą słowa kluczowego RAISE.
  • ⬆️ Propagacja: Nieobsłużony wyjątek jest przekazywany do bloku otaczającego, a RAISE ponownie sygnalizuje go programowi nadrzędnemu.
  • 🤖 Pomoc AI: Narzędzia do kodowania AI tworzą bloki EXCEPTION i sygnalizują nieobsłużone ścieżki błędów podczas przeglądu.

Obsługa wyjątków Oracle PL / SQL

Co to jest obsługa wyjątków w PL/SQL?

Wyjątek występuje, gdy silnik PL/SQL napotka instrukcję, której nie może wykonać z powodu błędu występującego w czasie wykonywania. Błędy te nie są wykrywane w czasie kompilacji i dlatego muszą być obsłużone dopiero w czasie wykonywania.

Na przykład, jeśli silnik PL/SQL otrzyma instrukcję dzielenia liczby przez zero, zgłasza błąd jako wyjątek. Wyjątek jest zgłaszany przez silnik PL/SQL tylko w czasie wykonywania.

Wyjątek uniemożliwia dalsze wykonywanie programu, dlatego aby uniknąć takiej sytuacji, błąd musi zostać przechwycony i obsłużony osobno. Proces ten nazywa się obsługą wyjątków, w której programista obsługuje błąd, który może wystąpić w czasie wykonywania.

Składnia obsługi wyjątków

Wyjątki są obsługiwane na poziomie bloku. Po wystąpieniu wyjątku w bloku sterowanie opuszcza część wykonawczą tego bloku, a wyjątek jest następnie obsługiwany w części bloku przeznaczonej do obsługi wyjątków. Po obsłużeniu wyjątku sterowanie nie może powrócić do sekcji wykonawczej tego samego bloku.

Poniższa ilustracja pokazuje, jak sekcja wykonywania i sekcja obsługi wyjątków znajdują się w jednym bloku PL/SQL:

Struktura bloku PL/SQL z sekcją wykonania i wyjątku

Poniższa składnia wyjaśnia, jak wychwycić i obsłużyć wyjątek.

BEGIN
<execution block>
.
.
EXCEPTION
WHEN <exceptionl_name>
THEN
  <Exception handling code for the “exception 1 _name’' >
WHEN OTHERS
THEN
  <Default exception handling code for all exceptions >
END;

Wyjaśnienie składni:

  • W powyższej składni blok obsługi wyjątków zawiera serię warunków WHEN służących do obsługi wyjątków.
  • Po każdym warunku WHEN następuje nazwa wyjątku, który ma zostać zgłoszony w czasie wykonywania.
  • Gdy w czasie wykonywania wystąpi wyjątek, silnik PL/SQL przeszukuje część obsługującą wyjątki w celu znalezienia tego konkretnego wyjątku, rozpoczynając od pierwszej klauzuli WHEN i przechodząc sekwencyjnie.
  • Jeżeli znajdzie procedurę obsługi zgłoszonego wyjątku, wykonuje konkretny kod procedury obsługi.
  • Jeśli żadna klauzula WHEN nie pasuje do zgłoszonego wyjątku, silnik PL/SQL wykonuje część WHEN OTHERS, jeśli jest obecna. Ta procedura obsługi jest wspólna dla wszystkich wyjątków.
  • Po uruchomieniu modułu obsługi sterowanie opuszcza bieżący blok.
  • Tylko jeden moduł obsługi wyjątków może być uruchomiony dla bloku w czasie wykonywania. Po jego uruchomieniu silnik pomija pozostałe moduły obsługi wyjątków i opuszcza bieżący blok.

Uwaga: Instrukcja WHEN OTHERS powinna zawsze być umieszczana na końcu sekwencji. Żaden handler napisany po instrukcji WHEN OTHERS nigdy się nie uruchamia, ponieważ sterowanie opuszcza blok po wykonaniu instrukcji WHEN OTHERS.

Rodzaje wyjątków

Istnieją dwa rodzaje wyjątków PL / SQL.

  • Predefiniowane wyjątki
  • Wyjątki zdefiniowane przez użytkownika

Predefiniowane wyjątki

Oracle ma predefiniowane kilka typowych wyjątków. Każdy predefiniowany wyjątek ma unikalną nazwę i numer błędu, a wszystkie są zadeklarowane w pakiecie STANDARD w OracleW kodzie można używać tych predefiniowanych nazw wyjątków bezpośrednio do obsługi odpowiadających im błędów. Wiele z nich jest bezpośrednio odwzorowywanych na typowe SQL błędy, które spotykają Cię każdego dnia.

Poniżej przedstawiono kilka wstępnie zdefiniowanych wyjątków:

Wyjątek Błąd Code Powód wyjątku
ACCESS_INTO_NULL ORA-06530 Przypisywanie wartości atrybutom niezainicjowanego obiektu
CASE_NOT_FOUND ORA-06592 Żadna z klauzul WHEN w poleceniu CASE nie jest spełniona i nie określono żadnej klauzuli ELSE
KOLEKCJA_IS_NULL ORA-06531 Korzystanie z metod kolekcji (oprócz EXISTS) lub uzyskiwanie dostępu do atrybutów kolekcji w niezainicjowanej kolekcji
CURSOR_ALREADY_OPEN ORA-06511 Próbuję otworzyć plik kursor który jest już otwarty
DUP_VAL_ON_INDEX ORA-00001 Przechowywanie zduplikowanej wartości w kolumnie bazy danych ograniczonej unikalnym indeksem
INVALID_CURSOR ORA-01001 Nielegalne operacje kursora, takie jak zamykanie nieotwartego kursora
NIEPRAWIDŁOWY NUMER ORA-01722 Konwersja znaku na liczbę nie powiodła się z powodu nieprawidłowego znaku numerycznego
NIE ZNALEZIONO DANYCH ORA-01403 Instrukcja SELECT zawierająca klauzulę INTO nie pobiera żadnych wierszy
WIERSZ_MISMATCH ORA-06504 Typ danych zmiennej kursora jest niezgodny z rzeczywistym typem zwracanym przez kursor
SUBSCRIPT_BEYOND_COUNT ORA-06533 Odwoływanie się do zbioru za pomocą numeru indeksu większego niż rozmiar zbioru
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Odwoływanie się do zbioru za pomocą numeru indeksu spoza dozwolonego zakresu (na przykład -1)
TOO_MANY_ROWS ORA-01422 Instrukcja SELECT z klauzulą ​​INTO zwraca więcej niż jeden wiersz
WARTOŚĆ_BŁĄD ORA-06502 Błąd arytmetyczny lub błąd ograniczenia rozmiaru (na przykład przypisanie wartości większej niż rozmiar zmiennej)
ZERO_DIVIDE ORA-01476 Dzielenie liczby przez zero

Wyjątek zdefiniowany przez użytkownika

Oprócz predefiniowanych wyjątków wymienionych powyżej, programista może tworzyć własne wyjątki i obsługiwać je. Są one tworzone na poziomie podprogramu w części deklaracyjnej i widoczne tylko w obrębie tego podprogramu. Wyjątek zdefiniowany w specyfikacji pakietu jest wyjątkiem publicznym i jest widoczny wszędzie tam, gdzie można uzyskać dostęp do pakietu.

Składnia: Na poziomie podprogramu

DECLARE
<exception_name> EXCEPTION;
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
  • W powyższej składni zmienna „exception_name” jest zdefiniowana jako typ EXCEPTION.
  • Następnie można go używać w taki sam sposób, jak predefiniowanego wyjątku.

Składnia: Na poziomie specyfikacji pakietu

CREATE PACKAGE <package_name>
 IS
<exception_name> EXCEPTION;
.
.
END <package_name>;
  • W powyższej składni zmienna „exception_name” jest zdefiniowana jako typ WYJĄTKU w specyfikacji pakietu .
  • Można go używać w całej bazie danych, wszędzie tam, gdzie można wywołać pakiet „package_name”.

Wyjątek zgłoszenia PL/SQL

Wszystkie predefiniowane wyjątki są zgłaszane domyślnie za każdym razem, gdy wystąpi odpowiadający im błąd. Wyjątki zdefiniowane przez użytkownika muszą być jednak zgłaszane jawnie za pomocą słowa kluczowego RAISE. Wyjątek RAISE można wykorzystać w sposób pokazany poniżej.

Jeśli polecenie RAISE zostanie użyte samodzielnie w procedurze obsługi wyjątku, przekaże ono zgłoszony już wyjątek do bloku nadrzędnego. Można go użyć tylko wewnątrz bloku wyjątku, jak pokazano poniżej.

Poniższy zrzut ekranu przedstawia instrukcję RAISE użytą samodzielnie do ponownego zgłoszenia wyjątku dla bloku otaczającego:

Propagowanie wyjątku do bloku nadrzędnego za pomocą polecenia RAISE

CREATE [ PROCEDURE | FUNCTION ]
 AS
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
             <Handler>
RAISE;
END;

Wyjaśnienie składni:

  • W powyższej składni słowo kluczowe RAISE używane jest wewnątrz bloku obsługi wyjątków.
  • Za każdym razem, gdy program napotka wyjątek „exception_name”, wyjątek jest obsługiwany i kończy działanie normalnie.
  • Słowo kluczowe RAISE w procedurze obsługi wyjątek propaguje następnie ten sam wyjątek do programu nadrzędnego.

Uwaga: Podczas zgłaszania wyjątku w bloku nadrzędnym, zgłaszany wyjątek musi być również widoczny w bloku nadrzędnym; w przeciwnym razie Oracle wyrzuca błąd.

Można również użyć słowa kluczowego RAISE, po którym następuje nazwa wyjątku, aby zgłosić konkretny wyjątek zdefiniowany przez użytkownika lub predefiniowany. Ta forma może być używana zarówno w części wykonawczej, jak i w części obsługi wyjątku.

Poniższy zrzut ekranu przedstawia polecenie RAISE, po którym następuje nazwa wyjątku powodująca wygenerowanie konkretnego wyjątku:

Podnoszenie określonego wyjątku o określonej nazwie za pomocą polecenia RAISE, po którym następuje nazwa wyjątku

CREATE [ PROCEDURE | FUNCTION ]
AS
BEGIN
<Execution block>
RAISE <exception_name>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;

Wyjaśnienie składni:

  • W powyższej składni słowo kluczowe RAISE używane jest w części wykonawczej, po którym następuje wyjątek „exception_name”.
  • Spowoduje to wygenerowanie konkretnego wyjątku w czasie wykonywania, który następnie należy obsłużyć lub zgłosić ponownie.

1 przykład: W tym przykładzie zobaczymy:

  • Jak zadeklarować wyjątek
  • Jak zgłosić zadeklarowany wyjątek
  • Jak propagować to do głównego bloku

Poniższy zrzut ekranu pokazuje cały blok, który deklaruje wyjątek sample_exception, zgłasza go wewnątrz zagnieżdżonego bloku i propaguje do bloku głównego:

Przykład PL/SQL deklarujący i zgłaszający wyjątek zdefiniowany przez użytkownika w zagnieżdżonym bloku

Poniższy zrzut ekranu pokazuje ciąg dalszy tego samego przykładu, w którym blok główny w końcu przechwytuje propagowany wyjątek:

Dane wyjściowe pokazujące wyjątek przechwycony najpierw w bloku zagnieżdżonym, a następnie w bloku głównym

DECLARE
Sample_exception EXCEPTION;
PROCEDURE nested_block
IS
BEGIN
Dbms_output.put_line('Inside nested block');
Dbms_output.put_line('Raising sample_exception from nested block');
RAISE sample_exception;
EXCEPTION
WHEN sample_exception THEN
Dbms_output.put_line ('Exception captured in nested block. Raising to main block');
RAISE;
END;
BEGIN
Dbms_output.put_line('Inside main block');
Dbms_output.put_line('Calling nested block');
Nested_block;
EXCEPTION
WHEN sample_exception THEN
Dbms_output.put_line ('Exception captured in main block');
END;
/

Code Wyjaśnienie:

  • Code linia 2: Deklarowanie zmiennej „sample_exception” jako typu WYJĄTKOWEGO.
  • Code linia 3: Deklarowanie procedury nested_block.
  • Code linia 6: Wydrukowanie komunikatu „Wewnątrz zagnieżdżonego bloku”.
  • Code linia 7: Wyświetlanie polecenia „Podnoszenie sample_exception z zagnieżdżonego bloku”.
  • Code linia 8: Zgłaszanie wyjątku za pomocą „RAISE sample_exception”.
  • Code linia 10: Obsługujący wyjątki sample_exception program w zagnieżdżonym bloku.
  • Code linia 11: Wydrukowanie komunikatu „Wyjątek przechwycony w zagnieżdżonym bloku. Zgłoszenie do bloku głównego”.
  • Code linia 12: Zgłoszenie wyjątku do bloku głównego (rozpowszechnianie go).
  • Code linia 15: Wydruk komunikatu „Wewnątrz bloku głównego”.
  • Code linia 16: Wydrukowanie instrukcji „Wywołanie bloku zagnieżdżonego”.
  • Code linia 17: Wywołanie procedury nested_block.
  • Code linia 19: Procedura obsługi wyjątku dla wyjątku sample_exception w głównym bloku.
  • Code linia 20: Wydruk komunikatu „Wyjątek przechwycony w bloku głównym”.

Ważne punkty, na które należy zwrócić uwagę w wyjątku

  • W funkcji wyjątek zawsze powinien albo zwrócić wartość, albo wywołać kolejny wyjątek; w przeciwnym razie Oracle zgłasza błąd „Funkcja zwrócona bez wartości” w czasie wykonywania.
  • Oświadczenia dotyczące kontroli transakcji można wydać wewnątrz bloku obsługi wyjątków.
  • SQLERRM i SQLCODE to wbudowane funkcje, które zwracają odpowiednio komunikat wyjątku i kod wyjątku.
  • Jeśli wyjątek nie zostanie obsłużony, domyślnie wszystkie aktywne transakcje w danej sesji zostaną wycofane.
  • BŁĄD_APLIKACJI_PODNIESIENIA (- , ) można użyć zamiast RAISE, aby zgłosić błąd z niestandardowym kodem i komunikatem. Kod błędu musi mieścić się w zakresie od -20000 do -20999.

FAQ

PRAGMA EXCEPTION_INIT kojarzy zadeklarowaną przez użytkownika nazwę wyjątku z określonym Oracle Numer błędu. Po powiązaniu możesz przechwycić ten błąd ORA według nazwy w klauzuli WHEN zamiast używać WHEN OTHERS i sprawdzać kod SQLCODE.

SQLCODE zwraca numeryczny kod błędu bieżącego wyjątku, a SQLERRM zwraca jego komunikat tekstowy. Oba są wywoływane w procedurze obsługi wyjątków, najczęściej w bloku WHEN OTHERS, w celu zarejestrowania lub wyświetlenia błędu.

Unikaj wyjątku WHEN OTHERS, który po cichu połyka każdy błąd. Bez rejestrowania SQLCODE i SQLERRM lub ponownego zgłaszania wyjątku RAISE, ukrywa on błędy. Używaj go tylko do rejestrowania, czyszczenia, a następnie propagowania wyjątku.

RAISE_APPLICATION_ERROR akceptuje numer błędu z zakresu od -20000 do -20999 oraz komunikat o długości do 2048 bajtów. Zatrzymuje wykonywanie i zwraca niestandardowy błąd do aplikacji wywołującej, sprawiając, że warunek zdefiniowany przez użytkownika wygląda jak natywny. Oracle Błąd.

Nie w tym samym bloku — gdy sterowanie przejdzie do sekcji WYJĄTEK, blok ten się kończy. Aby kontynuować, należy umieścić ryzykowne polecenie w wewnętrznym bloku BEGIN…EXCEPTION…END; po obsłużeniu błędu blok zewnętrzny kontynuuje wykonywanie.

Błąd to każdy problem w czasie wykonywania lub kompilacji kodu. Wyjątkiem jest mechanizm środowiska wykonawczego PL/SQL, który reprezentuje błąd w czasie wykonywania, przekazując kontrolę do sekcji EXCEPTION, aby program mógł zareagować zamiast nagle się zakończyć.

Tak. Asystenci AI i recenzenci kodu uczenia maszynowego tworzą bloki WYJĄTKÓW, sugerują, które predefiniowane wyjątki należy przechwycić, i sygnalizują ścieżki kodu, w których brakuje procedur obsługi. Deweloper powinien jednak potwierdzić logikę i komunikaty o błędach przed wdrożeniem.

Drugi pilot GitHub Automatycznie uzupełnia klauzule WHEN, wywołania RAISE_APPLICATION_ERROR i pełne bloki EXCEPTION z krótkiego komentarza opisującego intencję. Przyspiesza kodowanie procedur obsługi błędów, chociaż generowane kody błędów i komunikaty wymagają weryfikacji pod kątem poprawności.

Podsumuj ten post następująco: