Bazy danych wykład dwunasty PL/SQL, c.d. Konrad Zdanowski Uniwersytet Kardynała Stefana Wyszyńskiego, Warszawa dwunasty PL/SQL, c.d. 1 / 37
SQL to za mało SQL brakuje możliwości dostępnych w językach proceduralnych. W SQL wywołujemy pojedyńcze polecenia. dwunasty PL/SQL, c.d. 2 / 37
PL/SQL Język proceduralny. Zintegrowany z SQL. Możliwość składowania procedur i funkcji w bazie danych. Stosowany zarówno po stronie serwera jak i w aplikacjach klientów. Pozwala na korzystanie z bibliotek, np. I/O - set serveroutput on. Pozwala na dynamiczne konstruowanie zapytań SQL w trakcie wykonywania procedury. dwunasty PL/SQL, c.d. 3 / 37
PL/SQL postać programu DECLARE... BEGIN... EXCEPTION... END; W programie musza wystapić tylko BEGIN i END. Pozostałe części sa opcjonalne. dwunasty PL/SQL, c.d. 4 / 37
Kursory PL/SQL nie umożliwia zapytań SQL, które zwracaja całe tabele (zawierajace więcej niż jeden wiersz). Jeśli chcemy wykonać inne zapytanie, musimy użyć kursora. Kursor to zmienna, która przebiega zbiór wyników zapytania. Rodzaje kursorów: jawne i niejawne. Z każdym zapytaniem SQL zwiazany jest kursor niejawny. Kursor jawny deklarujemy w bloku DECLARE. dwunasty PL/SQL, c.d. 5 / 37
Kursory jawne deklarowanie cursor nazwa ( parametry ) i s { zapytanie return typ } [ for update [ of parametry ] ] ; Parametry podajemy jako listę oddzielona przecinkami: parametr typ [ default wartosc ] dwunasty PL/SQL, c.d. 6 / 37
Kursory jawne Zanim zaczniemy używać kursora musimy go otworzyć komenda: open nazwa_kursora ( parametry ) ; Po zakończeniu pracy kursor zamykamy: close nazwa_kursora ; Próba otwarcia otwartego kursora generuje bład, podobnie zamknięcie nieotwartego kursora. dwunasty PL/SQL, c.d. 7 / 37
Kursory jawne pobieranie rekordów Kursor możemy traktować jako zmienna typu rekordowego przebiegajac a zbiór wyników kwerendy. Aby odczytać krotkę używamy instrukcji: fetch kursor into lista zmiennych, fetch kursor into zmienna rekordowa. Zmienne przyjmuja wartość krotki, na która wskazuje kursor. Kursor przechodzi do następnej krotki. Jeśli kursor przeczytał wszystkie krotki wystapi bład. dwunasty PL/SQL, c.d. 8 / 37
Kursory jawne pobieranie rekordów declare cursor cur_osoby i s select from osoby ; osoba osoby%rowtype ; nazwisko osoby. nazwisko%type ; imie osoby. imie%type ; i d osoby. i d%type ; begin open cur_osoby ; fetch cur_osoby into imie, nazwisko, i d ; dbms_output. p u t _ l i n e ( imie nazwisko to_char ( i d ) ) ; fetch cur_osoby into osoba ; dbms_output. p u t _ l i n e ( osoba. imie osoba. nazwisko to_char ( osoba. i d ) ) ; close cur_osoby ; Konrad end Zdanowski ; ( Uniwersytet Kardynała Stefana Bazy danych Wyszyńskiego, wykładwarszawa) dwunasty PL/SQL, c.d. 9 / 37
Typy danych Możemy zadeklarować zmienna typu atrybutu jako R.atrybut%type, gdzie R to tabela lub kursor. Możemy zadeklarować zmienna typu krotki jako R%rowtype, gdzie R to tabela lub kursor. dwunasty PL/SQL, c.d. 10 / 37
Kursory jawne atrybuty Stan kursora możemy sprawdzić poprzez jego atrybuty: %ISOPEN, %FOUND przyjmuje wartości true, false lub null (przed pierwszym pobraniem), %NOTFOUND, %ROWCOUNT liczba pobranych rekordów (zero przed pobraniem). dwunasty PL/SQL, c.d. 11 / 37
Kursory jawne atrybuty declare cursor cur_osoby i s select from osoby ; osoba osoby%rowtype ; begin i f ( not cur_osoby%isopen ) then open cur_osoby ; end i f ; loop fetch cur_osoby into osoba ; e x i t when cur_osoby%notfound ; dbms_output. p u t _ l i n e ( osoba. imie osoba. nazwis end loop ; close cur_osoby ; end ; dwunasty PL/SQL, c.d. 12 / 37
Kursory jawne pętla for Możemy w łatwiejszy sposób przebiec wszystkie wyniki zapytania w pętli for: for l i c z n i k in kursor loop... end loop ; W tej konstrukcji nie musimy otwierać ani zamykać kursora. Zamiast kursora możemy użyć zapytania SQL. dwunasty PL/SQL, c.d. 13 / 37
Kursory jawne pętla for declare cursor cur_ osoby_ imie ( imie_ osoby varchar2 default Jan ) is select from osoby where osoby. imie=imie_osoby ; begin for cur in cur_osoby_imie loop dbms_output. p u t _ l i n e ( cur. imie cur. nazwisko to_char ( cur. i d ) ) ; end loop ; end ; dwunasty PL/SQL, c.d. 14 / 37
Kursory jawne modyfikacje tabel Możemy zadeklarować kursor jako for update. Kursor taki zakłada blokadę na wszystkie rekordy, które może zmodyfikować. Możemy modyfikować rekord, który został aktualnie odczytany przez kursor. update tabela set... where c u r r e n t of cur_tabela ; delete from tabela where c u r r e n t of cur_tabela ; dwunasty PL/SQL, c.d. 15 / 37
Kursory niejawne Każde polecenie SQL (select into, insert, update, delete) tworzy kursor. Nazwa kursora to sql. Sprawdzajac jego własności możemy sprawdzić własności ostatniego zapytania, np. sql%rowcount zwraca liczbę krotek zapytania. dwunasty PL/SQL, c.d. 16 / 37
Wyjatki Jeśli w czasie wykonywania programu PL/SQL wystapi bład, działanie programu zostaje przerwane. Program może przechwycić obsługę błedu w części exception. Program może zgłosić też własny wyjatek przez: raise nazwa_wyjatku. dwunasty PL/SQL, c.d. 17 / 37
Wyjatki Wyjatki prefefiniowane: cursor_already_open, invalid_cursor, no_date_found, too_many_rows, value_error, zero_divide. W części obsługujacej wyjatki możemy użyć: when others aby obsłużyć wyjatki, których wcześniej nie wymienilismy. dwunasty PL/SQL, c.d. 18 / 37
Wyjatki użytkownika Wyjatki definiujemy w częsci declare przez nazwa_wyjatku exception; Zgłaszamy przez raise nazwa_wyjatku. dwunasty PL/SQL, c.d. 19 / 37
Obsługa wyjatków sterowanie declare cursor cur_osoby is select from osoby osoba osoby%rowtype ; begin begin open cur_osoby ; open cur_osoby ; dbms_output. p u t _ l i n e ( T u t a j sterowanie nie dotrze exception when cursor_already_open then close cur_osoby ; dbms_output. p u t _ l i n e ( Zamknieto k end ; dbms_output. p u t _ l i n e ( T u t a j wraca sterowanie ) ; close cur_osoby ; exception when i n v a l i d _ c u r s o r then dbms_output. p u t _ l i n e ( Zabroniona operacja na kursorze end ; dwunasty PL/SQL, c.d. 20 / 37
Obsługa wyjatków sterowanie Po obsłużeniu wyjatku sterowanie wraca do bloku programu, który wywołał program, w którym powstał wyjatek. Raz obsłuzony wyjatek nie jest obsługiwany wyżej. Nie obsłużony wyjatek powoduje przerwanie programu i zgłoszenie błędu aplikacji. dwunasty PL/SQL, c.d. 21 / 37
Obsługa wyjatków sterowanie Jeśli wyjatek powstanie w sekcji declare, to sterowanie wraca do programu, który wywołał program, który zgłosił wyjatek. Podobnie zachowuja się wyjatki powstałe w części obsługujacej wyjatki. dwunasty PL/SQL, c.d. 22 / 37
Obsługa wyjatków sterowanie begin declare i number(3):=1000; begin null ; exception when v a l u e _ e r r o r then dbms_output. p u t _ l i n e ( Zla wartosc ) ; t u t a j sterowanie nie dotrze end ; null ; exception when v a l u e _ e r r o r then dbms_output. p u t _ l i n e ( T u t a j nastepuje obsluga end ; dwunasty PL/SQL, c.d. 23 / 37
Obsługa wyjatków przykład create table Kura ( i d i n t primary key, j a j k o _ i d i n t ) ; create table Jajko ( i d i n t primary key, kura_id i n t ) ; a l t e r table Kura add constraint KuraRefJajko foreign key ( j a j k o _ i d ) references Jajko ( i d ) i n i t i a l l y deferred deferrable ; a l t e r table Jajko add constraint JajkoRefKura foreign key ( kura_id ) references Kura ( i d ) i n i t i a l l y deferred deferrable ; dwunasty PL/SQL, c.d. 24 / 37
Obsługa wyjatków przykład create or replace t r i g g e r DodajJajko before update or insert on Kura for each row declare i number ; begin select i d into i from Jajko where kura_id =:new. kura_id ; exception when no_data_found then i n s e rt into Jajko values ( : new. j a j k o _ i d, null ) ; end ; dwunasty PL/SQL, c.d. 25 / 37
Składowane programy Przechowywane po skompilowaniu w BD. Procedury, funkcje, wyzwalacze, pakiety. dwunasty PL/SQL, c.d. 26 / 37
Składowane programy parametry Pozwalaja przekazywać wartości do programu i z programu. Paremetry programu w deklaracji nazywamy formalnymi, przy wywołaniu programu aktualnymi. Typy parametrów to in, out, in out. dwunasty PL/SQL, c.d. 27 / 37
Składowane programy składnia create [ or replace ] nazwa_procedury [ ( parametry ) ] i s d e k l a r a c j e begin... end [ nazwa_procedury ] ; dwunasty PL/SQL, c.d. 28 / 37
Składowane programy składnia create [ or replace ] nazwa_funkcji [ ( parametry ) ] return typ [ is as ] d e k l a r a c j e begin... end [ nazwa_funkcji ] ; Funkcja powinna zawierać return. Po wykonaniu tej instrukcji wychodzimy z funkcji. Funkcji możemy użyć w zapytaniu SQL. dwunasty PL/SQL, c.d. 29 / 37
Składowane programy parametry Parametry deklarujemy jako: nazwa_parametru [ t r y b przekazania ] typ [ { default wartosc ]. Typy parametrów to: in domyślny tryb, przekazuje wartość do programu, parametr zachowuje się jak stała, out parametr musi być zmienna, traktujemy ja jako zmienna niezainicjowana, przekazuje wartość na zewnatrz procedury, in out zmienna zainicjowana przekazujaca wartość na zewnatrz. dwunasty PL/SQL, c.d. 30 / 37
Składowane programy przykład create or replace procedure inkrementacja ( n in out number ) return number is begin n := n+1; return ( n ) ; end inkrementacja ; Teraz możemy procedurę wywołać: declare n number : = 3 ; i number ; begin t u t a j n = 3 i := inkrementacja ( n ) ; t u t a j n = 4 end ; dwunasty PL/SQL, c.d. 31 / 37
Pakiety create [ or replace ] package nazwa_pakietu i s d e k l a r a c j e zmiennych, stalych, kursorow, f u n k c j i, procedur,... end ; create [ or replace ] package body nazwa_pakietu i s d e k l a r a c j e zmiennych, stalych, kursorow niedostepnych w i n t e r f e j s i e pakietu, d e f i n i c j e f u n k c j i i procedur end ; Funkcje i procedury z pakietu wywołujemy jako: nazwa_pakietu.nazwa_programu(). dwunasty PL/SQL, c.d. 32 / 37
Dynamiczny SQL Jeśli nie znamy podczas kompilacji pytania SQL, możemy je skonstruować podczas wykonywania programu. Typowe sytuacje to: nie znamy nazwy tabeli, z której będziemy pobierać dane, nie znamy warunku. Dynamiczny SQL jest mniej efektywny i bardziej podatny na błedy (np. podczas kompilacji zapytania). Możemy też w ten sposób wywoływać programy PL/SQL. dwunasty PL/SQL, c.d. 33 / 37
Dynamiczny SQL przykład create or replace procedure wloz_osoba ( osoba_id i n out number, imie in varchar2, nazwisko i n varchar2 ) as begin osoba_id := osoby_seq. n e x t v a l ; insert into osoby values ( osoba_id, imie, nazwisko ) ; end ; declare plsql_komenda varchar2 ( 5 0 0 ) ; nowe_imie varchar2 ( 5 0 ) : = Jan ; nowe_nazwisko varchar2 ( 100):= Kowalski ; begin plsql_komenda := begin wloz_osoba ( : a, : b, : c ) ; end ; ; execute immediate plsql_komenda using i n out nowe_id, nowe_imie, nowe_nazwisko ; end ; dwunasty PL/SQL, c.d. 34 / 37
Dynamiczny SQL przykład Nie można przekazać stałej null ale można przekazać zmienna, która ma ta wartość. Trzeba uważać na typy przekazywanych zmiennych, by były zgodne z SQL, np. nie można użyć w tworzonym zapytaniu SQL zmiennej o typie boolean. dwunasty PL/SQL, c.d. 35 / 37
Dynamiczny SQL parametry Jeśli wywołujemy zapytanie SQL, to nie sa istotne nazwy użytych w definicji parametrów. Ten kod wstawi do tabeli osoby pana Jana Nowaka: begin sql_zapytanie := i n s e r t i n t o osoby values ( : x, : x, : y ) ; execute immediate sql_zapytanie using 18, Jan, Nowak ; end ; Jeśli wywołujemy program PL/SQL nazwy parametrów sa istotne. Ten kod obliczy wartość funkcja(a,b,a): begin sql_zapytanie := begin f u n k c j a ( : x, : y, : x ) ; execute immediate sql_zapytanie using a, b ; end ; dwunasty PL/SQL, c.d. 36 / 37
Dynamiczny SQL przykład declare type KursorTyp i s r e f cursor ; cur_osoby KursorTyp ; v _ s t r varchar2 ( 2 0 0 ) ; osoba osoby%rowtype ; begin v _ s t r := s e l e c t from osoby where imie =: i ; open cur_osoby for v _ s t r using Ewa ; loop fetch cur_osoby into osoba ; e x i t when cur_osoby%notfound ; dbms_output. p u t _ l i n e ( osoba. imie osoba. nazwisko ) ; end loop ; end ; dwunasty PL/SQL, c.d. 37 / 37