ZSBD PL/SQL CZĘŚĆ 3 Wykład 5 Prowadzący: dr Paweł Drozda
Program wykładu dr P. Drozda Pakiety Wyzwalacze
Pakiety dr P. Drozda Obiekt logiczny schematu bazy danych grupujący logicznie powiązane elementy PL/SQL – typy, zmienne, podprogramy (procedury, funkcje) Skład pakietu: Specyfikacja Zawartość/ciało Specyfikacja zawiera deklaracje typów, zmiennych, stałych, kursorów podprogramów, do których można się odwoływać z zewnątrz pakietu (zadeklarowane elementy są publiczne) Zawartość zawiera instrukcje dla kursorów i podprogramów zadeklarowanych w specyfikacji oraz może definiować dodatkowe elementy niewidoczne na zewnątrz Pozwala wiele elementów załadować na raz
Zalety pakietów dr P. Drozda Zgrupowane logicznie powiązane elementy w jednym miejscu Ukrycie informacji Z zewnątrz widoczna specyfikacja Konstrukcje w zawartości niedostępne do wglądu Kompilacja oddzielnie specyfikacji i zawartości Trwałość danych publicznych – zmienne, kursory – przez całą sesję użytkownika Lepsza wydajność – cały pakiet wczytywany jest raz dla wszystkich użytkowników Przeciążanie procedur, funkcji
Elementy deklaracji pakietów dr P. Drozda Specyfikacja Zmienna; Procedura A deklaracja; Funkcja B deklaracja; … Zawartość Zmienna1; Procedura C deklaracja … Procedura A deklaracja BEGIN …; END; Funkcja B deklaracja BEGIN … END; Publiczny Prywatny
Widoczność elementów w pakietach dr P. Drozda Zmienna widoczna wszędzie Zmienna1 widoczna tylko w obrębie Zawartości Zmienna2 widoczna tylko w procedurze A Procedura C widoczna tylko wewnątrz Zawartości – może być wykorzystana w procedurze A i funkcji C Specyfikacja Zmienna; Procedura A deklaracja; Funkcja B deklaracja; … Zawartość Zmienna1; Procedura C deklaracja … Procedura A deklaracja BEGIN Zmienna2; …; END; Funkcja B deklaracja BEGIN … END;
Tworzenie pakietów – składnia dr P. Drozda CREATE [OR REPLACE] PACKAGE nazwa AS|IS deklaracja typów publicznych; deklaracja zmiennych; specyfikacja podprogramów; END [nazwa]; CREATE [OR REPLACE] PACKAGE BODY nazwa AS|IS odpowiednie deklaracje, tworzenie zawartości podprogramów; Zmienne domyślnie inicjowane na NULL Wszystkie elementy zadeklarowane widoczne są dla użytkowników mających prawa dostępu do pakietu
Przykład – tworzenie pakietu dr P. Drozda CREATE OR REPLACE PACKAGE pracownicy IS numer NUMBER:= 111; CURSOR nazwisko IS SELECT last_name FROM employees; PROCEDURE nazwisko (id number); FUNCTION zarobki (id number) RETURN NUMBER; END pracownicy;
Przykład ciąg dalszy dr P. Drozda CREATE PACKAGE BODY Pracownicy IS Jakaszmienna VARCHAR2(2); PROCEDURE nazwisko (id number) IS name employees.last_name%TYPE; BEGIN SELECT last_name INTO name FROM employees WHERE employee_id = id; DBMS_OUTPUT.PUT_LINE(last_name); END nazwisko; … END Pracownicy;
Przykład pakietu bez zawartości dr P. Drozda CREATE PACKAGE stale IS km2mile CONSTANTNUMBER := ; mile2km CONSTANTNUMBER := ; jard2metr CONSTANTNUMBER := ; metr2jard CONSTANTNUMBER := ; END stale; CREATE OR REPLACE FUNCTION zamiana(km NUMBER) RETURN NUMBER IS BEGIN RETURN (km*stale.km2mile); END;
Wywołanie elementów pakietu dr P. Drozda Z linii komend EXECUTE nazwapakietu.nazwaElementu; EXECUTE Pracownicy.nazwisko(100); Gdy ze schematu innego użytkownika EXECUTE HR.Pracownicy.nazwisko(100); Wewnątrz bloku Tak samo jak wywołanie normalne elementów – tylko poprzedzone nazwą pakietu do którego należą; gdy pakiet z innego schematu – dodatkowo na początku nazwa schematu
Przeglądanie, usuwanie pakietów dr P. Drozda Informacje o pakietach znajdują się w user_source SELECT text FROM user_source WHERE type=PACKAGE | PACKAGE BODY; DROP PACKAGE nazwa; DROP PACKAGE BODY nazwa;
Reguły tworzenia pakietów dr P. Drozda Specyfikacja pakietu tworzona przed zawartością Odwołanie w podprogramie do innego elementu (np. w procedurze do funkcji) możliwe tylko, gdy ta funkcja została wcześniej zadeklarowana (jeśli publiczna – nie ma problemu, jeśli prywatna trzeba pilnować) Umieszczanie w specyfikacji tylko niezbędnych elementów (widocznych dla wszystkich)
Przeciążanie podprogramów dr P. Drozda Możliwość zadeklarowania procedury/funkcji z tą samą nazwą więcej niż raz Konieczność rozróżnienia za pomocą parametrów (ich liczby, rodzin typów lub kolejności) Możliwość nadpisania lokalnych podprogramów, z pakietu Nie można przeciążać: Gdy parametry są w tej samej rodzinie typów (np. NUMBER i DECIMAL) Gdy są podtypami tej samej rodziny (VARCHAR i STRING są podtypami VARCHAR2) Gdy funkcje różnią się tylko zwracanym typem
Przykład przeciążania dr P. Drozda CREATE OR REPLACE PACKAGE dept IS PROCEDURE add_dept(id NUMBER, name VARCHAR2 :=edu, location VARCHAR); PROCEDURE add_dept(name VARCHAR2); END dept;
Pakiet wbudowany STANDARD dr P. Drozda Zawiera najczęściej wykorzystywane funkcje (np. ROUND, TO_CHAR, NVL, LENGTH, etc.) Funkcje wywoływane bez konieczności poprzedzania nazwą pakietu Gdy jakaś funkcja zostanie przeciążona – konieczność odwołania poprzez nazwę pakietu
Blok inicjalizacyjny pakietu dr P. Drozda Na koniec zawartości można dodać blok wykonywany raz Uruchomiany raz w momencie ładowania pakietu do sesji użytkownika Służy do dokładniejszej inicjalizacji elementów pakietu Przykład: CREATE PACKAGE inic IS kasa NUMBER; … CREATE PACKAGE BODY inic IS … BEGIN SELECT salary INTO kasa FROM employees WHERE employee_id =120; END inic;
Wyzwalacze dr P. Drozda Bloki składowane w bazie, które są uruchomiane w momencie wystąpienia jakiegoś zdarzenia Wyzwalacze definiowane są na perspektywie, tabeli, schemacie użytkownika bądź na całej bazie Możliwości uruchomienia wyzwalacza: Wystąpienie DML (INSERT, UPDATE, DELETE) Wystąpienie DDL (CREATE, ALTER, DROP) Wystąpienie operacji na bazie danych takich jak SERVERERROR, LOGON, LOGOFF, SHUTDOWN, STURTUP
Wyzwalacze dla DML dr P. Drozda Możliwe instrukcje wywołujące wyzwalacz: INSERT UPDATE [OF kolumna] DELETE Może być więcej niż jedna instrukcja INSERT OR DELETE INSERT OR UPDATE OR DELETE Zawartość wyzwalacza określa jakie akcje zostaną podjęte w momencie użycia wyzwalacza (może być blokiem, odwołaniem do procedur)
Tworzenie wyzwalacza – składnia dr P. Drozda CREATE TRIGGER nazwa BEFORE | AFTER | INSTEAD OF INSERT | UPDATE | DELETE ON nazwaObiektu [REFERENCING OLD AS old /NEW AS new] [FOR EACH ROW WHEN (condition)] [DECLARE] BEGIN … END;
Wyzwalacz przykład dr P. Drozda CREATE OR REPLACE TRIGGER godziny BEFORE INSERT ON employees BEGIN IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR (TO_CHAR(SYSDATE,'HH24:MI') NOT BETWEEN '08:00' AND '18:00') THEN RAISE_APPLICATION_ERROR(-20500,nie można nic wstawić przecież nie pracujesz'); END IF; END;
Odpalenie wyzwalacza raz/wiele dr P. Drozda Gdy zapytanie operuje na jednym wierszu – trigger odpalany raz (obojętnie czy z opcją każdego wiersza czy bez opcji) np. INSERT INTO departments(department_id) VALUES (3); Gdy zapytanie dotyczy wielu wierszy – z opcją FOR EACH ROW wyzwalacz odpalany wiele razy, bez opcji – tylko raz UPDATE employees SET salary=salary*1.2 WHERE department_id=50;
Przykład – różne instrukcje DML dr P. Drozda CREATE TRIGGER godziny BEFORE INSERT OR UPDATE OR DELETE ON employees BEGIN IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR (TO_CHAR(SYSDATE,'HH24:MI') NOT BETWEEN '08:00' AND '18:00') THEN IF INSERTING THEN RAISE_APPLICATION_ERROR(-20500,nic nie wstawic'); ELSE IF DELETING THEN RAISE_APPLICATION_ERROR(-20502,nie wyrzucaj'); ELSEIF UPDATING THEN RAISE_APPLICATION_ERROR(-20503,zostalo zmodyfikowane wczoraj); END IF; END;
Wyzwalacz wierszowy - przykład dr P. Drozda CREATE TRIGGER widelki BEFORE INSERT OR UPDATE OF salary ON employees FOR EACH ROW BEGIN IF NOT (:NEW.job_id IN (AD_PRES,AD_VP)) AND :NEW.SALARY >15000 THEN RAISE APPLICATION_ERROR(-20202, za dużo chcesz zarabiać); END;
Przykład z opcją WHEN dr P. Drozda CREATE TRIGGER zarobki BEFORE INSERT OR UPDATE OF salary ON employees FOR EACH ROW WHEN (NEW.job_id = SA_REP) BEGIN IF INSERTING THEN :NEW.commission_pct := 0; ELSEIF :OLD.commission_pct THEN :NEW.commission_pct := 0; ELSE :NEW.commission_pct :=:OLD.commission_pct +0.05; END;