Plan wykładu 2 TWORZENIE APLIKACJI BAZODANOWYCH Wykład 2: Wprowadzenie do PL/SQL: bloki anonimowe, zmienne, kursory Wprowadzenie do PL/SQL Bloki Podstawowe składowe języka Zmienne i stałe Kursory Małgorzata Krętowska Wydział Informatyki Politechnika Białostocka PL/SQL PL/SQL - historia 3 4 PL/SQL (Procedural Language SQL) Proceduralne (a czasem obiektowe) rozszerzenie programistyczne języka SQL, stworzone, udostępnione przez Oracle i przeznaczone do obsługi narzędzi tej firmy Wywodzi się z języka ADA Jest chroniony prawami autorskimi, Jest językiem trzeciej generacji 3GL, PL/SQL 1.0 wprowadzono w 1991 roku, wersja była ograniczona i brakowało w niej wielu funkcji, wypuszczona z wersją serwera bazodanowego 6.0, Kolejna wersja 2.3 udostępniała obsługę procedur i funkcji składowanych, Wersja 8.0 wprowadzenie modelu obiektoworelacyjnego, Wersje 8.1, 9.0, 9.2, 10.0 to kolejne udoskonalenia języka, Najnowsza wersja to 11.0
Bloki Struktura bloku 5 6 Podstawowa jednostka w PL/SQL Program składa się przynajmniej z jednego bloku Bloki mogą być zagnieżdżone Bloki mogą być wykonywane tylko raz, bez zapisywania (bloki anonimowe) Bloki można zapisywać w bazie w celu ich późniejszego wykorzystania (bloki nazwane) Bloki obsługują wszystkie instrukcje DML, a także DDL [ ] deklaracje zmiennych, wyjątki wyrażenia SQL i PL/SQL [EXCEPTION ] obsługa wyjątków [] opcjonalnie Blok nie może być pusty. Sekcja deklaracji Sekcja wykonawcza 7 8 Jest to sekcja opcjonalna Umieszczamy w niej zmienne i ich typy, stałe, kursory, wyjątki definiowane przez użytkownika, wszystko to do czego odwołujemy się w kolejnej sekcji bloku Możliwość dokonania inicjalizacji Przykład v_zmienna NUMBER; Obowiązkowa Rozpoczyna się od słowa kluczowego Musi posiadać co najmniej jedną instrukcję Może zawierać dowolną liczbę bloków PL/SQL, zagnieżdżonych Może zawierać polecenia SQL lub PL/SQL
Sekcja wyjątków Typy bloków 9 10 Opcjonalna Rozpoczyna się od słowa kluczowego EXCEPTION Pozwala na przechwytywanie błędów, które wystąpiły w sekcji wykonawczej Bloki anonimowe Bloki nazwane Funkcje Procedury Bloki anonimowe Przykład 11 12 Nie posiadają nazwy i nie są przechowywane w bazie danych Można w nich wywoływać inne programy, ale ich nigdzie nie można wywołać Są kompilowane za każdym razem gdy program jest uruchamiany Struktura bloku anonimowego jak wcześniej. SET SERVEROUTPUT ON; - na zewnątrz bloku anonimowego umożliwia wypisywanie komunikatów DBMS_OUTPUT.PUT_LINE ( komunikat ); - wypisywanie komunikatu DBMS_OUTPUT.NEW_LINE; - przejście do nowej linii
Uruchamianie bloku Uruchamianie bloku 13 14 Oracle SQL Developer: Uruchamianie: Run Script (F5); Wyniki: Script Output Oracle SQL*Plus: Uruchamianie: znak / na końcu kodu Uruchamianie bloku Podstawowe składowe języka 15 16 Identyfikatory Ograniczniki Literały Słowa zarezerwowane Komentarze Oracle SQL*Plus: Jeżeli kod bloku jest zapisany w pliku (ze znakiem / na końcu): Uruchamianie: start ścieżka dostępu do pliku @ ścieżka dostępu do pliku
Identyfikatory Ograniczniki 17 18 Służą do nazywania zmiennych, kursorów, funkcji, procedur, etc., Zasady tworzenia identyfikatorów: <30 znaków Rozpoczynają się literą Mogą zawierać znaki $,#,_ i cyfry (oprócz pierwszej pozycji), Nie mogą zawierać znaków przestankowych, odstępów i myślników, Nie mogą zawierać słów zarezerwowanych, Wyjątek to identyfikatory w cudzysłowach - można w nich stosować prawie wszystko. +,-,*,/ - operatory matematyczne >,<,<>,=,!= - operatory porównania --, /*, */ - komentarze <<, >> - etykiety % - atrybuty (TYPE, etc.) ogranicznik łańcuchów znaków ogranicznik identyfikatorów := - przypisanie, inicjalizacja zmiennej - łączenie łańcuchów znaków Literały Deklaracja zmiennych i stałych 19 20 Wartości, które nie są reprezentowane przez identyfikatory, ani nie są wyliczane na podstawie innych wartości: Znakowe: np. abc Liczbowe: 1, 2, 456 Logiczne: TRUE, FALSE Związane z datą 23-12-2013 Zmienne: identyfikator typ_danych [NOT NULL] [:=wart_pocz DEFAULT wart_pocz]; Stałe: identyfikator CONSTANT typ_danych [:=wart_pocz DEFAULT wart_pocz]; v_zmienna NUMBER(5); v_nr NUMBER(3) NOT NULL := 10; c_stala CONSTANT NUMBER(2) DEFAULT 13; v_sprawdz BOOLEAN NOT NULL := TRUE;
Typy zmiennych Typy znakowe 21 22 Typy skalarne typ o pojedynczej wartości Znaki i łańcuchy znaków Liczby Typy logiczne Data i czas Typy złożone typ złożony z kilku odrębnych wartości (np. rekord, kolekcja (tablice, listy), instancja typu obiektowego) Wskaźniki logiczny wskaźnik danej wartości lub kursora LOB identyfikator typu wielkoobiektowego (ang. large object) CHAR ([(max długość)] domyślnie 1; typ danych o stałej długości, pojemność określamy w bajtach: maksymalnie 32 767 bajtów w PL/SQL (w SQL 2000 bajtów) VARCHAR2 (max długość) - typ danych o zmiennej długości, maksymalnie 32 767 bajtów ( w SQL 4000 bajtów) Typy liczbowe i logiczne Data i czas 23 24 NUMBER [(precyzja, skala)] precyzja: wartości od 1 do 38, skala: -84 do 127, identyczny z typem NUMBER bazy danych Podtypy: REAL (63 cyfry), DOUBLE PRECISION (126 cyfr), FLOAT (126 cyfr) BINARY_DOUBLE, BINARY_FLOAT - od wersji Oracle 10g, typ zmiennoprzecinkowy o podwójnej (pojedynczej) precyzji PLS_INTEGER zakres od -2 147 483 648 do 2 147 483 647. Potrzebuje mniej przestrzeni na dysku niż NUMBER; bardziej efektywne wyliczenia BOOLEAN wartości TRUE, FALSE, NULL DATE podstawowy typ daty i czasu; przechowuje rok, miesiąc, dzień, godzinę, minutę, sekundę TIMESTAMP [(precyzja)] rozszerzenie typu DATE o ułamki sekund, w tym celu określa się precyzję 0-9, domyślnie 6 Przechowywanie okresów czasów: INTERVAL YEAR [(precyzja)] TO MONTH w latach i miesiącach INTERVAL DAY [(precyzja_dni)] TO SECOND [(precyzja_ułamki_sekund)] w dniach, minutach i sekundach
Typy zakotwiczone Instrukcje warunkowa 25 26 zmienna%type tabela.kolumna%type tabela%rowtype v_imie VARCHAR2(15); v_moje_imie v_imie%type; v_cena t_ksiazka.cena%type; ksiazki_record t_ksiazka%rowtype IF warunek THEN instrukcja-1; IF warunek-1 THEN instrukcja-1; ELSIF warunek-2 THEN instrukcja-2; instrukcja-3; IF warunek THEN instrukcja-1; instrukcja-2; Instrukcja warunkowa Instrukcja CASE 27 28... IF v_cena > 100 THEN RETURN (v_cena*1.1); ELSIF v_cena >= 50 THEN RETURN (v_cena*1.2); RETURN (v_cena*1.25);. Od wersji 9i, Alternatywa dla instrukcji warunkowych IF upraszczająca składnię CASE warunek WHEN kryterium1 THEN operacje1; WHEN kryterium2 THEN operacje2; [ operacje;] END CASE;
Instrukcja CASE - przykład CASE z wyszukiwaniem 29 30 selector NUMBER := 0; CASE selector WHEN 0 THEN dbms_output.put_line('case 0!'); WHEN 1 THEN dbms_output.put_line('case 1!'); dbms_output.put_line('no match!'); END CASE; / CASE [TRUE FALSE] WHEN warunek1 THEN operacje1; WHEN warunek2 THEN operacje2; [ operacje;] END CASE; Domyślnie poszukuje warunku prawdziwego (TRUE) CASE z wyszukiwaniem - przykład Pętla prosta 31 CASE WHEN 1 = 2 THEN dbms_output.put_line('case [1 = 2]'); WHEN 2 = 2 THEN dbms_output.put_line('case [2 = 2]'); dbms_output.put_line('no match'); END CASE; / Wynik działania CASE 32 LOOP instrukcje; EXIT [WHEN warunek];
Przykład CONTINUE [WHEN] 33 34 counter NUMBER; first BOOLEAN; LOOP IF NVL(counter,1) >= 1 THEN IF NOT NVL(first,TRUE) THEN counter := counter + 1; counter := 1; first := FALSE; dbms_output.put_line('iteration [' counter ']'); EXIT WHEN NOT counter < 3; / Od wersji 11g Dodatkowe sterowanie pętlą Działanie: natychmiast kończy aktualną iterację i przechodzi do pierwszego działania w pętli CONTINUE CONTINUE 35 36 counter NUMBER; first BOOLEAN; LOOP IF NVL(counter,1) >= 1 THEN IF NOT NVL(first,TRUE) THEN counter := counter + 1; counter := 1; first := FALSE; EXIT WHEN NOT counter < 3; IF counter = 2 THEN CONTINUE; dbms_output.put_line('index [' counter '].'); IF counter = 2 THEN CONTINUE; dbms_output.put_line('index [' counter '].'); CONTINUE WHEN counter = 2; dbms_output.put_line('index [' counter '].');
Instrukcje FOR i WHILE Instrukcja FOR - przykład 37 38 WHILE warunek LOOP instrukcje; FOR licznik IN [REVERSE] min..max LOOP instrukcje; v_licznik NUMBER(1) :=0; v_ostatni NUMBER(1); v_min NUMBER(1) := 1; v_max NUMBER(1) := 5; FOR i IN v_min..v_max LOOP Nie trzeba deklarować zmiennej i v_licznik := v_licznik + 1; v_ostatni := i; dbms_output.put_line( Ostatni indeks: TO_CHAR(v_ostatni). Liczba petli: TO_CHAR(v_licznik)); Instrukcja NULL Polecenie SELECT INTO 39 40 i NUMBER(2) :=0; IF i > 10 THEN dbms_output.put_line( i jest większe od 10 ); NULL; / NULL oznacza brak akcji SELECT lista_zmiennych INTO nazwa_zmiennej nazwa_rekordu FROM tabela [ WHERE warunki]; SELECT INTO przekazuje wartości uzyskane z bazy (lista_zmiennych) do zmiennych występujących w klauzuli INTO Polenie musi zwrócić jeden wiersz
SELECT INTO - przykład Pojęcie kursora 41 42 bonus NUMBER(8,2); SELECT salary * 0.10 INTO bonus FROM employees WHERE employee_id = 100; DBMS_OUTPUT.PUT_LINE('bonus = ' TO_CHAR(bonus)); / Udostępnia dane zwrócone przez zapytanie Otwarcie kursora to pobranie części bieżących danych, co oznacza, że modyfikacje danych po jego otwarciu nie będą widoczne w zbiorze, który zwrócił kursor. Dwa typy kursorów Niejawne Jawne Typy kursorów Atrybuty kursora SQL 43 44 Niejawne Jawne Nazwa atrybuty SQL%ROWCOUNT Opis Liczba wierszy, których dotyczyła ostatnia instrukcja SQL Deklarowane są dla wszystkich instrukcji DML oraz SELECT PL/SQL zarządza automatycznie kursorem niejawnym Parametry kursora: SQL%nazwa_parametru Deklarowane przez programistę Programista zarządza kursorem jawnym Parametry kursora: Nazwa_kursora%nazwa_p arametru SQL%FOUND SQL%NOTFOUND SQL%ISOPEN 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
45 Kursory niejawne - przykład n NUMBER; SELECT 1 INTO n FROM dual; dbms_output.put_line('selected [' SQL%ROWCOUNT ']'); ==================================================================== UPDATE system_user SET last_update_date = SYSDATE; IF SQL%FOUND THEN dbms_output.put_line('updated [' SQL%ROWCOUNT ']'); dbms_output.put_line('nothing updated!'); 46 Kursory niejawne - przykład v_usuniete VARCHAR2(30); DELETE FROM t_z_ksiazka WHERE id_zamowienia = ∥ v_usuniete := TO_CHAR(SQL%ROWCOUNT) rekordow usunietych. ; 47 Kursory jawne 48 Sterowanie kursorami jawnymi CURSOR nazwa_kursora [(parametr [, parametr] )] IS instrukcja_select; parametr ::= nazwa_parametru typ danych [{:= DEFAULT wyrażenie}] CURSOR kursor (p_isbn VARCHAR(10)) IS SELECT * FROM t_ksiazka WHERE isbn = p_isbn; NIE OPEN FETCH PUSTY? TAK CLOSE
Kursory jawne Atrybuty kursora jawnego 49 50.. ; OPEN nazwa_kursora [(parametr [, parametr]...)]; FETCH nazwa_kursora INTO zmienna [, zmienna...]; Nazwa atrybuty %ROWCOUNT %FOUND %NOTFOUND %ISOPEN Opis 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 CLOSE nazwa_kursora; 51 Kursor jawny - przykład CURSOR k_cursor IS SELECT * FROM t_z_ksiazka WHERE isbn = 1; k_record t_z_ksiazka%rowtype; v_ilosc t_z_ksiazka. ilosc %TYPE := 0; OPEN k_cursor; LOOP FETCH k_cursor INTO k_record; IF k_cursor%notfound THEN EXIT; v_ilosc := v_ilosc + k_record.ilosc; dbms_output.put_line(k_cursor%rowcount); dbms_output.put_line(v_ilosc); CLOSE k_cursor; 52 Pętla kursorowa FOR FOR nazwa_rekordu IN nazwa_kursora LOOP instrukcja-1; instrukcja-2;. Niejawne instrukcje OPEN, FETCH, CLOSE zmienna nazwa_rekordu zadeklarowana niejawnie
53 Pętla kursorowa FOR - przykład CURSOR k_cursor (p_zam t_zamowienie.id_zamowienia%type) IS SELECT * FROM t_z_ksiazka WHERE id_zamowienia = p_zam; FOR i IN k_cursor(1) LOOP dbms_output.put_line(i.isbn); 54 Pętla kursorowa FOR- przykład CURSOR a_cursor IS SELECT * FROM t_autor; ======== Metoda 1 ======================== FOR i IN a_cursor LOOP dbms_output.put_line(i.nazwisko); ======== Metoda 2 ======================== FOR i IN (SELECT * FROM t_autor) LOOP dbms_output.put_line(i.nazwisko); Klauzula FOR UPDATE Klauzula WHERE CURRENT OF 55 CURSOR nazwa_kursora [(parametr, )] IS instrukcja_select [FOR UPDATE [OF (lista_kolumn) [NOWAIT]]; Służy do blokowania rekordów po otwarciu kursora Rekordy są dostępne dla innych sesji, ale tylko w trybie do odczytu Gdy użyjemy NOWAIT, przy otwieraniu kursora program zostanie zamknięty, jeśli nie może utworzyć blokady na wyłączność. 56 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;
57 Klauzula 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 58 Literatura McLaughlin, Michael, Oracle Database 11g PL/SQL programming, Oracle Press, 2008 www.oracle.com