Informatyka, Bazy danych II
Kierunek Informatyka
Laboratorium 7 - Wyjątki w PL/SQL
Zagadnienia:
· obsługa wyjątków predefiniowanych
· tworzenie własnych wyjątków
· przechwytywanie własnych wyjątków;
Rodzaje wyjątków w PL/SQL:
1. Definiowane wyjątki systemowe – wywoływane w przypadku wystąpienia błędów przetwarzania RDBMS lub błędów języka PL/SQL
EXCEPTION
WHEN CURSOR_ALREADY_OPEN
THEN CLOSE my_cursor;
END;
2. Definiowane wyjątki użytkownika – wywoływane w przypadku wystąpienia błędów aplikacji użytkownika, definiowane w części deklaracyjnej i wywoływane explicite w części ciała bloku PL/SQL
PROCEDURE calc_annual_sales
(company_id_in IN company.company_id%TYPE)
IS
invalid_company_id EXCEPTION;
no_sales_for_company EXCEPTION;
negative_balance EXCEPTION;
duplicate_company BOOLEAN;
BEGIN
... body of executable statements ...
WHEN invalid_company_id THEN ...
WHEN no_sales_for_company THEN ...
3. Niedefiniowane wyjątki systemowe – tylko niewielka część błędów ma swoje zdefiniowane wyjątki systemowe, reszta ma swoje numery błędów i może być obsługiwana zgodnie ze składnią PRAGMA EXCEPTION_INIT
PROCEDURE delete_company (company_id_in IN NUMBER)
/* Deklaracja wyjatku. */
still_have_employees EXCEPTION;
/* Przyporzadkowanie wyjatku do numeru bledu */
PRAGMA EXCEPTION_INIT (still_have_employees, −2292);
DELETE FROM company
WHERE company_id = company_id_in;
/* Wyjatek wywolany w zwiazku z zaleznoscia tabeli od innych */
WHEN still_have_employees
THEN
DBMS_OUTPUT.PUT_LINE (' Please delete employees for company first.');
Można także wykorzystać kody błędów do informacji o wystąpieniu wyjątku: SQLERRM, SQLCODE – użycie klauzuli WHEN OTHERS w części EXCEPTION.
WHEN OTHERS
/* Blok PL/SQL w czesci EXCEPTION */
DECLARE
error_code NUMBER := SQLCODE;
error_msg VARCHAR2 (300) := SQLERRM;
IF error_code = −2292
/* Tabela podrzedna zawiera powiazania. Usun powiazania! */
DELETE FROM employee
/* Teraz usun wlasciwe dane! */
ELSIF error_code = −2291
/* ID nie zostal znaleziony */
DBMS_OUTPUT.PUTLINE
(' Invalid company ID: '||TO_CHAR (company_id_in));
ELSE
/* Uzycie WHEN OTHERS wewnatrz WHEN OTHERS! */
(' Error deleting company, error: '||error_msg);
END IF;
END delete_company;
4. Nienazwane wyjątki użytkownika – wywoływane za pomocą polecenia RAISE_APPLICATION_ERROR, ze zdefiniowaniem kodu błędu i wiadomości o błędzie, wykorzystywane do obsługi błędów komunikacji klient – serwer.
RAISE_APPLICATION_ERROR(error_number, message[, {TRUE | FALSE}]);
error_number z zakresu -20000 .. -20999
message - maks. do 2048 bajtów tekstu
TRUE/FALSE - jeśli false (domyślnie), zastępuje poprzednie wiadomości o błędach w podprogramie
Uwaga!
W przypadku wystąpienia tego wyjątku, zmiany globalne na obiektach bazy danych nie będą wycofane, wymaga to więc użycia explicite polecenia ROLLBACK.
Wyjątki w PL/SQL – facts & tips
1. Sekcja EXCEPTION w bloku PL/SQL obsługuje tylko wyjątki wywołane w tym bloku.
2. Wyjątek wywołany w części deklaracyjnej bloku PL/SQL jest obsługiwany w części EXCEPTION bloku wyższego, jeśli istnieje ta część.
3. Wyjątki wywołane w sekcji EXCEPTION są obsługiwane w części EXCEPTION bloku wyższego, jeśli istnieje ta część.
4. Jeśli chcemy przechwycić wszelkie wyjątki, należy korzystać z klauzuli WHEN_OTHERS.
5. W wypadku wystąpienia wyjątku, obsługa programu przechodzi do części EXCEPTION. Nie ma możliwości powrotu do części wykonywalnej tego bloku, po wywołaniu wyjątku.
6. Po przechwyceniu wyjątku, w następnej kolejności wykonywana jest sekcja BODY wyższego bloku PL/SQL, o ile istnieje ta część.
7. W celu przechwycenia specyficznych wyjątków, należy je definiować i nazywać.
Ponadto
Ponowne definiowanie wyjątków predefiniowanych
WHEN invalid_number OR STANDARD.INVALID_NUMBER
THEN ...
Jawne wywołanie wyjątków predefiniowanych
Podobnie jak wywołuje się wyjątek definiowany przez użytkownika, można również jawnie wywołać wyjątek predefiniowany, który z reguły wywołuje sam system ORACLE.
...
IF acct_type NOT IN (1, 2, 3) THEN
RAISE INVALID_NUMBER;
Wyjątki wywoływane w części deklaracyjnej
zmienna varchar2(2) := 'ZA DUZO TEKSTU W TEJ ZMIENNEJ';
WHEN VALUE_ERROR THEN
Wyjątki wywoływane w części EXCEPTION
WHEN VALUE_ERROR THEN RAISE NO_DATA_FOUND;
WHEN NO_DATA_FOUND THEN ...
Wywołanie wyjątku w części wyjątku powoduje przerwanie wykonywania części EXCEPTION w danym bloku PL/SQL, przejście do części EXCEPTION bloku wyższego i obsługę wywołanego wyjątku.
Przypomnienie – systemowe wyjątki predefiniowane:
DUP_VAL_ON_INDEX: wywoływany, gdy na skutek wykonania polecenia insert lub update różne rekordy relacji posiadają tę samą wartość atrybutu zadeklarowanego jako unikalny;
INVALID_CURSOR: wywoływany w wyniku wykonania operacji na kursorze, która jest niepoprawna w pewnym kontekście, np. zamknięcie nieotwartego kursora;
INVALID_NUMBER: wywoływany, gdy nie jest możliwa konwersja łańcucha znaków do postaci liczby, ponieważ łańcuch zawiera niedopuszczalne wartości;
LOGIN_DENIED: wywoływany w przypadku podania niepoprawnych parametrów w poleceniu rozpoczęcia sesji - login, np. nazwy użytkownika lub hasła;
NO_DATA_FOUND: wywoływany, gdy polecenie select nie wyznacza żadnej krotki;
NOT_LOGGED_ON: wywoływany w wyniku próby wykonania funkcji Oracle przez użytkownika nie dołączonego do systemu;
PROGRAM_ERROR: wywoływany w wyniku błędnego działania programu PL/SQL;
STORAGE_ERROR: wywoływany w wyniku błędu pamięci lub braku miejsca w pamięci;
TIMEOUT_ON_RESOURCE: wywoływany po upłynięciu czasu oczekiwania na przydzielenie zasobu;
TOO_MANY_ROWS: wywoływany, gdy jest wymagana dokładnie jedna krotka, a polecenie select wyznacza większą liczbę krotek;
VALUE_ERROR: wywoływany w przypadku błędu konwersji typów danych (np. próby wpisania daty do numerycznego pola krotki) lub, gdy aktualna długość danej przekracza wcześniej zadeklarowaną długość (np. próba wpisania do pola krotki o długości 3 znaków danej o długości 5 znaków);
ZERO_DIVIDE: wywoływany w wyniku próby dzielenia przez 0;
OTHERS: wywoływany w dla wszystkich wyjątków, które nie zostały wyspecyfikowane w bloku exception; definiowany jako ostatni w bloku exception.
Kody błędów w PL/SQL:
ACCESS_INTO_NULL ORA-06530 -6530
CASE_NOT_FOUND ORA-06592 -6592
COLLECTION_IS_NULL ORA-06531 -6531
CURSOR_ALREADY_OPEN ORA-06511 -6511
DUP_VAL_ON_INDEX ORA-00001 -1
INVALID_CURSOR ORA-01001 -1001
INVALID_NUMBER ORA-01722 -1722
LOGIN_DENIED ORA-01017 -1017
NO_DATA_FOUND ORA-01403 +100
NOT_LOGGED_ON ORA-01012 -1012
PROGRAM_ERROR ORA-06501 -6501
ROWTYPE_MISMATCH ORA-06504 -6504
SELF_IS_NULL ORA-30625 -30625
STORAGE_ERROR ORA-06500 -6500
SUBSCRIPT_BEYOND_COUNT ORA-06533 -6533
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 -6532
SYS_INVALID_ROWID ORA-01410 -1410
TIMEOUT_ON_RESOURCE ORA-00051 -51
TOO_MANY_ROWS ORA-01422 -1422
VALUE_ERROR ORA-06502 -6502
ZERO_DIVIDE ORA-01476 -1476
Zadania do samodzielnego wykonania:
tryniti