PL/SQL Zaawansowane tematy PL/SQL Piotr Medoń
Cele Omówienie transakcji bazodanowych Omówienie obsługi wyjątków Zarządzanie perspektywami Tworzenie i usuwanie sekwencji Budowa wyzwalaczy 2
Transakcje bazodanowe Transakcja zaczyna się wraz z pierwszą instrukcją DML (INSERT lub UPDATE lub DELETE) Transakcja kończy się i jest zatwierdzana, gdy użytkownik wyda polecenie COMMIT, lub wyda instrukcje DDL (np. CREATE TABLE, TRUNCATE TABLE ) Transakcja kończy się i jest wycofywana, gdy użytkownik wyda polecenie ROLLBACK, rozłączy się z bazą danych, lub nastąpi awaria bazy danych 3
Transakcje bazodanowe Zmiany danych wykonane za pomocą instrukcji DML są widoczne dla sesji użytkownika od razu Zmiany są widoczne dla sesji innych użytkowników dopiero w momencie zatwierdzenia transakcji INSERT COMMIT Drugi użytkownik widzi wynik operacji INSERT dopiero po operacji COMMIT 4
Transakcje bazodanowe Baza danych w przypadku wycofania transakcji przywraca oryginalne dane. To znaczy, że po sekwencji instrukcji: INSERT UPDATE DELETE ROLLBACK; nie pozostanie żaden ślad w systemie! 5
Transakcje bazodanowe Planowanie transakcji bazodanowej Transakcje zatwierdzamy instrukcją COMMIT, gdy zapisane dane są spójne, Pisząc kod mamy na uwadze, że równolegle z jego wykonaniem wykonywać się będą inne sesje i transakcje, Pisząc kod zawsze musimy wziąć pod uwagę możliwość wystąpienia awarii. 6
Obsługa wyjątków 7
Obsługa wyjątków Wyjątki pojawiają się, gdy z powodu niepoprawnej sytuacji program nie może być dalej przetwarzany. Wykonywany program Zaistnienie okoliczności uniemożliwiającej dalszą pracę programu WYJĄTEK
Przykład braku obsługi wyjątków DECLARE a NUMBER := 0; b NUMBER; c NUMBER; BEGIN b := 20; c := b / a; DBMS_OUTPUT.PUT_LINE(c); END; Po wystąpieniu wyjątku przetwarzanie programu zostaje przerwane
Przykład sekcji obsługi wyjątków DECLARE a NUMBER := 0; b NUMBER; c NUMBER; BEGIN b := 20; c := b / a; DBMS_OUTPUT.PUT_LINE(c); EXCEPTION WHEN ZERO_DIVIDE THEN ROLLBACK; Sekcja obsługi wyjątków pozwala przechwycić sterowanie w przypadku wystąpienia błędu DBMS_OUTPUT.PUT_LINE( Nie można dzielić przez 0 ); END;
Konstrukcja sekcji obsługi wyjątków Sekcje obsługi wyjątków budujemy bezpośrednio przed instrukcją END kończącą blok instrukcji PL/SQL EXCEPTION WHEN wyjątek THEN obsługa_wyjątku1; WHEN wyjątek THEN obsługa_wyjątku1; WHEN OTHERS THEN obsługa pozostałych wyjątków END; 11
Obsługa wyjątków Sekcje obsługi wyjątków możemy budować w blokach anonimowych, procedurach, funkcjach i wyzwalaczach bazodanowych DECLARE BEGIN EXCEPTION WHEN NO_DATA_FOUND THEN END; PROCEDURE test IS BEGIN EXCEPTION WHEN NO_DATA_FOUND THEN END; 12
Obsługa wyjątków Sekcje obsługi wyjątków możemy budować również w blokach PL/SQL zawartych w innych blokach PL/SQL BEGIN BEGIN SELECT INTO FROM WHERE.; EXCEPTION WHEN NO_DATA_FOUND THEN END; END; 13
Obsługa wyjątków Wyjątki dzielimy na wyjątki systemu i wyjątki zdefiniowane przez użytkownika Wyjątki systemu pojawiają się, gdy baza danych Oracle odmawia wykonania niektórych operacji. Przykłady wyjątków systemu: Kod wyjątku ZERO_DIVIDE NO_DATA_FOUND Opis Dzielenie przez zero Nie znaleziono danych TOO_MANY_ROWS Pobrano zbyt dużo wierszy INVALID_NUMBER Podana wartość nie jest poprawną liczbą
Obsługa wyjątków W celu obsłużenia wyjątków, czyli sytuacji niepoprawnych, budujemy sekcje obsługi wyjątków Kod obsługi wyjątku powinien: W miarę możliwości przywrócić poprawny stan systemu: wycofać transakcję poleceniem ROLLBACK, zamknąć otwarte kursory, oznaczyć nieprzetworzone lub przetworzone dane. Zawiadomić operatora o błędzie i udostępnić ilość informacji wystarczającą do diagnozy błędu (kod błędu, dokładną lokalizację błędu, informacje na temat przetwarzanego rekordu)
Obsługa wyjątków W sekcji obsługi błędów możemy wykorzystać następujące funkcje: Funkcja zwracająca kod błędu: sqlcode Funkcja zwracająca komunikat błędu: sqlerrm Funkcja zwracająca miejsca podniesienia wyjątku: dbms_utility.format_error_backtrace 16
Przykład stosowania funkcji zwracających informacje o wyjątkach EXCEPTION WHEN OTHERS THEN dbms_output.put_line ( Kod: sqlcode); dbms_output.put_line ( Komunikat: sqlerrm); dbms_output.put_line ( Wyjatek podniesiony: dbms_utility.format_error_backtrace); END; 17
Obsługa wyjątków Instrukcja RAISE umożliwia podniesienie wyjątku ręcznie - przez programistę. Na przykład poniższa instrukcja podnosi wyjątek NO_DATA_FOUND: RAISE NO_DATA_FOUND; 18
Obsługa wyjątków Instrukcja RAISE bez nazwy wyjątku, użyta w bloku obsługi wyjątków podnosi wyjątek, który wywołał blok obsługi wyjątków EXCEPTION WHEN OTHERS THEN Dbms_output.put_line( Tu był wyjątek, ale podniesiemy go dalej ); RAISE; END; 19
Wyjątki zdefiniowane przez użytkownika Wyjątki zdefiniowane przez użytkownika są elementem logiki programu Wyjątki definiuje się w sekcji deklaracji Wyjątki takie są podnoszone tylko za pomocą funkcji RAISE. e_budzet_zostal_przekroczony EXCEPTION; 20
Wyjątki zdefiniowane przez użytkownika Przkład wykorzystania wyjątków zdefiniowanych przez użytkownika DECLARE e_budzet_zostal_przekroczony EXCEPTION; BEGIN; -- IF ln_koszty>ln_budzet THEN RAISE e_budzet_zostal_przekroczony; END; EXCEPTION WHEN e_budzet_zostal_przekroczony THEN... 21
Propagacja obsługi wyjątku Gdy wyjątek nie jest obsługiwany przez sekcję obsługi wyjątków wykonywanego aktualnie bloku, jest propagowany do kolejnych bloków zewnętrznych, aż zostanie znaleziona odpowiednia sekcja obsługi wyjątków. 22
23
Propagacja obsługi wyjątku BEGIN BEGIN c:=a/0; EXCEPTION WHEN NO_DATA_FOUND THEN END; EXCEPTION WHEN ZERO_DIVIDE THEN END; 24
Propagacja obsługi wyjątku BEGIN BEGIN EXCEPTION WHEN NO_DATA_FOUND THEN END; BEGIN EXCEPTION WHEN ZERO_DIVIDE THEN END; EXCEPTION WHEN NO_DATA_FOUND THEN END; 25
Propagacja obsługi wyjątku PROCEDURE sprawdz_podwozie EXCEPTION WHEN ZERO_DIVIDE DECLARE EXCEPTION WHEN NO_DATA_FOUND WHEN ZERO_DIVIDE END; PROCEDURE sprawdz_kolo EXCEPTION WHEN TOO_MANY_ROWS WHEN INVALID_NUMBER PROCEDURE sprawdz_samochod EXCEPTION WHEN INVALID_NUMBER FUNCTION cisnienie_w_kole EXCEPTION WHEN INVALID_NUMBER END; 26
Spis obiektów bazodanowych Obiekt Tabela Perspektywa Sekwencja Synonim Indeks Procedura składowana Funkcja składowana Pakiet składowany Wyzwalacz Opis Obiekt przechowujący dane Obiekt reprezentujący zapytanie Generator kolejnych liczb Umożliwia nadawanie dodatkowych nazw obiektom Przyspiesza wykonanie niektórych zapytań Obiekt wykonujący pewne operacje Obiekt wykonujący pewne operacje, zwracający wynik pracy Kontener na procedury i funkcje Kod uruchamiany podczas operacji DML 27
Tworzenie tabel Nazwy tabel i kolumn: Muszą zaczynać się od litery Muszą mieć długość od 1 do 30 znaków Dozwolonymi znakami są A Z, a z, 0 9, _, $, oraz # Małe i duże litery nie są rozróżniane Nie mogą być żadnym słowem kluczowym Nie mogą się dublować 28
Tworzenie tabel Tabelę tworzymy za pomocą instrukcji: CREATE TABLE nazwa_tabeli ( kolumna typ [, kolumna typ [,...]] ); Na przykład: CREATE TABLE pracownicy ( id NUMBER, imie VARCHAR2(60), data_zatrudnienia DATE ); 29
Tworzenie tabel Domyślną wartość w kolumnie można zdefiniować wykorzystując słowo kluczowe DEFAULT: CREATE TABLE pracownicy ( id NUMBER DEFAULT 1, imie VARCHAR2(60) DEFAULT MARIUSZ, data_zatrudnienia DATE DEFAULT SYSDATE); 30
Kopiowanie tabel Do kopiowania tabeli służy konstrukcja: CREATE TABLE AS SELECT, np. CREATE TABLE pracownicy_kopia AS SELECT * FROM pracownicy; Do tworzenia tabeli o strukturze identycznej z inną tabelą służy konstrukcja: CREATE TABLE pracownicy_kopia AS SELECT * FROM pracownicy WHERE 1=0; 31
Edycja tabel Instrukcja ALTER TABLE służy do modyfikacji tabeli. Za jej pomocą można: Dodać nową kolumnę Zmodyfikować kolumnę Usnąć kolumnę 32
Edycja tabel Dodawanie kolumny do tabeli ALTER TABLE table ADD (column datatype [DEFAULT expr] [, column datatype]...); Na przykład: ALTER TABLE pracownicy ADD (drugie_imie VARCHAR2(60)); 33
Edycja tabel Modyfikowanie kolumny w tabeli ALTER TABLE table MODIFY (column datatype [DEFAULT expr] [, column datatype]...); Można modyfikować typ oraz wartość domyślną kolumny 34
Edycja tabel Modyfikowanie kolumny przykład zmiany typu kolumny ALTER TABLE pracownicy MODIFY (drugie_imie VARCHAR2(160)); Modyfikowanie kolumny przykład zmiany wartości domyślnej kolumny ALTER TABLE pracownicy MODIFY (drugie_imie DEFAULT ADAM ); 35
Edycja tabel Modyfikacja domyślnej wartości kolumny nie wpływa na wartości już obecne w tej kolumnie. Zmiana typu danych jest możliwa, gdy wszystkie wartości w tej kolumnie są NULL Zawsze można zwiększyć precyzję wartości numerycznej lub wydłużyć kolumny tekstowe 36
Edycja tabel Usuwanie kolumny z tabeli ALTER TABLE nazwa_tabeli DROP (nazwa_kolumny); Na przykład: ALTER TABLE pracownicy DROP (drugie_imie); 37
Zmiana nazwy tabeli Usuwanie kolumny z tabeli RENAME nazwa_tabeli TO nowa_nazwa_tabeli; Na przykład: RENAME pracownicy TO mistrzowie; 38
Czyszczenie tabel Za pomocą instrukcji TRUNCATE TABLE usuwamy wszystkie dane z tabeli i zwalniamy zajmowany przez nie obszar TRUNCATE TABLE nazwa_tabeli; Po wykonaniu tej operacji tabela dalej istnieje, ale jest pusta TRUNCATE TABLE mistrzowie; 39
Usuwanie tabel Tabelę usuwamy poleceniem DROP TABLE DROP TABLE nazwa_tabeli; Na przykład: DROP TABLE mistrzowie; 40
Tabele - podsumowanie Poznaliśmy 7 instrukcji do tworzenia modyfikacji i usuwania tabel: Instrukcja CREATE TABLE ALTER TABLE RENAME TRUNCATE DROP TABLE Zadanie Tworzenie tabeli Modyfikacja struktury tabeli Zmiana nazwy tabeli Czyszczenie tabeli Usuwanie tabeli 41
Perspektywy Perspektywy Reprezentują podzbiór danych z bazy danych Nie przechowują danych Bazują na tabelach lub widokach Za ich pomocą można pobierać i modyfikować dane w tabelach 42
Perspektywy Tabela PRACOWNICY Imie Pobory Data_zatrudnienia Adam 2600 2000-01-01 Bartosz 4200 2005-09-15 Beata 3800 2007-08-01 Celina 6000 2003-05-01 Perspektywa PRACOWNICY_NA_LITERE_B Imie Zatrudniony Bartosz 2005-09-15 Beata 2007-08-01 43
Perspektywy Perspektywy służą do: Upraszczania skomplikowanych zapytań Ograniczania dostępu do danych Uniezależnienia aplikacji od struktury bazy danych 44
Perspektywy Instrukcja tworzenia perspektywy CREATE [OR REPLACE] VIEW nazwa_widoku [(alias[, alias]...)] AS zapytanie; 45
Perspektywy Tworzenie perspektywy przykład CREATE OR REPLACE VIEW PRACOWNICY_NA_LITERE_B AS SELECT imie, data_zatrudnienia AS zatrudniony FROM pracownicy WHERE imie LIKE B% ; 46
Perspektywy Pobieranie danych z perspektywy przykład SELECT * FROM pracownicy_na_litere_b; Imie Zatrudniony Bartosz 2005-09-15 Beata 2007-08-01 47
Perspektywy Tworzenie perspektywy, wykorzystanie aliasów przykład CREATE OR REPLACE VIEW PRACOWNICY_NA_LITERE_B (imie, zatrudniony) AS SELECT imie, data_zatrudnienia FROM pracownicy WHERE imie LIKE B% [WITH READ ONLY]; 48
Perspektywy Tworzenie perspektywy wykorzystującej dwie tabele CREATE OR REPLACE VIEW PRACOWNICY_NA_LITERE_B AS SELECT p.imie, p.data_zatrudnienia, d.nazwa_dzialu FROM pracownicy p JOIN dzialy d ON d.dzial_id = p.dzial_id WHERE imie LIKE B% ; 49
Perspektywy Można wykonywać operacje DML (INSERT, UPDATE, DELETE) na perspektywach pod warunkiem, że: Nie wykorzystują konstrukcji DISTINCT ani GROUP BY Nie wykorzystują funkcji agregujących SUM, COUNT, MIN, MAX etc Nie wykorzystują pseudokolumny ROWNUM Modyfikowane kolumny nie są oparte na funkcjach SQL lub PL/SQL W przypadku perspektyw zawierających łączenie kilku tabel obowiązują dodatkowe kryteria 50
Perspektywy Wszystkie operacje DML wykonane na perspektywie zmieniają jedną tabelę, na której ta perspektywa jest oparta UPDATE pracownicy_na_litere_b SET zatrudniony = TRUNC(SYSDATE) Imie Pobory Data_zatrudnienia Adam 2600 2000-01-01 Bartosz 4200 2012-03-15 Beata 3800 2012-03-15 Celina 6000 2003-05-01 51
Perspektywy Za pomocą wyrażenia WITH READ ONLY uniemożliwimy operacje DML na perspektywie CREATE OR REPLACE VIEW PRACOWNICY_NA_LITERE_B AS SELECT imie, data_zatrudnienia AS zatrudniony FROM pracownicy WHERE imie LIKE B% WITH READ ONLY; 52
Perspektywy Perspektywy można usuwać wykorzystując instrukcję DROP VIEW Usuwając perspektywę nie usuwamy żadnych danych DROP VIEW pracownicy_na_litere_b; 53
Perspektywy - podsumowanie Nauczyliśmy się: Tworzyć perspektywy Wykorzystywać dyrektywę READ ONLY Wykonywać operacje DML na perspektywach Usuwać perspektywę 54
Sekwencje Sekwencje służą do generowania kolejnych liczb naturalnych Wykorzystywane są do tworzenia unikatowych identyfikatorów Są bezpieczne do wykorzystania przez równoległe wątki, żaden z wątków nie pobierze tej samej liczby 55
Sekwencje Składnia tworzenia sekwencji: CREATE SEQUENCE nazwa_sekwencji [INCREMENT BY n] [START WITH n] [{MAXVALUE n NOMAXVALUE}] [{MINVALUE n NOMINVALUE}] [{CYCLE NOCYCLE}] [{CACHE n NOCACHE}]; 56
Sekwencje Tworzenie sekwencji - przykład: CREATE SEQUENCE pracownik_id_seq INCREMENT BY 2 START WITH 10 MAXVALUE 9999 NOCACHE NOCYCLE; 57
Sekwencje Wartości z sekwencji odczytujemy za pomocą pseudokolumn NEXTVAL i CURRVAL Pseudokolumna NEXTVAL pobiera kolejną wartość sekwencji Pseudokolumna CURRVAL pobiera ostatnią wartość sekwencji pobraną w sesji Próba pobrania wartości CURRVAL bez wcześniejszego pobrania wartości NEXTVAL kończy się wyjątkiem 58
Sekwencje Pobieranie wartości z sekwencji - przykłady SELECT pracownik_id_seq.nextval FROM DUAL; SELECT pracownik_id_seq.currval FROM DUAL; INSERT INTO pracownicy VALUES( pracownik_id_seq.nextval, ) 59
Sekwencje Pobieranie wartości z sekwencji - przykłady INSERT INTO faktury(faktura_id, VALUES (faktura_id_seq.nextval,.); INSERT INTO linie_faktur (linia_faktury_id, faktura_id,.) VALUES (linia_faktury_id_seq.nextval, faktura_id_seq.currval ) 60
Sekwencje Sekwencję można usunąć wykorzystując instrukcję DROP SEQUENCE: DROP SEQUENCE nazwa_sekwencji; 61
Sekwencje - podsumowanie Nauczyliśmy się: Tworzyć sekwencje Pobierać wartości z sekwencji Usuwać sekwencje 62
Wyzwalacze INSERT INTO EMPLOYEES VALUES (100, 'Steven', 'King', 'SKING', '515.123.4567', TO_DATE('06/17/2003 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 'AD_PRES', 24000, 90); 63
Wyzwalacze (Trigger) Wyzwalacz jest nazwanym blokiem PL/SQL skojarzonym z tabelą Jest blokiem składowanym w bazie danych Jest uruchamiany automatycznie po instrukcji INSERT, UPDATE lub DELETE na tabeli CREATE OR REPLACE TRIGGER nazwa_wyzwalacza BEFORE INSERT ON employees BEGIN END; 64
Wyzwalacze INSERT, UPDATE lub DELETE TRIGGER 65
Wyzwalacze (Trigger) Wyzwalacze mogą być zdefiniowane, aby uruchamiać się na zdarzenia: INSERT UPDATE DELETE CREATE OR REPLACE TRIGGER nazwa_wyzwalacza BEFORE INSERT OR UPDATE OR DELETE ON employees BEGIN END; 66
Wyzwalacze (Trigger) Wyzwalacze mogą być zdefiniowane, aby uruchamiać się przed lub po zdarzeniu: - BEFORE -AFTER CREATE OR REPLACE TRIGGER nazwa BEFORE INSERT ON employees CREATE OR REPLACE TRIGGER nazwa AFTER INSERT ON employees 67
Wyzwalacze (Trigger) Wyzwalacze mogą być zdefiniowane, aby uruchamiać się raz dla instrukcji lub dla każdego wiersza, którego instrukcja dotyczy. - STATEMENT -ROW CREATE OR REPLACE TRIGGER nazwa BEFORE INSERT ON employees BEGIN CREATE OR REPLACE TRIGGER nazwa BEFORE INSERT ON employees FOR EACH ROW BEGIN 68
Wyzwalacze (Trigger) BEFORE STATEMENT BEFORE ROW AFTER STATEMENT AFTER ROW 69
Kolejność wyzwalaczy UPDATE PRACOWNICY SET POBORY = 200; IMIĘ POBORY ANDRZEJ 100 ANNA 110 BEATA 120 70
Kolejność wyzwalaczy UPDATE PRACOWNICY SET POBORY = 200; 1 BEFORE STATEMENT 2 BEFORE ROW 4 BEFORE ROW 6 BEFORE ROW IMIĘ POBORY ANDRZEJ 100 ANNA 110 BEATA 120 3 AFTER ROW 5 AFTER ROW 7 AFTER ROW 8 AFTER STATEMENT 71
Wyzwalacze (Trigger) Wykorzystanie instrukcji DELETING INSERTING UPDATING CREATE OR REPLACE TRIGGER nazwa_wyzwalacza BEFORE INSERT OR UPDATE OR DELETE ON employees BEGIN IF DELETING THEN IF INSERTING THEN IF UPDATING THEN END; 72
Wyzwalacze (Trigger) Pseudokolumny :NEW i :OLD umożliwiają odczytanie wartości kolumn rekordu sprzed i po zmianie Mogą być wykorzystywane tylko w wyzwalaczach BEFORE - FOR EACH ROW i AFTER - FOR EACH ROW W wyzwalaczach BEFORE - FOR EACH ROW pseudokolumna :NEW umożliwia zmianę wartości zapisywanej do tabeli 73
Wyzwalacze (Trigger) Wartości w rekordach :NEW oraz :OLD Operacja Wartość dla OLD Wartość dla NEW Wstawianie (INSERT) NULL Wartość wstawiana Aktualizacja (UPDATE) Wartość przed aktualizacją Wartość po aktualizacji Usuwanie (DELETE) Wartość przed usunięciem NULL 74
Wyzwalacze (Trigger) CREATE OR REPLACE TRIGGER trigger_name AFTER DELETE OR INSERT OR UPDATE ON PRACOWNICY FOR EACH ROW BEGIN INSERT INTO log_table END; Wykorzystanie pseudokolumn :NEW i :OLD VALUES (USER, SYSDATE, :OLD.salary, :NEW.salary); 75
Wyzwalacze (Trigger) CREATE OR REPLACE TRIGGER trigger_name BEFORE UPDATE ON pracownicy FOR EACH ROW BEGIN :NEW.imie := UPPER(:NEW.imie); END; Wykorzystanie pseudokolumny :NEW do zmiany wartości kolumny 76
Wyzwalacze (Trigger) INSERT, UPDATE lub DELETE TRIGGER 77