Bazy danych wykład szósty Więzy i wyzwalacze Konrad Zdanowski Uniwersytet Kardynała Stefana Wyszyńskiego, Warszawa szósty Więzy i wyzwalacze 1 / 35
Wstęp Wiemy jak nakładać pewne ograniczenia (więzy) w schemacie bazy danych (klucze, integralność referencyjna). Implementacja bazy danych może korzystać z tych ograniczeń aby zwiększyć wydajność ale musi też dbać o ich zachowanie, czyli o spójność danych. Można dbać o to z poziomu aplikacji lecz jest to niebezpieczne i niewygodne. DBMS dostarcza narzędzi do definiowania czynnosci, które trzeba podjać aby sprawdzić czy więzy nie zostały naruszone (i co wtedy zrobić). szósty Więzy i wyzwalacze 2 / 35
Outline 1 Więzy Klucze 2 Wyzwalacze szósty Więzy i wyzwalacze 3 / 35
Outline 1 Więzy Klucze 2 Wyzwalacze szósty Więzy i wyzwalacze 4 / 35
Klucze własne Klucze własne tabeli deklarujemy przez PRIMERY KEY lub UNIQUE. create table osoby ( pesel char [ 1 1 ] primary key, imie char [ 2 0 ], nazwisko char [ 5 0 ] ) ; create table samochody ( n r _ s i l n i k a int, marka char [ 3 0 ], primary key ( n r _ s i l i n i k a, marka ) ) ; szósty Więzy i wyzwalacze 5 / 35
Klucze obce Niech A będzie zbiorem atrybutów w relacji T i niech B będzie zbiorem atrybutów w relacji S. Możemy zadeklarować A jako klucz obcy powiazany z atrybutami G. Atrybuty G musza być kluczem relacji S. Dla każdej krotki t T, która ma różne od NULL wartości atrybutów A musi istnieć krotka s S taka, że t[a] = s[b]. szósty Więzy i wyzwalacze 6 / 35
Klucze obce Klucze obce deklarujemy jako create table Malzenstwa ( maz i n t references Osoby ( i d ), zona i n t references Osoby ( i d ) ) ; lub przez oddzielna deklarację create table Ksiegozbior ( t y t u l char [ 5 0 ], rok_wydania int, szerokosc int, wysokosc int, foreign key ( t y t u l, rok ) references K s i a z k i ( t y t u l, rok ) ) ; szósty Więzy i wyzwalacze 7 / 35
Problem jajka i kury Rozważmy deklaracje create table Kura ( i d i n t primary key, j a j k o _ i d i n t references Jajko ( i d ) ) ; create table Jajko ( i d i n t primary key, kura_id i n t references Kura ( i d ) ) ; Wykonanie tych poleceń wygeneruje bład (Oracle) gdyż podczas tworzenia tabeli Kura nie istnieje tabela, do której odwołuje się klucz obcy tabeli Kura. szósty Więzy i wyzwalacze 8 / 35
Problem jajka i kury Musimy utworzyć tabele Jajko i Kura bez deklaracji kluczy obcych: create table Kura ( i d i n t primary key, j a j k o _ i d i n t ) ; create table Jajko ( i d i n t primary key, kura_id i n t ) ; Następnie modyfikujemy tabele: a l t e r table Kura add constraint KuraRefJajko foreign key ( j a j k o _ i d ) references Jajko ( i d ) i n i t i a l l y deferred deferrable ; a l t e r table Jajko add constraint JajkoRefKura foreign key ( kura_id ) references Kura ( i d ) i n i t i a l l y deferred deferrable ; szósty Więzy i wyzwalacze 9 / 35
Problem jajka i kury Opcja initially deferred deferrable każe odroczyć sprawdzenie integralności referencyjnej. Dzięki temu możemy dodać coś do obu tabel: i n s e rt into Kura values ( 1, 3 ) ; i n s e rt into Jajko values ( 3, 1 ) ; commit ; Sprawdzenie następuje dopiero podczas commit. szósty Więzy i wyzwalacze 10 / 35
Problem jajka i kury Podobnie usunięcie tabeli Kura narusza warunek klucza obcego z tabeli Jajko. Przed usunięciem musimy wcześniej zmienić tabele a l t e r table Kura drop constraint KuraRefJajko ; a l t e r table Jajko drop constraint JajkoRefKura ; drop table Kura ; drop table Jajko ; szósty Więzy i wyzwalacze 11 / 35
Odroczenie sprawdzania więzów Domyślnie więzy sprawdzane sa po każdej instrukcji, która może je naruszyć. Możemy odroczyć sprawdzanie więzów przez deklaracje bf deferable initially deferred. Możemy też zmienić strategie sprawdzania więzów poleceniem: set constraint <ograniczenie> deferred lub set constraint <ograniczenie> immediate. szósty Więzy i wyzwalacze 12 / 35
Integralność referencyjna Zmiany krotek, w tabeli z więzami moga spowodować ich naruszenie. DBMS powinien zareagować w takich sytuacjach. szósty Więzy i wyzwalacze 13 / 35
Integralność referencyjna Rozważmy tabele Klucze(id) i KluczeObce(ko), gdzie ko jest kluczem obcym odwołujacym się do Klucze(id). Jeśli chcemy wstawić do KluczeObce krotkę z wartościa klucza obcego różna od NULL i taka, że nie znajduje się ona w tabel Klucze, to DBMS odrzuci zmianę. Podobnie musi zachować się w sytuacji, gdy zmieniamy wartość ko w KluczeObce na wartość różna od NULL i nie znajdujac a się w tabeli Klucze. szósty Więzy i wyzwalacze 14 / 35
Integralność referencyjna usuwanie Rozważmy tabele Klucze(id) i KluczeObce(ko), gdzie ko jest kluczem obcym odwołujacym się do Klucze(id). DBMS domyślnie zabroni usunięcia krotek z tabeli Klucz, do których odwołuja się pewne krotki z tabeli KluczObcy. Polityka kaskadowa usunie wszystkie krotki z tabeli KluczObcy, które odwołuja się do usuniętej wartości (opcja on delete cascade). Polityka ustawienia NULL wstawi wartości NULL w miejsce wszystkich wartości, które przestały odwoływać się do istniejacej wartości (on delete set null). szósty Więzy i wyzwalacze 15 / 35
Integralność referencyjna modyfikacja Rozważmy tabele Klucze(id) i KluczeObce(ko), gdzie ko jest kluczem obcym odwołujacym się do Klucze(id). DBMS domyślnie zabroni modyfikacji krotek z tabeli Klucz, do których odwołuja się pewne krotki z tabeli KluczObcy. Polityka kaskadowa zmieni wartości atrybutu ko krotek z tabeli KluczObcy, na nowa wartość (opcja on update cascade). Polityka ustawienia NULL wstawi wartości NULL w miejsce wszystkich wartości, które przestały odwoływać się do istniejacej wartości (on update set null). szósty Więzy i wyzwalacze 16 / 35
Więzy atrybutów i krotek Możemy nakładać więzy na poszczególne atrybuty tabeli. Przykłady: id int not null, plec char(1) check (plec in ( K, M )). kluczobcy int check (exists (select id from Klucze)). check (placa >= select avg(placa) / 2 from pracownicy). Więzy te sa sprawdzane przy każdym wstawieniu lub aktualizacji wartości atrybutu. szósty Więzy i wyzwalacze 17 / 35
Więzy atrybutów i krotek W definicji tabeli możemy dodać warunek, który maja spełniać krotki z tabeli. Np. tylko osoby posiadajace kartę kredytowa w danym banku moga mieć w nim kredyt: check ( (KartaKredytowa is not null)or( Kredyt is null)). szósty Więzy i wyzwalacze 18 / 35
Więzy atrybutów i krotek Więzy krotek sa sprawdzane przy modyfikacji krotki. Więzy atrybutów sa sprawdzane tylko przy włożeniu lub modyfikacji atrybutu. Jeśli warunek odwołuje się do innych krotek w tabeli lub innych tabel, to łatwo może stać się fałszywy. szósty Więzy i wyzwalacze 19 / 35
Własności więzów Nałożone więzy moga być: DEFERRABLE albo NOT DEFERRABLE, INITIALLY DEFERRED albo INITIALLY IMMEDIATE. Konsekwencje różnych własności: Więzy IMMEDIATE sa sprawdzane po każdej instrukcji, która może zmienić ich zachodzenie (insert, update). Więzy DEFERRED sa sprawdzane dopiero podczas operacji commit. Własności więzów ustawiamy instrukcja set constraint <warunek> <własność>. Aby można było ustawić własność DEFERRED dane ograniczenie musi być utworzone z własnościa DEFERRABLE. Jeśli więzy nie sa spełnione transakcja lub cały ciag transakcji (przy własności deferred) zostaje cofnięty. szósty Więzy i wyzwalacze 20 / 35
Własności więzów przykład Jeśli w tabeli T mamy ograniczenie T_chk postaci check (a>-20 and a<20), które ma własność deferred i wykonujemy ciag instrukcji: insert into T values(30); insert into T values(11); insert into T values(2); commit; to cofnięte zostana wszystkie instrukcje. szósty Więzy i wyzwalacze 21 / 35
Własności więzów przykład W tabeli T mamy ograniczenie T_chk postaci check (a>-20 and a<20). set constraint T_chk immediate ; i n sert into T values ( 1 6 ) ; i n sert into T values ( 2 0 ) ; i n sert into T values ( 1 7 ) ; set constraint T_chk deferred ; i n sert into T values ( 1 8 ) ; i n sert into T values ( 3 0 ) ; i n sert into T values ( 1 9 ) ; Po wykonaniu powyższych instrukcji T będzie zawierać wartości 16, 17, 18, 30, 19. Po wykonaniu commit wszystkie powyższe instrukcje zostana cofnięte. Możemy się przed tym zabezpieczyć wykonujać przed zakończeniem transakcji set constraint T_chk immediate. szósty Więzy i wyzwalacze 22 / 35
Modyfikacje więzów Możemy modyfikować więzy poprzez instrukcje: set constraint... albo alter table... modify constraint... Więzy możemy włacz ać lub wyłaczać, ENABLE lub DISABLE, z opcjami VALIDATE lub NOVALIDATE. ENABLE (opcja domyślna VALIDATE) włacza warunek i sprawdza czy zachodzi dla aktualnych danych. Jeśli nie jest spełniony to instrukcja się nie powiedzie. ENABLE NOVALIDATE włacza warunek lecz nie sprawdza go dla aktualnych danych. DISABLE (opcja domyślna NOVALIDATE ) wyłacza warunek (np. usuwa index dla warunków UNIQUE lub PRIMARY KEY). DISABLE VALIDATE wyłacza warunek lecz nie pozwala na późniejsza modyfikację kolumny, której dotyczy warunek. szósty Więzy i wyzwalacze 23 / 35
Outline 1 Więzy Klucze 2 Wyzwalacze szósty Więzy i wyzwalacze 24 / 35
Wyzwalacze Wyzwalacze pozwalaja kontrolować zarówno czas wykonania akcji jak i warunek, który ma być spełniony. Określane jako reguły ECA event-condition-action. event modyfikacja bazy danych, condition wyrażenie SQL o wartości booleowskiej, action wyrażenie SQL. Nie należy stosować wyzwalaczy jeśli możemy uzyskać ten sam efekt przez zastosowanie więzów (NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK, ON DELETE CASCADE, ON DELETE SET NULL). szósty Więzy i wyzwalacze 25 / 35
Przykład Jeśli wkładana do tabeli KluczeObce(id, ko) wartość ko nie występuje w tabeli Klucze(id), to zastapmy ja wartościa NULL. create or replace t r i g g e r BrakKlucza a f t e r i n sert on KluczeObce referencing old row as StaraKrotka new row as NowaKrotka for each row when ( NowaKrotka. ko not i n ( select i d from Klucze ) ) update KluczeObce ( i d, ko ) set ko=null where i d =NowaKrotka. i d ; szósty Więzy i wyzwalacze 26 / 35
Przykład Ostatniego przykładu proszę nie sprawdzać w Oracle. Nie ma DBMS, który by implementował całość standardu SQL zwiazanego z wyzwalaczami. szósty Więzy i wyzwalacze 27 / 35
Wyzwalacze Wydarzenie Wyzwalacz możemy uruchomić przed, po lub zamiast wydarzenia (before, after, instead of). Wydarzenie instead of jest zarezerwowane dla perspektyw (określamy co zrobić zamiast modyfikowania perspektywy). Wykonujac wyzwalacz przed wydarzeniem, po wykonaniu wyzwalacza warunek nie jest sprawdzany drugi raz. Wydarzeniami moga być: insert, update, delete. Przy update możemy zawęzić modyfikację do pewnych atrybutów: update of atrybuty. szósty Więzy i wyzwalacze 28 / 35
Wyzwalacze warunek Warunek to wyrażenie SQL o wartości boole owskiej. Warunek sprawdzany jest w tabeli, która istnieje przed zmiana lub która istniałaby po zmianie. szósty Więzy i wyzwalacze 29 / 35
Wyzwalacze akcja Akcja może być pojedyńcza instrukcja SQL lub ich zbiór (begin... end). Akcję możemy wykonać dla pojedyńczych wierszy (for each row) lub dla całej instrukcji, która uruchomiła wyzwalacz (for each statement domyślne). Przy opcji for each row możemy odwołać się do starej i nowej krotki tabeli (jeśli istnieja). szósty Więzy i wyzwalacze 30 / 35
Wyzwalacze Oracle Możemy wywołać wyzwalacz przy wydarzeniu systemowym (startup, shutdown, logon, logoff) Przy update możemy zawęzić modyfikację do pewnych atrybutów: update of atrybuty. Możemy wymienić do trzech warunkow przy pomocy or: before update or insert on Tab. Wyzwalacz typu statement nie może posiadać klauzuli when. W warunku when nie możemy użyć kwerendy SQL. szósty Więzy i wyzwalacze 31 / 35
Wyzwalacze Oracle Jeden wyzwalacz może określać akcje typu statement jak i akcję each row (compound triggers). Do nowych krotek odwołujemy się przez new, do starych przez old. W akcji nowe i stare wartosci poprzedzamy dwukropkiem ale po warunku when nie. Aby uniknać nieskończonych sekwencji wywołań wyzwalacz nie może: modyfikować tabeli, której modyfikacja go uruchomiła, modyfikować tabeli powiazanej z ta tabela przez więzy klucza obcego. Możemy obejrzeć błędy kompilacji wyzwalacza wydajac polecienie: show errors trigger <nazwa_wyzwalacza>; szósty Więzy i wyzwalacze 32 / 35
Wyzwalacze przykład Wstawianie domyślnej wartości zamiast NULL we wstawianych do tabeli danych. create or replace t r i g g e r UstawJajko before update or insert on Kura for each row when (new. j a j k o _ i d i s null ) begin :new. j a j k o _ i d : = 1 ; end ; szósty Więzy i wyzwalacze 33 / 35
Wyzwalacze przykład Wstawianie brakujacej krotki z kluczem do tabeli Klucze przy próbie wstawienia do tabeli KluczeObce. create or replace t r i g g e r DodajKlucz before update or i n s e r t on KluczeObce for each row declare i number ; begin select count ( ) into i from Klucze where i d =:new. kluczobcy ; i f ( i =0) then i n sert into Klucze values ( : new. kluczobcy ) ; end i f ; end ; szósty Więzy i wyzwalacze 34 / 35
Podsumowanie Więzy kluczy: sprawdzane przy zmianach tabeli z kluczem obcym oraz przy zmianach tabeli, do której odwołuje sie klucz obcy, pozwalaja na różne lecz ograniczone strategie przy niespełnieniu integralności. Więzy check atrybutów: sprawdzane tylko przy zmianach odpowiednich atrybutów, zmiany innych krotek lub tabel moga je ufałszywić, pozwalaja na dowolne strategie reakcji. Więzy check krotek podobnie jak atrybutów lecz sa częściej sprawdzane. Wyzwalacze: elastyczne warunki uruchomienia. dowolne podejmowane akcje. szósty Więzy i wyzwalacze 35 / 35