Materiały dostępne są na stronie: Materiały Technologie baz danych aragorn.pb.bialystok.pl/~gkret Wykład 5: Kursory jawne. Podprogramy. Małgorzata Krętowska Wydział Informatyki Politechnika Białostocka 1 2 Plan wykładu Kursory Kursory niejawne powtórzenie Kursory jawne Podprogramy: funkcje, procedury, pakiety Kursory niejawne deklarowane są dla wszystkich instrukcji DML oraz SELECT PL/SQL zarządza automatycznie kursorem niejawnym Kursory jawne deklarowane przez programistę Parametry kursora: Nazwa_kursora%nazwa_parametru Parametry kursora: SQL%nazwa_parametru 3 4
Atrybuty kursora SQL SQL%ROWCOUNT SQL%FOUND SQL%NOTFOUND SQL%ISOPEN Liczba wierszy, których dotyczyła ostatnia instrukcja SQL Atrybut logiczny, który przyjmuje wartość TRUE, gdy ostatnia instrukcja dotyczyla jednego lub więcej wierszy Atrybut logiczny, który przyjmuje wartość TRUE, gdy ostatnia instrukcja dotyczyła zerowej liczby wierszy Zawsze przyjmuje wartość FALSE ponieważ PL/SQL zamyka kursory natychmiast po ich wykonaniu Atrybuty kursorów - przykład v_usuniete VARCHAR2(30); DELETE FROM zamowiona_ksiazka WHERE id_zamowienia = ∥ v_usuniete := TO_CHAR(SQL%ROWCOUNT) rekordow usunietych. ; Kursory niejawne - przykład CREATE TABLE komunikat (numer NUMBER, tekst1 VARCHAR2(15), tekst2 VARCHAR2(15) ); Przykład: Napisać blok PL/SQL, który sprawdzi ile książek wydał wydawca o identyfikatorze = 1. Nazwę wydawcy oraz liczbę książek należy zapisać w tabeli komunikat. v_liczba NUMBER; v_nazwa VARCHAR2(15); Przykład cd SELECT COUNT(*), nazwa INTO v_liczba, v_nazwa FROM t_wydawca, t_ksiazka WHERE t_wydawca.id_wydawcy=t_ksiazka.wydawca AND id_wydawcy =1 GROUP BY nazwa,id_wydawcy; INSERT INTO komunikat (numer,tekst1) VALUES (v_liczba, v_nazwa); / 7 8
Kursory jawne - deklaracja Kursory jawne CURSOR nazwa_kursora [(parametr [, parametr] )] IS instrukcja_select; parametr ::= nazwa_parametru typ danych [{:= DEFAULT wyrażenie}].. ; OPEN nazwa_kursora [(parametr [, parametr]...)]; CURSOR kursor (p_isbn VARCHAR(10)) IS SELECT * FROM ksiazka WHERE isbn = p_isbn; FETCH nazwa_kursora INTO zmienna [, zmienna...]; CLOSE nazwa_kursora; Sterowanie kursorami jawnymi NIE OPEN FETCH PUSTY? TAK CLOSE CURSOR k_cursor IS SELECT * FROM zamowiona_ksiazka WHERE isbn = 1; k_record zamowiona_ksiazka%rowtype; v_ilosc zamowiona_ksiazka. ilosc %TYPE := 0; OPEN k_cursor; LOOP FETCH k_cursor INTO k_record; IF k_cursor%notfound THEN EXIT; END IF; v_ilosc := v_ilosc + k_record.ilosc; dbms_output.put_line(k_cursor%rowcount); dbms_output.put_line(v_ilosc); CLOSE k_cursor;
Pęta kursorowa FOR FOR nazwa_rekordu IN nazwa_kursora LOOP instrukcja-1; instrukcja-2;. Niejawne instrukcje OPEN, FETCH, CLOSE zmienna nazwa_rekordu zadeklarowana niejawnie Kursory jawne - przykład CURSOR k_cursor (p_zam zamowienie.id_zamowienia%type) IS SELECT * FROM zamowiona_ksiazka WHERE id_zamowienia = p_zam; FOR i IN k_cursor(1) LOOP dbms_output.put_line(i.isbn); Kursor w pętli FOR CURSOR a_cursor IS SELECT * FROM autor; FOR i IN a_cursor LOOP dbms_output.put_line(i.nazwisko); FOR i IN (SELECT * FROM autor) LOOP dbms_output.put_line(i.nazwisko); Atrybuty kursorow jawnych %ROWCOUNT %FOUND %NOTFOUND %ISOPEN Liczba wierszy, sprawdzonych w kursorze w danym momencie Atrybut logiczny, który przyjmuje wartość TRUE, jeśli instrukcja FETCH zwróci wiersz Atrybut logiczny, który przyjmuje wartość TRUE, jeśli ostatnia instrukcja FETCH nie zwrócila żadnego wiersza Atrybut logiczny, który przyjmuje wartość TRUE, jeśli kursor jest otwarty
Użycie klauzuli WHERE CURRENT OF CURSOR k_cursor(v_zakres ksiazka.cena%type) IS SELECT cena FROM ksiazka WHERE cena > v_zakres FOR UPDATE; FOR i IN k_cursor(40) LOOP UPDATE ksiazka SET cena = cena* 1.1 WHERE CURRENT OF k_cursor; COMMIT; Użycie klauzuli WHERE CURRENT OF Używając kursorów można aktualizować lub usuwać rekordy Klauzula FOR UPDATE blokuje wiersze Klauzula WHERE CURRENT OF odwołuje się do bieżącego rekordu z kursora jawnego Nie wolno zatwierdzać instrukcji z kursora jawnego, jeżeli użyta jest klauzula FOR UPDATE Kursory - podsumowanie Podprogramy Kursory niejawne używane dla wszystkich instrukcji DML oraz zapytań zwracających jeden wiersz Kursory jawne używane dla zapytań zwracających zero lub więcej wierszy Procedury do przeprowadzenia akcji Funkcje do obliczania wartości Pakiety do gromadzenia logicznie powiązanych procedur i funkcji
Składniki podprogramu Nagłówek podprogramu [deklaracje] [EXCEPTION obsługa wyjątków] Podprogramy [CREATE OR REPLACE] PROCEDURE nazwa_procedury [ (parametr [, parametr ] )] IS [deklaracje] [EXCEPTIONS obsługa wyjątków] END [nazwa_procedury]; Podprogramy Tryby parametrów podprogramów [CREATE OR REPLACE] FUNCTION nazwa_funkcji [(parametr [, parametr ] )] RETURN nazwa_typu IS [deklaracje] [EXCEPTIONS obsługa wyjątków] END [nazwa_funkcji]; Środowisko Argument IN Argument OUT Argument IN OUT [deklaracje] [EXCEPTION obsługa wyjątków]
Parametry w podprogramach Procedura - przykład parametr [IN OUT [NOCOPY] IN OUT [NOCOPY]] typ_danych [:= DEFAULT wyrazenie] CREATE OR REPLACE PROCEDURE mod_cene (p_isbn ksiazka.isbn%type, p_wartosc NUMBER) IS IN OUT IN OUT Parametry przekazywane przez wartość Parametry przekazywane przez referencję UPDATE ksiazka SET cena = cena + p_wartosc WHERE isbn = p_isbn; END mod_cene; Funkcja - przykład Wywoływanie procedur/funkcji CREATE OR REPLACE FUNCTION wyznacz_vat(p_isbn ksiazka.isbn%type) RETURN NUMBER IS v_cena ksiazka.cena%type; SELECT cena INTO v_cena FROM ksiazka WHERE isbn = p_isbn; EXECUTE nazwa_procedury[(parametry)] EXECUTE zmienna:= nazwa_funkcji[(parametry)] RETURN (v_cena*0.07); END wyznacz_vat;
Wywoływanie procedur/funkcji - przykład Użycie funkcji w instrukcji SQL EXECUTE mod_cene(1, 5); VARIABLE g_vat NUMBER EXECUTE :g_vat := wyznacz_vat(1); PRINT g_vat SELECT tytul, cena, wyznacz_vat(1) FROM ksiazka WHERE isbn = 1; Błędy Błędy bloków anonimowych pojawiają się na ekranie Błędy zapamiętanych procedur są zapisywane w tabeli USER_ERRORS słownika danych Procedury/funkcje -podsumowanie Funkcje zdefiniowane przez użytkownika mogą być stosowane w instrukcjach SQL (procedury nie!) Funkcja nie może zawierać instrukcji DML SHOW ERRORS SELECT * FROM user_errors;
Pakiety Specyfikacja pakietu Aplikacja Pakiet Specyfikacja Ciało pakietu Baza danych CREATE [OR REPLACE] PACKAGE nazwa_pakietu AS deklaracje publiczne specyfikacje podprogramów Tworzenie ciala pakietu CREATE [ OR REPLACE ] PACKAGE BODY nazwa_pakietu AS deklaracje prywatne definicje podprogramów [ instrukcje inicjalizujące pakietu] Pakiety - przykład CREATE OR REPLACE PACKAGE pak_zamowienia AS PROCEDURE usun_zamowienie (v_id zamowienie.id_zamowienia%type); PROCEDURE dodaj_pozycje (v_id zamowienie.id_zamowienia%type, v_isbn ksiazka.isbn%type, v_ilosc zamowiona_ksiazka.ilosc%type);
Pakiety - przykład Pakiety - przykład CREATE PACKAGE BODY pak_zamowienia AS PROCEDURE usun_zamowienie (v_id zamowienie.id_zamowienia%type) IS DELETE FROM zamowiona_ksiazka WHERE id_zamowienia = v_id; DELETE FROM zamowienie WHERE id_zamowienia = v_id; PROCEDURE dodaj_pozycje (v_id zamowienie.id_zamowienia%type, v_isbn ksiazka.isbn%type, v_ilosc zamowiona_ksiazka.ilosc%type); IS INSERT INTO zamowiona_ksiazka VALUES(v_id, v_isbn, SYSDATE, v_ilosc); -- koniec pakietu Pakiety - przykład Pakiety - zalety korzystania EXECUTE pak_zamowienia.usun_zamownienie(5); Poprawa zarządzania procedurami i funkcjami Poprawa bezpieczeństwa (uprawnienia do pakietu!) Poprawa efektywności EXECUTE pak_zamowienia.dodaj_pozycje(,,,);