PODSTAWY BAZ DANYCH 13. PL/SQL 1
Wprowadzenie do języka PL/SQL Język PL/SQL - rozszerzenie SQL o elementy programowania proceduralnego. Możliwość wykorzystywania: zmiennych i stałych, instrukcji sterujących IF, pętli, kursorów, wyjątków. Podstawowa jednostka w PL/SQL: blok - grupuje logicznie powiązane deklaracje i wyrażenia. 2
Struktura bloku (programu) PL/SQL Struktura bloku: część deklaracji zmiennych i stałych opcjonalna część wykonywalna część obsługi wyjątków opcjonalna [ DECLARE ] [ EXCEPTION ] -- deklaracje zmiennych, stałych i kursorów -- wyrażenia -- obsługa wyjątków 3
Komentarze Komentarz zawierający jedną linię - znaki -- Komentarz wieloliniowy - znaki /*... */ Komentarze nie mogą być zagnieżdżone -- Wykonaj procedurę X X; /* Teraz wykonaj procedurę Y i zakończ działanie program */ Y; 4
Podstawowe typy Typ numeryczny NUMBER[(precyzja, skala)] Typy znakowe CHAR[(maks_długość)] VARCHAR2(maks_długość) Inne typy BOOLEAN - typ logiczny, wartości: TRUE, FALSE, NULL DATE data... typy zdefiniowane przez programistę. 5
Zmienne Zmienne zmienne proste (np. numeryczne, znakowe, logiczne, ) zmienne złożone zmienne rekordowe tablice obiekty (ang. objects) /*rozszerzenie obiektowe Oracle */ 6
Deklarowanie zmiennych i stałych DECLARE nazwa_zmiennej typ; Przykłady. DECLARE licznik number(4); znak char(1); flaga boolean := TRUE; osoba osoby.nazwisko%type; Nadanie wartości zmiennym: licznik := 10; znak := 'A'; flaga := TRUE; osoba := 'Lis'; Definiowanie stałych: DECLARE nazwa_zmiennej CONSTANT typ := wartość; 7
Rekordy - przykład DECLARE TYPE osoba_dane IS RECORD ( nazwisko VARCHAR2(20), imie VARCHAR2(20) ); /* typ rekordowy */ p osoba_dane ; /* zmienna typu rekordowego */... p.nazwisko := 'Nowak'; /* dostęp do pól rekordu */ p.imie:= 'Jan';... 8
Instrukcja SELECT INTO... DECLARE v_nazwisko VARCHAR2(20); v_imie1 VARCHAR2(20); SELECT nazwisko, imie1 INTO FROM v_nazwisko, v_imie1 osoby WHERE id = 1; Zapytanie w języku SQL musi zwrócić dokładnie jeden wiersz. Klauzula INTO wskazuje na zmienne, które zostaną wypełnione wartościami odczytanymi przez zapytanie. 9
Instrukcja warunkowa IF... IF warunek 1 THEN... /* wykonaj polecenia */ [ ELSIF warunek 2 THEN... /* wykonaj polecenia */...................... ] [ ELSIF warunek n THEN... ] /* wykonaj polecenia */ [ ELSE... ] /* wykonaj polecenia */ END IF; Operatory logiczne: OR, AND, NOT. IF (x = 1 AND y) OR (x = 2 AND NOT y) THEN... END IF; 10
Pętle Pętla podstawowa (nieskończona) Pętla LOOP /* polecenia */ [ EXIT WHEN warunek; ] /* polecenia */ END LOOP; WHILE warunek LOOP /* polecenia */ END LOOP; 11
Pętle Pętla numeryczna FOR FOR zmienna_licznikowa IN [REVERSE] x..y LOOP /* polecenia */ END LOOP; 12
Kursor Każde zapytanie SQL umieszczone w programie PL/SQL jest wykonywane w tzw. obszarze roboczym (kursor). Serwer bazy danych wykorzystuje ten obszar (kursor) do przechowywania danych otrzymanych w wyniku zapytania oraz do przechowywania innych dodatkowych informacji dotyczących stanu wykonywanego zapytania. Kursor (ang. cursor) jest konstruktorem PL/SQL umożliwiającym: nadanie nazwy temu obszarowi, dostęp do niego, pobranie z niego danych, kontrolę procesu przetwarzania danych. 13
Operacje na kursorze Podstawowe operacje na kursorze: deklaracja kursora otwarcie kursora pobranie wartości z kursora zamknięcie kursora CURSOR nazwa [(parametr_1, parametr_2,...)] IS zapytanie; OPEN nazwa [(wart_param_1, wart_param_2,..)]; FETCH nazwa INTO lista_zmiennych; CLOSE nazwa; 14
Kursor - Przykład DECLARE CURSOR pracownik_kursor IS SELECT id_os, nazwisko, imie1 FROM osoby; Osoba_id osoby.id_os%type; osoba_nazwisko osoby.nazwisko%type; osoba_imie1 osoby.imie1%type; pracownik_dane pracownik_kursor%rowtype; OPEN pracownik_kursor; FETCH pracownik_kursor INTO osoba_id, osoba_nazwisko, osoba_imie1; FETCH pracownik_kursor INTO pracownik_dane; CLOSE pracownik_kursor; 15
Kursor Pętla FOR z kursorem lub z podzapytaniem Pętla FOR z kursorem FOR zmienna_rekord IN kursor LOOP /* polecenia */ END LOOP; nie wymaga otwarcia ani zamknięcia kursora. Nie wymaga również deklaracji zmiennej zmienna_rekord. Pętla FOR z podzapytaniem FOR zmienna_rekord IN (podzapytanie_sql) LOOP /* polecenia */ END LOOP; W celu iteracyjnego przetwarzania wyników zapytania nie jest konieczne jawne deklarowanie kursora. 16
Procedury i funkcje składowane W PL/SQL można tworzyć własne procedury i funkcje. Cechy: przechowywane w bazie danych, postać skompilowana - zwiększenie szybkości działania, ułatwiają pielęgnowanie aplikacji, mogą być współdzielone przez wielu użytkowników. Procedury i funkcje można gromadzić w pakietach. 17
Procedury i funkcje składowane Przykład 1. Przykład funcji. DROP FUNCTION f; CREATE OR REPLACE FUNCTION f(x NUMBER) RETURN NUMBER IS y NUMBER; y:=x*x; RETURN y; / Przykład 2. Przykład wykorzystania funkcji w bloku PL/SQL. DECLARE wynik NUMBER; wynik:= f(4); DBMS_OUTPUT.PUT_LINE(wynik); DBMS_OUTPUT.PUT_LINE(f(4)); / 18
Procedury i funkcje składowane Przykład 3. Przykład procedury. DROP PROCEDURE p; CREATE OR REPLACE PROCEDURE p(x IN NUMBER, w IN OUT NUMBER) IS y NUMBER; y:=x*w; w:=y; / Przykład 4. Przykład wykorzystania procedury w bloku PL/SQL. DECLARE wynik NUMBER; wynik:=6; p(4,wynik); DBMS_OUTPUT.PUT_LINE(wynik); / 19
PODSTAWY BAZ DANYCH 14. Wyzwalacze (database triggers) 20
Wyzwalacze Wyzwalacze bazy danych (database triggers) - procedury składowane w bazie danych w powiązaniu z konkretną relacją (tabelą) i są automatycznie uruchamiane w momencie wykonania polecenia SQL dotyczącego tej relacji. Z relacją może być związanych wiele rożnych wyzwalaczy (z pewnymi ograniczeniami), ale pojedynczy wyzwalacz może być związany tylko z jedną relacją. 21
Wyzwalacze Moment uruchamiania W zależności od czasu uruchamiania wyzwalaczy możemy je podzielić na dwie grupy: AFTER - wykonywane po wykonaniu polecenia SQL. BEFORE - wykonywane przed wykonaniem polecenia SQL; Uruchamiane są przy wykonywaniu poleceń SQL: INSERT, UPDATE, DELETE. 22
Wyzwalacze - budowa CREATE [ OR REPLACE ] TRIGGER nazwa { AFTER BEFORE } { DELETE INSERT UPDATE } [ OF lista_atrybutów ] ON nazwa_relacji [ FOR EACH ROW [ WHEN warunek ] ] [ DECLARE /* deklaracja zmiennych,... */ ] /* ciało wyzwalacza */ 23
Wyzwalacze - ograniczenia W ciele wyzwalacza można stosować polecenia SQL, PL/SQL i wywoływać podprogramy (procedury i funkcje). Ograniczenia: nie można stosować poleceń DDL; nie można stosować poleceń sterujących transakcjami COMMIT, ROLLBACK, SAVEPOINT; wywoływać podprogramy z wyżej wymienionymi poleceniami. 24
Wyzwalacze - Przykład Osoby Id_os Nazwisko Imie1 Imie2 D_ur Plec 1 Kowalski Jan Adam 11-10-1970 M 2 Nowak Anna 01-10-1980 K 3 Norek Tadeusz 05-09-1980 M Zatrudnienia Id_z Id_os Id_w Id_s Od Do Pensja 1 2 1 1 01-10-1990 1200 2 3 3 2 01-10-2000 30-10-2001 1600 3 3 3 2 01-11-2001 2000 25
Wyzwalacze - przykład Przykład. CREATE OR REPLACE TRIGGER test1 AFTER UPDATE ON zatrudnienia DBMS_output.put_line('placa została zmieniona'); Komunikat będzie wyświetlony przy zmianie dowolnego atrybutu pierwszej aktualizowanej krotki. 26
Wyzwalacze - przykład Przykład. CREATE OR REPLACE TRIGGER test2 AFTER UPDATE OF pensja ON zatrudnienia DBMS_output.put_line('placa została zmieniona'); Komunikat będzie wyświetlony przy zmianie tylko atrybutu pensja pierwszej aktualizowanej krotki. 27
Wyzwalacze - przykład Przykład. CREATE OR REPLACE TRIGGER test3 AFTER UPDATE OF pensja ON zatrudnienia FOR EACH ROW DBMS_output.put_line('placa została zmieniona'); Komunikat będzie wyświetlony przy zmianie tylko atrybutu pensja każdej aktualizowanej krotki. 28
Wyzwalacze - przykład Przykład. CREATE OR REPLACE TRIGGER test4 AFTER UPDATE OF pensja ON pensje FOR EACH ROW WHEN placa>1000 DBMS_output.put_line('placa została zmieniona'); Komunikat będzie wyświetlony przy zmianie tylko atrybutu pensja każdej aktualizowanej krotki, w której wartość atrybutu >1000. 29
Wyzwalacze Ten sam wyzwalacz może być uruchamiany przez każde polecenie DML: INSERT, UPDATE, DELETE lub ich dowolną kombinację. W tym samym momencie nie może być uruchamianych więcej jak jeden wyzwalacz. 30
Wyzwalacze CREATE [ OR REPLACE ] TRIGGER nazwa { AFTER BEFORE } DELETE OR INSERT OR UPDATE [ OF lista_atrybutów] ON nazwa_relacji [ FOR EACH ROW [ WHEN warunek ] ] [ DECLARE /* deklaracja zmiennych,... */ ] /* ciało wyzwalacza */ 31
Wyzwalacze W ciele i w warunku można korzystać z dwóch kwalifikatorów (qualifier) NEW i OLD, które przyjmują nową i starą wartość krotki: NEW.nazwa_atrybutu OLD.nazwa_atrybutu Dla wyzwalacza uruchamianego poleceniem INSERT wartość kwalifikatora OLD przyjmuje wartość NULL dla każdego atrybutu krotki. Dla wyzwalacza uruchamianego poleceniem DELETE wartość kwalifikatora NEW przyjmuje wartość NULL dla każdego atrybutu krotki. 32
Wyzwalacze Dla wyzwalacza uruchamianego poleceniem UPDATE wyzwalacz ma dostęp do starej i nowej wartości atrybutu. Odwołania do kwalifikatorów NEW i OLD w klauzuli WHEN nie są poprzedzone : NEW.nazwa_atrybutu w pozostałych odwołaniach poprzedzone jest :. :NEW.nazwa_atrybutu 33
Wyzwalacze - przykład Przykład. Poprawianie pisowni. CREATE OR REPLACE TRIGGER test5 BEFORE INSERT ON osoby FOR EACH ROW :NEW.nazwisko:=InitCap(:NEW.nazwisko); :NEW.imie1:=InitCap(:NEW.imie1); :NEW.imie2:=InitCap(:NEW.imie2); 34
Wyzwalacze - przykład Przykład. Wyzwalacz nadający kolejny numer pobrany z licznika licz_osoby wprowadzanej nowej krotki do relacji osoby. CREATE OR REPLACE TRIGGER test6 BEFORE INSERT ON osoby SELECT licz_osoby.nextval INTO :NEW.id_os FROM DUAL; 35
Wyzwalacze - przykład Przykład. Przy wprowadzaniu nowej krotki do relacji zatrudnienia zrobić aktualizację poprzedniej pensji (atrybut do). CREATE OR REPLACE TRIGGER bi_zatrudnienia BEFORE INSERT ON zatrudnienia FOR EACH ROW SELECT licz_zatrudnienia.nextval INTO :NEW.id_z FROM DUAL; :NEW.od:=SYSDATE; UPDATE zatrudnienia SET do=sysdate-1 WHERE id_os=:new.id_os AND do IS NULL; 36
Wyzwalacze - przykład Przykład. CREATE OR REPLACE TRIGGER test7 BEFORE INSERT OR UPDATE ON osoby FOR EACH ROW :NEW.nazwisko:=InitCap(:NEW.nazwisko); :NEW.imie1:=InitCap(:NEW.imie1); :NEW.imie2:=InitCap(:NEW.imie2); 37
Wyzwalacze - przykład Przykład. CREATE OR REPLACE TRIGGER test8 BEFORE INSERT OR UPDATE ON osoby FOR EACH ROW WHEN NEW.nazwisko <> InitCap(NEW.nazwisko)... 38
Wyzwalacze - przykład CREATE OR REPLACE TRIGGER test9 BEFORE INSERT ON zatrudnienia FOR EACH ROW IF :NEW.pensja < 500 THEN DBMS_output.put_line('mało????????????'); END IF; 39
Wyzwalacze Ciało wyzwalacza, które może być uruchamiane przez więcej niż jedno polecenie DML, może zawierać tzw. predykaty warunkowe: inserting, deleting, updating. 40
Wyzwalacze CREATE [ OR REPLACE ] TRIGGER nazwa {AFTER BEFORE} DELETE OR INSERT OR UPDATE [OF atrybuty] ON nazwa_relacji [ FOR EACH ROW [ WHEN warunek ] ] DECLARE... IF INSERTING THEN...END IF; IF UPDATING [lista_atrybutów] THEN...END IF; IF DELETING THEN...END IF;... 41
Wyzwalacze Predykaty można łączyć za pomocą AND, OR NOT w tej samej klauzuli IF IF UPDATING OR DELETING THEN... END IF; IF UPDATING( lista_atrybutów 1 ) OR UPDATING( lista_atrybutów 2 ) THEN... END IF; 42
Wyzwalacze - przykład CREATE OR REPLACE TRIGGER test10 BEFORE INSERT OR UPDATE ON osoby FOR EACH ROW IF INSERTING THEN :NEW.nazwisko:=InitCap(:NEW.nazwisko); :NEW.imie1:=InitCap(:NEW.imie1); :NEW.imie2:=InitCap(:NEW.imie2); END IF; IF UPDATING('nazwisko') THEN :NEW.nazwisko:=InitCap(:NEW.nazwisko); END IF; 43
Wyzwalacze Zmiana wyzwalacza ALTER TRIGGER nazwa DISABLE [ENABLE]; ALTER TABLE nazwa_relacji DISABLE [ENABLE] ALL TRIGGERS; Kasowanie wyzwalaczy DROP TRIGGER nazwa; Informacje o wyzwalaczach można znaleźć w widokach: SELECT * FROM USER_TRIGGERS; 44