BAZY DANYCH II WYKŁAD 6 Plan wykładu Co to są wyjątki? Co to
Transkrypt
BAZY DANYCH II WYKŁAD 6 Plan wykładu Co to są wyjątki? Co to
2010-12-02 Plan wykładu Wyjątki Deklarowanie, zgłaszanie, obsługa wyjątków Przekazywanie wyjątków Funkcje Procedury BAZY DANYCH II WYKŁAD 6 dr inż. Agnieszka Bołtuć Co to są wyjątki? Wyjątki są zaprojektowane w celu obsługi błędów, Gdy nastąpi błąd zgłaszany jest wyjątek, Wyjątki obsługują jeden rodzaj błędów tzw. błędy czasu wykonania zgłaszane przez silnik wykonawczy PL/SQL, Co to są wyjątki? DECLARE v_last_name employees.last_name%type; BEGIN SELECT last_name INTO v_last_name FROM employees WHERE salary>3000; DBMS_OUTPUT.PUT_LINE(v_last_name); END; 1 2010-12-02 Deklarowanie wyjątków Deklaracja wyjątków – sekcja deklaracji, Zgłaszanie wyjątków – sekcja wykonawcza, Obsługiwanie wyjątków – sekcja wyjątków, Wyróżniamy dwa typy wyjątków: Wyjątki zdefiniowane przez użytkownika DECLARE identyfikator EXCEPTION; Zdefiniowane przez użytkownika, Wbudowane. Wyjątki wbudowane Wyjątki wbudowane Odpowiadają najczęściej spotykanym błędom, Ich identyfikatory zdefiniowane są w pakiecie STANDARD, Są dostępne w programach bez konieczności deklaracji, Wyjątki zdefiniowane przez użytkownika deklarowane są w sekcji deklaracyjnej, Są to błędy określone przez programistę, nie muszą wynikać z błędu Oracle, ORA-0001 – DUP_VAL_ON_INDEX – naruszenie ograniczenia niepowtarzalności, ORA-06511 – CURSOR_ALREADY_OPEN – próba otwarcia otwartego kursora, ORA-01001 – INVALID_CURSOR – niedozwolona operacja na kursorze, ORA-1403 – NO_DATA_FOUND – brak żądanych danych, ORA-1422 – TOO_MANY_ROWS – SELECT INTO zwrócił więcej niż jeden wiersz, 2 2010-12-02 Wyjątki wbudowane ORA-6531 – COLLECTION_IS_NULL – próba zastosowania metod na pustej kolekcji, ORA-1476 – ZERO_DIVIDE – dzielenie przez zero, ORA-6500 – STORAGE_ERROR – w PL/SQL zabrakło pamięci, ORA-1012 – NOT_LOGGED_ON – błąd połączenia z Oracle, etc. Obsługa wyjątków Po zgłoszeniu wyjątku (RAISE lub automatycznie) sterowanie przekazywane jest do sekcji wyjątków, Sekcja ta zawiera bloki obsługi wyjątków, Jest to kod wykonywany w razie wystąpienia błędu powiązanego z danym wyjątkiem i zgłoszenia tego wyjątku, Zgłaszanie wyjątków Wyjątki zdefiniowane przez użytkownika muszą być zgłoszone jawnie, RAISE identyfikator; Wyjątki wbudowane zgłaszane są automatycznie w momencie wystąpienia powiązanego błędu, mogą być też zgłoszone jawnie przez RAISE, Po zgłoszeniu wyjątku sterowanie jest przekazywane do sekcji wyjątków lub bloku zewnętrznego, Sekcja wyjątków DECLARE BEGIN … [EXCEPTION ...] END; EXCEPTION WHEN nazwa_wyjątku THEN instrukcje; WHEN nazwa_wyjątku THEN instrukcje; [WHEN OTHERS THEN instrukcje;] 3 2010-12-02 Obsługa wyjątków – przykład 1 Obsługa wyjątków – przykład 2 DECLARE v_last_name employees.last_name%type; BEGIN SELECT last_name INTO v_last_name FROM employees WHERE salary>3000; DBMS_OUTPUT.PUT_LINE(v_last_name); EXCEPTION WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE(’Select zwrócił więcej niż jeden wiersz. Użyj kursora’); END; DECLARE e_powtorka EXCEPTION; v_pensja NUMBER; BEGIN SELECT salary INTO v_pensja FROM employees WHERE employee_id=100; IF (v_pensja<500) THEN RAISE e_powtorka; END IF; EXCEPTION WHEN e_powtorka THEN DBMS_OUTPUT.PUT_LINE(’Błąd użytkownika’); END; Obsługa wyjątków Obsługa wyjątków Wyjątek jest obsługiwany przez najwyżej jeden blok obsługi wyjątków w sekcji wyjątków, Sekcja wyjątków może zawierać bloki obsługi wyjątków nie zgłaszanych w sekcji wykonawczej, Nie każdy zgłoszony wyjątek musi mieć blok obsługi, Dopuszczalna konstrukcja EXCEPTION WHEN NO_DATA_FOUND OR TOO_MANY_ROWS THEN …. END; Niedopuszczalna konstrukcja EXCEPTION WHEN NO_DATA_FOUND AND TOO_MANY_ROWS THEN …. END; 4 2010-12-02 Blok OTHERS Blok wywoływany dla wszystkich zgłoszonych wyjątków nie obsłużonych przez żadną inną klauzulę WHEN, Powinien być to ostatni blok, Przechwytuje wyjątki wbudowane oraz zdefiniowane przez użytkownika, Dobrze jest zamieścić taki blok obsługi w najbardziej zewnętrznym bloku. Analiza błędów PL/SQL udostępnia dwie funkcje mające na celu przekazanie informacji o błędach: SQLCODE Zwraca kod błędu w przypadku wyjątków wbudowanych, zaś w przypadku zdefiniowanych przez użytkownika – 1, SQLERRM Zwraca komunikat tekstowy związany z danym błędem, w przypadku wyjątków zdefiniowanych przez użytkownika komunikat „User-defined Exception” Blok OTHERS DECLARE e_powtorka EXCEPTION; v_pensja NUMBER; BEGIN SELECT salary INTO v_pensja FROM employees WHERE employee_id=100; IF (v_pensja<500) THEN RAISE e_powtorka; END IF; EXCEPTION WHEN e_powtorka THEN DBMS_OUTPUT.PUT_LINE(’Błąd użytkownika’); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(’Wystapił błąd’); END; Analiza błędów - SQLCODE Wartość SQLCODE Opis 0 Nie napotkano wyjątku 1 Wyjątek zdefiniowany przez użytkownika +100 NO_DATA_FOUND liczba ujemna Numery innych błędów 5 2010-12-02 Analiza błędów DECLARE v_error_code NUMBER; lub log_table.code%type v_error_message VARCHAR2(255); lub log_table.message%type BEGIN … RAISE e_powtorka; EXCEPTION WHEN ... WHEN OTHERS THEN v_error_code:=SQLCODE; v_error_message:=SQLERRM; INSERT INTO log_table (code,message,info) VALUES (v_error_code, v_error_message, ’błąd’); END; EXEPTION_INIT Dyrektywa służąca do powiązania wyjątku z wybranym błędem Oracle, Pozwala to na specyficzną obsługę takiego wyjątku, a nie w klauzuli OTHERS, DECLARE PRAGMA EXCEPTION_INIT(nazwa_wyjątku, numer_błędu_Oracle); EXEPTION_INIT RAISE_APPLICATION_ERROR DECLARE e_wstawianie EXCEPTION; PRAGMA EXCEPTION_INIT(e_wstawianie,-1400); BEGIN INSERT INTO employees (salary) VALUES (NULL); EXCEPTION WHEN e_wstawianie THEN DBMS_OUTPUT.PUT_LINE(’Błąd wstawiania’); END; Funkcja pozwalająca na utworzenie własnych komunikatów o błędach, bardziej odpowiednich i szczegółowych niż w standardowych wyjątkach, RAISE_APPLICATION_ERROR(numer_błędu, Komunikat_o_błędzie [, {TRUE|FALSE}]); 6 2010-12-02 RAISE_APPLICATION_ERROR numer błędu – wartość z przedziału -20000 do -20999 komunikat_o_błędzie – tekst powiązany z błędem, maksymalnie 512 znaków, TRUE|FALSE – jeśli wartość jest równa TRUE nowy błąd zostanie dodany do listy już zgłoszonych, jeśli FALSE to nowy błąd zastąpi bieżącą listę błędów. Raise…w części wyjątków … EXCEPTION WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR(20001,’Pracownik nie istnieje’); END; Raise…w części wykonawczej … BEGIN SELECT count(*) INTO v_licznik FROM employees WHERE employee_id=30; IF v_licznik=0 THEN RAISE_APPLICATION_ERROR (-20001,’Pracownik nie istnieje’); END IF; … END; Przekazywanie wyjątków Wyjątki mogą być zgłaszane w sekcji deklaracyjnej, wykonawczej lub wyjątków, Mechanizm odpowiedzialny za odpowiednią obsługę takich wyjątków nazywamy przekazywaniem wyjątków, 7 2010-12-02 Zgłaszanie wyjątków w sekcji wykonawczej Jeśli w bloku w którym zgłoszono wyjątek jest blok jego obsługi to program wykonuje go i przekazuje sterowanie do bloku zewnętrznego, Jeśli nie ma bloku obsługi wyjątku, program przekazuje go zgłaszając w bloku zewnętrznym; jeśli brak bloku zewnętrznego to wyjątek jest przekazywany do środowiska wywołującego. Zgłaszanie wyjątków w sekcji wykonawczej DECLARE NR1 EXCEPTION; BEGIN BEGIN RAISE NR1; EXCEPTION WHEN NR1 THEN … END; END; SYTUACJA 1 Zgłaszanie wyjątków w sekcji wykonawczej Zgłaszanie wyjątków w sekcji wykonawczej DECLARE NR1 EXCEPTION; NR2 EXCEPTION; BEGIN BEGIN RAISE NR2; EXCEPTION WHEN NR1 THEN … END; EXCEPTION WHEN NR2 THEN … END: DECLARE NR1 EXCEPTION; NR2 EXCEPTION; NR3 EXCEPTION; BEGIN BEGIN RAISE NR3; EXCEPTION WHEN NR1 THEN … END; EXCEPTION WHEN NR2 THEN … END: SYTUACJA 2 SYTUACJA 3 8 2010-12-02 Zgłaszanie wyjątków w sekcji deklaracji Zgłoszenie wyjątku w sekcji deklaracji spowoduje natychmiastowe przekazanie go do bloku zewnętrznego, Nawet jeśli bieżący blok zawiera blok OTHERS nie zostanie on wykonany, Zgłaszanie wyjątków w sekcji deklaracji BEGIN DECLARE v_liczba NUMBER(3):=’XYZ’; BEGIN … EXCEPTION WHEN OTHERS THEN … END; EXCEPTION WHEN OTHERS THEN … END: Zgłaszanie wyjątków w sekcji deklaracji DECLARE v_liczba NUMBER(3):=’XYZ’; BEGIN … EXCEPTION WHEN OTHERS THEN … END; SYTUACJA 1 nieudane działanie, brak obsługi Zgłaszanie wyjątków w sekcji wyjątków Wyjątki zgłoszone w sekcji obsługi są bezpośrednio przekazywane do bloku zewnętrznego, SYTUACJA 2 Zgłoszenie wyjątków w tej sekcji odbywa się za pomocą RAISE lub pośrednio, w wyniku wystąpienia błędu. 9 2010-12-02 Zgłaszanie wyjątków w sekcji wyjątków Zgłaszanie wyjątków w sekcji wyjątków DECLARE NR1 EXCEPTION; NR2 EXCEPTION; BEGIN BEGIN DECLARE NR1 EXCEPTION; NR2 EXCEPTION; BEGIN RAISE NR1; EXCEPTION WHEN NR1 THEN RAISE NR2; WHEN NR2 THEN … END; EXCEPTION WHEN NR2 THEN … END; RAISE NR1; EXCEPTION WHEN NR1 THEN RAISE NR2; SYTUACJA 1 nieudane działanie, brak obsługi WHEN NR2 THEN … END; Funkcje i procedury tzw. bloki nazwane, podprogramy, mają strukturę podobną do bloków anonimowych: Opcjonalna sekcję deklaracyjną, bez słowa DECLARE, występuje po słowie IS lub AS, Obowiązkową sekcję wykonawczą, zawartą pomiędzy słowami BEGIN i END; Opcjonalną sekcję wyjątków. SYTUACJA 2 Różnice pomiędzy blokami nazwanymi i anonimowymi Bloki anonimowe Bloki nazwane nienazwane nazwane kompilowane każdorazowo kompilowane tylko raz nie przechowywane w bazie danych przechowywane w bazie danych nie mogą mieć żadnych parametrów mogą mieć parametry nie zwracają wartości funkcje muszą zwrócić wartość nie mogą być używane przez inne aplikacje mogą być używane przez inne programy 10 2010-12-02 Tworzenie procedur Tworzenie procedur CREATE [OR REPLACE] PROCEDURE nazwa [(argument1 [tryb1] typ_danych1, argument2 [tryb2] typ_danych2, …)] IS|AS [część_deklaracyjna] BEGIN ciało_procedury; [EXCEPTION …] END; Tryb parametrów Tryb parametrów IN – wartość argumentu jest przekazywana do procedury w momencie jej wywołania, takie argumenty są traktowane jak tylko do odczytu i nie można ich zmieniać, po zakończeniu działania wartość argumentów nie zmienia się, tryb domyślny, OUT – ignorowana jest wartość jaką ma argument w momencie wywołania procedury, parametr ma wartość NULL, można go używać do odczytu i zapisu, po zakończeniu działania procedury wartość parametru jest przypisywana do argumentu, Nazwa – dowolna nazwa procedury, Parametry – lista parametrów, ich tryb i typ danych, liczba parametrów jest dowolna, Tryb parametrów – IN OUT IN OUT Typ_danych – dowolny typ Oracle, bez jawnego określenia rozmiaru danych, można używać %TYPE IN OUT – połączenie trybów IN i OUT, wartość argumentu przekazywana jest do procedury w momencie jej wywołania, parametr działa jak zainicjowana zmienna, można do niego zapisywać i odczytywać z niego, po zakończeniu działania procedury wartość parametru jest przypisywana do argumentu, 11 2010-12-02 Procedura - przykład Procedura – tryb IN CREATE OR REPLACE PROCEDURE płaca IS v_id_dep employees.department_id%TYPE; v_podwyzka NUMBER :=10; BEGIN UPDATE employees SET salary=salary*(1+v_podwyzka/100) WHERE department_id=v_id_dep; END; CREATE OR REPLACE PROCEDURE aktualizacja (v_id IN employees.employee_id%TYPE) IS BEGIN UPDATE employees SET hire_date=sysdate WHERE employee_id=v_id; END; Procedura – tryb OUT Procedura – tryb IN OUT CREATE OR REPLACE PROCEDURE wyswietl (v_id IN employees.employee_id%TYPE, v_nazw OUT employees.last_name%TYPE) IS BEGIN SELECT last_name INTO v_nazw FROM employees WHERE employee_id=v_id; END; / SET SERVEROUTPUT ON; DECLARE v_name employees.last_name%TYPE; BEGIN wyswietl(105,v_name); DBMS_OUTPUT.PUT_LINE(v_name); END; / CREATE OR REPLACE PROCEDURE form_NIP (v_tekst IN OUT VARCHAR2) IS BEGIN v_tekst:=SUBSTR(v_tekst,1,3) || ’-’ || SUBSTR(v_tekst,4,2) || ’-’ || SUBSTR(v_tekst,6,2) || ’-’ || SUBSTR(v_tekst, 8); END; / v_tekst -> 5428323456 v_tekst -> 542-83-23-456 12 2010-12-02 Procedura - przechowywanie Procedura - wywołanie Wywołanie procedury może odbywać się np. w części wykonawczej bloku anonimowego lub innego programu PL/SQL, bądź z narzędzia SQL*Plus Procedura jest przechowywana w tabeli user_objects, można obejrzeć jej zawartość za pomocą zapytania SELECT object_name, object_type FROM user_objects; Kod źródłowy procedury można znaleźć w tabeli user_source, można go obejrzeć za pomocą zapytania SELECT * FROM user_source WHERE name=’nazwa_procedury’; Funkcje Funkcje CREATE [OR REPLACE] FUNCTION nazwa [(argument1 [tryb1] typ_danych1, argument2 [tryb2] typ_danych2, …)] RETURN typ_danych IS|AS [część_deklaracyjna] BEGIN ciało_funkcji; [EXCEPTION …] END; BEGIN nazwa_procedury; END; EXECUTE nazwa_procedury; Usunięcie procedury DROP PROCEDURE nazwa_procedury; Nazwa – nazwa funkcji, Parametry – lista parametrów z trybem i typem danych, liczba parametrów dowolna, Tryb – tryb parametru, Typ_danych – typy dostępne w PL/SQL, bez rozmiaru danych, można używać %TYPE, RETURN typ_danych – typ danych wartości zwracanej przez funkcję, Ciało_funkcji – w ciele funkcji musi wystąpić wyrażenie RETURN zwracające wartość funkcji do środowiska zewnętrznego, 13 2010-12-02 Funkcje - przykład Funkcje – wywołanie i inne CREATE FUNCTION sprawdz RETURN Boolean IS v_id employees.employee_id%TYPE; v_zarobki employees.salary%TYPE; v_zarobki_avg employees.salary%TYPE; v_dep employees.department_id%TYPE: BEGIN v_id:=105; v_dep:=100; SELECT salary INTO v_zarobki FROM employees WHERE employee_id=v_id; SELECT avg(salary) INTO v_zarobki_avg FROM employees GROUP BY department_id HAVING department_id=v_dep; IF v_zarobki>v_zarobki_avg THEN RETURN TRUE; ELSE RETURN FALSE; END IF; END; Funkcja z parametrami - przykład Funkcje z parametrami - wywołanie CREATE FUNCTION sprawdz (v_id employees.employee_id%TYPE) RETURN Boolean IS v_zarobki employees.salary%TYPE; v_zarobki_avg employees.salary%TYPE; v_dep employees.department_id%TYPE: BEGIN v_dep:=100; SELECT salary INTO v_zarobki FROM employees WHERE employee_id=v_id; SELECT avg(salary) INTO v_zarobki_avg FROM employees GROUP BY department_id HAVING department_id=v_dep; IF v_zarobki>v_zarobki_avg THEN RETURN TRUE; ELSE RETURN FALSE; END IF; END; BEGIN IF (sprawdz(105)) THEN DBMS_OUTPUT.PUT_LINE(‘Większe zarobki pracownika niż średnia w departamencie 100’); ELSE DBMS_OUTPUT.PUT_LINE(‘Mniejsze zarobki pracownika niż średnia w departamencie 100’); END IF; END; Wywołanie funkcji BEGIN IF (sprawdz) THEN DBMS_OUTPUT.PUT_LINE(‘Większe zarobki pracownika niż średnia w departamencie 100’); ELSE DBMS_OUTPUT.PUT_LINE(‘Mniejsze zarobki pracownika niż średnia w departamencie 100’); END IF; END; Usuwanie funkcji DROP FUNCTION sprawdz; Sprawdzenie argumentów i typu zwracanego funkcji DESCRIBE sprawdz; 14 2010-12-02 Notacja bazująca na pozycjach i nazwach Notacja bazująca na pozycji – podajemy argumenty wywołania w kolejności takiej jak parametry podane w definicji procedury czy funkcji, Notacja bazująca na nazwie – podajemy parametr formalny i argument, daje to możliwość zmiany kolejności argumentów w wywołaniu procedury czy funkcji, Wartości domyślne parametrów Parametrom można nadawać wartości domyślne, Jeśli parametr ma wartość domyślną nie trzeba jej przekazywać ze środowiska wywołania, argument tryb typ_danych {:= | DEFAULT} wartość Notacja - przykłady CREATE OR REPLACE PROCEDURE notacja (p_p1 Varchar2, p_p2 NUMBER, p_p3 DATE) AS BEGIN NULL; END; / DECLARE v_a1 Varchar2(10); v_a2 NUMBER; v_a3 DATE; BEGIN Notacja(v_a1,v_a2,v_a3); - bazująca na pozycji Notacja(p_p1=>v_a1, p_p3=>v_a3, p_p2=>v_a2); - bazująca na nazwie Notacja(v_a1, p_p3=>v_a3, p_p2=>v_a2); - mieszana END; Wartości domyślne parametrów CREATE OR REPLACE PROCEDURE domyslne (p_p1 Varchar2 :=‘Brak’, p_p2 NUMBER DEFAULT 0) AS BEGIN NULL; END; / BEGIN Domyslne; Domyslne(‘lancuch’,p_p2=>10); Domyslne(p_p2=>200); END; 15 2010-12-02 Przekazywanie parametrów przez referencję i wartość Parametry mogą być przekazywane przez: Referencję Program przesyła do parametru wskaźnik na argument Wartość Program kopiuje dane z argumentu do parametru formalnego Przekazywanie przez referencję jest szybsze, Domyślnie w PL/SQL: IN przez referencję, OUT, IN OUT przez wartość, Wyjątki a NOCOPY Modyfikator NOCOPY W przypadku przekazywania parametru przez referencję zmiany w parametrach formalnych wpływają na argumenty, gdyż mają tą samą lokalizację, Tak więc jeśli procedura zakończy działanie bez obsługi wyjątku po modyfikacji parametru, wartość początkowa argumentu zostanie utyracona. Pozwala na zmianę trybu przekazywania parametru, Jeśli w instrukcji znajduje się modyfikator NOCOPY to kompilator spróbuje przekazać parametr przez referencję a nie przez wartość, nazwa_parametru [tryb] NOCOPY typ_danych CREATE OR REPLACE PROCEDURE example (p_p1 OUT NOCOPY VARCHAR2, p_p2 IN OUT NOCOPY NUMBER, p_p3 IN NOCOPY DATE) IS … Ignorowanie NOCOPY Gdy argument jest elementem tablicy asocjacyjnej, Jest ograniczony przez np. precyzję lub NOT NULL, Gdy argument i parametr formalny są rekordami, a ograniczenia odpowiadających sobie pól są odmienne, Przekazanie argumentu wymaga jawnego przekształcenia typu danych, 16 2010-12-02 Sposoby wywoływania funkcji DBMS_OUTPUT.PUT_LINE(nazwa_funkcji(10)); VARIABLE p_par NUMBER; :p_par:=nazwa_funkcji(10); DECLARE v_par NUMBER; BEGIN v_par:=nazwa_funkcji(10); DBMS_OUTPUT.PUT_LINE(v_par); END; SELECT id, nazwa_funkcji(id) FROM employees; Ograniczenia – funkcje w SQL Funkcje w zapytaniach SQL Mogą wystąpić na liście SELECT, Jako wyrażenia warunkowe w WHERE lub HAVING, W klauzulach ORDER BY i GROUP BY, Jako wartości VALUES w klauzuli INSERT, W klauzuli SET w UPDATE. Procedury i funkcje – SQL Developer Funkcje muszą być składowane w bazie, Akceptują jedynie parametry typu IN o typach zgodnych z SQL a nie PL/SQL, Zwracają typ SQL a nie PL/SQL, Wywołując funkcję w zapytaniu SQL musisz być właścicielem tej funkcji lub mieć uprawnienie EXECUTE, Dopuszczalna jest tylko notacja oparta na pozycjach, a nie nazwach, 17 2010-12-02 Procedury i funkcje – SQL Developer WYKORZYSTANA LITERATURA J. Price, Oracle Database 11g i SQL. Programowanie. Helion, 2009. S. Urman, R. Hardman, M. McLaughlin, Oracle Database 10g. Programowanie w języku PL/SQL. Helion, 2008. http://wazniak.mimuw.edu.pl/index.php?title=B azy_danych www.oracle.com 18