Spis treści 1 Kursory
Transkrypt
Spis treści 1 Kursory
Plan wykładu Spis treści 1 Kursory 1 2 Wyjątki 2.1 Wyjątki predefiniowane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Wyjątki niezdefiniowane wcześniej . . . . . . . . . . . . . . . . . . . . . . . 2.3 Definiowanie własnych wyjątków . . . . . . . . . . . . . . . . . . . . . . . . 4 4 5 6 3 Podsumowanie 8 4 Źródła 8 1 Kursory Kursor Kursor - posiadający nazwę wskaźnik do prywatnej przestrzeni roboczej pozwalającej składować i udostępniać wynik zapytania SELECT albo zapytań DML manipulujących na danych (INSERT, UPDATE, DELETE albo MERGE). Rodzaje kursorów • Kursory niejawne - tworzone automatycznie dla wszystkich zapytań SQL manipulujących na danych oraz dla zapytań SELECT wewnątrz PL/SQL. • Kursory jawne - tworzone i zarządzanie przez programistę dla zapytań, które zwracają więcej niż jeden wiersz. Kursor jawny Obsługa kursora jawnego (instrukcje sterujące): • deklaracja, • otwarcie (OPEN), • pobranie danych (FETCH), • zamknięcie (CLOSE). Deklaracja kursora Deklaracja kursora: CURSOR nazwa [(parametr1 typ [:=|DEFAULT wartosc1] [, parametr2...]...)] [RETURN typ] IS SELECT...; Przykłady: 1 CURSOR c_szefowie IS SELECT DISTINCT kierownik FROM pracownicy; CURSOR c_dzial (p_id NUMBER) IS SELECT * FROM pracownicy WHERE id_dzialu=p_id; CURSOR c_dzial (p_id NUMBER := 10) IS SELECT * FROM pracownicy WHERE id_dzialu=p_id; CURSOR c_pracownicy RETURN pracownicy%ROWTYPE; Otwarcie kursora OPEN nazwa (lista_parametrow); Np.: DECLARE CURSOR c_dzial (p_id NUMBER := 10) IS SELECT * FROM pracownicy WHERE id_dzialu=p_id; ... BEGIN OPEN c_dzial(20); ... END; Pobranie danych FETCH nazwa INTO {lista_zmiennych|zmienna_rekordowa}; Np.: DECLARE CURSOR c_dzial (p_id NUMBER := 10) IS SELECT * FROM pracownicy WHERE id_dzialu=p_id; vr_pracownik pracownicy%ROWTYPE; ... BEGIN OPEN c_dzial(20); FETCH c_dzial INTO v_pracownik; ... END; Zamknięcie kursora CLOSE nazwa; Np.: DECLARE CURSOR c_dzial (p_id NUMBER := 10) IS SELECT * FROM pracownicy WHERE id_dzialu=p_id; vr_pracownik pracownicy%ROWTYPE; ... BEGIN OPEN c_dzial(20); FETCH c_dzial INTO v_pracownik; CLOSE c_dzial; ... END; 2 Atrybuty kursora jawnego Każdy kursor posiada atrybuty: • %ISOPEN - zwraca TRUE jeżeli kursor jest otwarty, w przeciwnym razie zwraca FALSE (dla niejawnego zawsze FALSE), • %FOUND - po otwarciu kursora ale przed pierwszym pobraniem danych zwraca NULL; zwraca TRUE jeżeli ostatnie pobranie (FETCH) zwróciło dane albo FALSE jeśli nie zwróciło danych, • %NOTFOUND - po otwarciu kursora ale przed pierwszym pobraniem danych zwraca NULL; zwraca TRUE jeżeli ostatnie pobranie nie zwróciło danych albo TRUE jeśli zwróciło dane, • %ROWCOUNT - zwraca liczbę pobranych wierszy od momentu otwarcia kursora; przed pierwszym pobraniem zwraca 0. Pętle obsługujące kursor DECLARE CURSOR c_dzial (p_id NUMBER := 10) IS SELECT * FROM pracownicy WHERE id_dzialu=p_id; vr_pracownik pracownicy%ROWTYPE; BEGIN OPEN c_dzial(20); LOOP FETCH c_dzial INTO vr_pracownik; EXIT WHEN c_dzial%NOTFOUND OR c_dzial%NOTFOUND IS NULL; dbms_output.put_line(c_dzial%ROWCOUNT || ' . ' || vr_pracownik.nazwisko); END LOOP; dbms_output.put_line('Wybrano '|| c_dzial%ROWCOUNT||' wierszy.'); CLOSE c_dzial; END; Pętla FOR obsługująca kursor I DECLARE CURSOR c_dzial (p_id NUMBER := 10) IS SELECT * FROM pracownicy WHERE id_dzialu=p_id; BEGIN FOR vr_pracownik IN c_dzial(20) LOOP dbms_output.put_line(vr_pracownik.nazwisko); END LOOP; END; Pętla FOR obsługująca kursor II DECLARE v_id pracownicy.id_dzialu%TYPE := &id; BEGIN FOR vr_pracownik IN (SELECT * FROM pracownicy WHERE id_dzialu = v_id ) LOOP dbms_output.put_line(vr_pracownik.nazwisko); END LOOP; END; 3 2 Wyjątki Wyjątki Czym jest wyjątek? Wyjątek Wyjątek błąd który może wystąpić w czasie wykonywania bloku PL/SQL. Zdarzenie to powoduje przerwanie normalnego toku działania programu. Wyjątek można obsłużyć wychwytując go (obsługa sytuacji wyjątkowej) albo przekazując go (propagacja) do środowiska uruchomienia programu. Wyjątek może być wywołany niejawnie przez serwer Oracle albo jawnie przez program. Rodzaje wyjątków • Wywoływane niejawnie – zdefiniowane wcześniej – nie zdefiniowane wcześniej • Wywoływane jawnie - predefiniowane przez użytkownika 2.1 Wyjątki predefiniowane Wyjątki predefiniowane Niektóre wyjątki zgłaszane automatycznie przez system: • CASE_NOT_FOUND - żadna z podanych klazul WHEN nie spełnia warunku, a nie przewidziano sekcji domyślnej ELSE. • CURSOR_ALREADY_OPEN - próba otwarcia otwartego kursora; kursor musi być zamknięty przed próbą ponownego otwarcia go. • DUP_VAL_ON_INDEX - próba naruszenia ograniczenia unikalnej wartości. • INVALID_CURSOR - nielegalna operacja na kursorze, np. próba zamknięcia nieotwartego kursora. • INVALID_NUMBER - w wyrażeniach SQL błąd konwersji znaków na liczbę wartości (ciąg zanków nie przedstawia prawidłowej liczby). W kodzie PL/SQL wywoływany jest błąd VALUE_ERROR. • LOGIN_DENIED - nieudana próba połączenia do bazy, błędny login albo hasło. • NO_DATA_FOUND - instrukcja SELECT INTO nie zwróciła żadnego wiersza albo program odnosi się do usuniętego elementu w zagnieżdżonej tabeli albo do niezainicjowanego elementu w tabeli asocjacyjnej. • NOT_LOGGED_ON - program próbuje operować na baze danych nie będąc z nią połączonym. • TIMEOUT_ON_RESOURCE - przekroczenie czasu oczekiwania na zasoby przekazywane do bazy danych. • TOO_MANY_ROWS - instrukcja SELECT INTO zwróciła więcej niż jeden wiersz. 4 • VALUE_ERROR - wystąpił błąd arytmetyczny, konwersji, przycięcia wartości albo przekroczenia ograniczenia jej rozmiaru. • ZERO_DIVIDE - próba dzielenia przez zero. Funkcje umożliwiające identyfikację błędu Identyfikacja błędu (obie funkcje bez parametrów): • SQLERRM - funkcja zwraca opis błęduzwiązanego z wyjątkiem, który wystąpił jako ostatni. • SQLCODE - funkcja zwracająca numer wyjątku, który wystąpił jako ostatni. Dla wyjątków wewnętrznych zwraca numer błędu z bazy Oracle. Wychwytywanie wyjątków EXCEPTION WHEN wyjatek1 [OR wyjatek2 ...] THEN instrukcje1; [WHEN wyjatek3 [OR wyjatek4 ...] THEN instrukcje2; ...] [WHEN OTHERS THEN instrukcje_n;] Sekcja WHEN OTHERS • Sekcja OTHERS jest używana do obsługi wszystkich wyjątków, które nie zostały wcześniej określone. • Sekcja OTHERS musi być ostatnia na liście obsługi wyjątków. 2.2 Wyjątki niezdefiniowane wcześniej Wyjątki niezdefiniowane wcześniej • Są dowolnymi innymi standardowymi błędami serwera Oracle • Muszą być zadeklarowane w sekcji deklaracji • Należy powiązać podaną nazwę z zewnętrznym numerem błędu używając: PRAGMA EXCEPTION_INIT Wyjątki niezdefiniowane wcześniej DECLARE e_insert EXCEPTION; PRAGMA EXCEPTION_INIT(e_insert, -014000); BEGIN INSERT INTO dzial (id_dzialu, nazwa) VALUES(300, 'Executives') EXCEPTION WHEN e_insert THEN DBMS_OUTPUT.PUT_LINE ('Błąd wstawiania'); END; / 5 2.3 Definiowanie własnych wyjątków Wyjątki użytkownika Jak tworzyć i obsługiwać własne wyjątki? Korzystanie z wyjątków użytkownika I • deklaracja nazwa_wyjatku EXCEPTION; • podniesienie wyjątku RAISE nazwa_wyjatku; • przechwycenie w sekcji obsługi wyjątków. EXCEPTION WHEN wyjatek1 THEN instrukcje1; WHEN wyjatek2 THEN instrukcje2; ... WHEN OTHERS THEN instrukcje_n; Korzystanie z wyjątków użytkownika II DECLARE e_zla_wartosc EXCEPTION; ... BEGIN ... IF v_id = 0 THEN RAISE e_zla_wartosc; END IF; ... EXCEPTION WHEN e_zla_wartosc THEN dbms_output.put_line('Bledna wartosc identyfikatora.'); END; 6 Propagacja wyjątków I BEGIN ... BEGIN ... IF v_id = 0 THEN RAISE e_zla_wartosc; END IF; ... EXCEPTION WHEN e_zla_wartosc THEN dbms_output.put_line('Bledna wartosc identyfikatora.'); END; ... EXCEPTION ... END; Propagacja wyjątków II BEGIN ... BEGIN ... IF v_id = 0 THEN RAISE e_zla_wartosc; END IF; ... EXCEPTION WHEN TOO_MANY_ROWS THEN dbms_output.put_line('Za duzo wartosci.'); END; ... EXCEPTION WHEN e_zla_wartosc THEN dbms_output.put_line('Bledna wartosc ident...'); END; Propagacja wyjątków III BEGIN ... BEGIN ... IF v_id = 0 THEN RAISE e_zla_wartosc; END IF; ... EXCEPTION WHEN TOO_MANY_ROWS THEN dbms_output.put_line('Za duzo wartosci.'); END; ... 7 EXCEPTION WHEN VALUE_ERROR THEN dbms_output.put_line('Blad konwersji.'); END; Raise application error Wywołania procedury Raise_application_error pozwala przerwać działanie programu i wyprowadzić na ekran informacje o błędzie. Pozwala to pominąć zwracanie niewychwyconego wyjątku. Składnia: Raise_application_error( numer_bledu, opis[, {TRUE|FALSE}]); Numer błedu zawiera się w przedziale od -20000 do -20999, a opis może zajmować 2048 bajtów. Opcjonalny trzeci parametr dla wartości FALSE (domyślnie) powoduje, że zgłaszany błąd zastępuje wszystkie wcześniejsze błędy na stosie. Wartość TRUE oznacza dodanie błędu do stosu wcześniejszych błędów. Raise application error Przykład użycia: IF v_id = 0 THEN Raise_application_error(-20002, 'Błędny identyfikator'); ELSE ... END IF; 3 Podsumowanie Podsumowanie PL/SQL pozwala na: • korzystanie ze zmiennych, stałych, • korzystanie z instrukcji sterujących, • przetwarzanie sekwencyjne zorientowane na dane, • obsługiwanie wyjątków, • użycie wcześniej zdefiniowanych pakietów i bibliotek, • i wiele innych o czym na następnym wykładzie... 4 Źródła Źródła • http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/toc.htm • M. Lentner, Oracle 9i Kompletny podrêcznik u¿ytkownika, PJWSTK - W-wa, 2003 • http://www.ploug.org.pl/showhtml.php?file=szkola/szkola_9/materialy 8 • http://plsql-tutorial.com/index.htm • http://www.toadworld.com/platforms/oracle/w/wiki/8243.plsql-obsession. aspx 9