Bazy danych
Transkrypt
Bazy danych
Bazy danych—model relacyjny – minimum? E. F. Codd za podstawę modelu baz danych przyjął pojęcie relacji – obiektu ze świata matematyki. Niech A1 , A2 ,⋯, An oznaczają zbiory (dziedziny). Relacją ρ nazywamy dowolny podzbiór iloczynu kartezjańskiego (produktu) zbiorów ⊆ A1 × A2 ×⋯× An . Np. dla zbiorów A={2, 9 , 3, 6 , 5 }, B={7, 1, 4 } można zdefinować relację „<” (mniejszy). Cały produkt kartezjański to, w tym przypadku, następujący zbiór par: A×B={ 2,7 ,2,1 ,2,4 , 9,7 ,9,1 ,9,4 , {2,7 ,2,4 ,3,7 , 3,7 ,3,1 ,3,4 , , zaś interesujący nas podzbiór (relacja) to 3,4 ,6,7 ,5,7}. 6,7 ,6,1 ,6,4 , 5,7 ,5,1 ,5,4 } Elementami zbiorów niekoniecznie muszą być liczby. Np. Zbiór M zawiera nazwy miast, zaś zbiór O imiona osób; relacją będzie mieszka w. Własność być w relacji można przedstawiać graficznie, łącząc dwa elementy obu zbiorów linią ze strzałką: linia wychodzi z elementu zbioru pierwszego i kończy się strzałką na elemencie zbioru drugiego. Poniżej pokazano graficzną interpretację relacji obu przykładów. Relacja: element zbioru A jest mniejszy od elementu zbioru B 3 B 5 4 Relacja: mieszka w Iza Ola Kuba Jarek Witek J J J J Puck Sopot Konin 1 6 A Reda Ustka 7 2 9 Rumia J Quiz. Zbiór: rodzeństwo. Relacja: mam brata Określić płeć osoby ukrywającej się za buźką Aga Ewa Przy okazji zauważmy następujący fakt (będzie o krotności relacji): Przykład z liczbami jest relacją, umownie określaną, N:M. Otóż w relacji „<” z jedną liczbą zbioru A jest kilka liczb zbioru B i kilka liczb zbioru A jest w relacji „<” z jedną liczbą zbioru B. Przykład drugi „mieszka w” określany jest jako relacja 1:N. Można tu już mówić o zależności funkcyjnej elementu zbioru M od elementu zbioru O: element zbioru O (element determinujący) jednoznacznie określa element zbioru M (element zależny), albo inaczej różne elementy zbioru M gwarantują różne elementy zbioru O. Gwoli kompletności rozważań: istnieją relacje o krotności 1:1. Według propozycji Codd'a każda relacja jest tabelą, dla której spełnione są warunki: • Każda relacja w bazie ma jednoznaczną nazwę. • Każda kolumna w relacji ma jednoznaczną nazwę w ramach jednej relacji. • Wszystkie wartości w kolumnie muszą być tego samego typu (mówimy, że są zdefiniowane na tej samej dziedzinie). • Porządek kolumn w relacji nie jest istotny. • Każdy wiersz w relacji musi być różny (powtórzania wierszy nie są dozwolone). • Porządek wierszy nie jest istotny. • Każde pole leżące na przecięciu kolumna/wiersz w relacji powinno zawierać wartość atomową (w jednym polu nie jest dozwolony zbiór wartości). Ostatni warunek to tzw. postulat 1NF; relacyjna baza danych niejako z definicji jest w pierwszej postaci normalnej. Poniżej przykład relacji—tabeli wraz z opisem używanych określeń. Nazwa atrybutu (kolumny) Nazwa relacji (tabeli) Relacja (tabela) { Towar Nazwa Cena JednMiary CHLEB 1.20 SZT MASŁO 2.89 SZT SER 16.70 KG } Krotka Atrybut Kilka lat po pierwszych publikacjach Codd'a na temat modelu relacyjnego P.P.Chen zaproponował model danych encja-związek (entity-relationship data model) — graficzną reprezentację modelu danych, w którym stosuje się trzy konstrukcje: encje, związki i atrybuty. Encja† (ang. entity) oznacza coś co (obiektywnie) istnieje i jest rozróżnialne. Formalnej definicji pojęcia encji nie ma. Tzw. diagramów ER używa się do reprezentacji modelu koncepcyjnego. Poniżej już znany temat. osoba Mieszka w miasto Encja Związek † Moim zdaniem (MK) encja to kolejny potworek, który trafił do polszczyzny. Filozofia dużo wcześniej dorobiła się zgrabnego terminu byt, który oznacza dokładnie to samo. No ale trzeba było zamieszać, żeby nie rzec, ściemnić… O normalizacji. Normalizacja to proces mający na celu takie przekształcenie (dużych) tabel o nieefektywnej budowie na mniejsze o wydajniejszej strukturze, podczas którego nie dochodzi do utraty informacji. Dobrze zbudowana baza danych nie zawiera duplikatów, a dane nadmierne ograniczone są do niezbędnego minimum. To zapewnia spójność danych i gwarantuje, że informacje wyszukiwane będą precyzyjne i niezawodne (odporne na anomalie modyfikacyjne). Przyswojenie istoty procesu normalizacji być może ułatwi rota przysięgi normalizacyjnej: 1. Bez powtórzeń. 2. Pola zależą od klucza. 3. Od całego klucza. 4. I niczego innego, tylko klucza. 5. Tak mi dopomóż Codd. (Ponoć) nia każda tabela jest dobra. Zanim powstanie aplikacja należy zaprojektować bazę danych. Nie każdy projekt zasługuje na pochwałę. W przypadku projektowania tabel warto stosować się do następujących generalnych wskazówek projektowych: • Dla nazwania kolumn tabeli warto stosować nazwy opisowe. Niech te nazwy są klarowne i jednoznacznie określają zawartość. • Należy być konsekwentnym podczas definowania nazw kolumn tabeli. • Należy tworzyć tylko te kolumny, które są niezbędne do właściwego modelowania encji lub powiązań. • W każdej tabeli należy zawsze tworzyć (przewidzieć) pola kluczowe (unikalne). W ten sposób uniknie się potencjalnego problemu powtarzania się rekordów. • Należy unikać powtarzania informacji w bazie danych. Do analizy procesu normalizacji używa się dwóch pojęć: • klucz (kandydujący) — jest to minimalny zbiór kolumn, które jednoznacznie identyfikują każdy wiersz (kombinacja wartości w tych kolumnach jest unikalna w ramach całej tabeli i spośród kolumn klucza nie można wybrać pozbioru kolumn, który również zapewnia unikatowość wierszy w tabeli); tabela może mieć kilka takich kluczy. • klucz podstawowy (główny) — jest jednym wybranym (dowolnie) kluczem kandydującym tabeli. Podział danych na tabele opiera się krotności relacji między obiektami. Wyróżniamy relacje: • jeden do jednego (1:1) — relacja taka zachodzi, gdy jeden element wykazuje zależność funkcyjną od drugiego. W takiej sytuacji elementy umieszcza się zwykle w jednej tabeli. Na przykład w tabeli z danymi personalnymi osób, tj. imię, nazwisko, data urodzenia, nie ma na ogół sensu umieszczać danych o dacie urodzenia w osobnej tabeli, gdyż imię i nazwisko jednoznacznie odwzorowują się na datę urodzenia. • jeden do wielu (1:N) — relacja taka zachodzi, gdy jeden element powiązany jest z wieloma innymi elementami. W takich sytuacjach umieszcza się je w osobnych tabelach. Wiąże się je ze sobą za pomocą pary kluczy: klucza głównego i klucza obcego. Klucz główny znajduje się w tabeli, gdzie element, który jest powiązany z innymi elementami jest unikalny i jest tylko jeden taki klucz, natomiast klucz obcy znajduje się w tabeli, gdzie może znaleźć się wiele takich elementów. Klucz obcy też jest unikalny w obrębie (pewnej) tabeli. Przykład: zamówienie ma wiele pozycji, wiele osób mieszka w jednym mieście, ktoś ma kilka (numerów) telefonów, itp. • wiele do wiele (N:M) — relacja taka zachodzi, gdy istnieją dwie grupy elementów, które mogą łączyć się ze sobą w taki sposób, że zarówno dowolny element z pierwszej grupy może łączyć się z wieloma elementami grupy drugiej, jak również dowolny element grupy drugiej może łączyć się z wieloma elementami grupy pierwszej. Technicznie, relację taką realizuje się poprzez specjalną dodatkową tabelę łączącą dwie tabele, zawierające specyfikacje elementów obu grup powiązanych relacją (następuje przejście na dwie relacje: 1:N i 1:M). Np. w bazie z ocenami studentów taka relacja może powstać, jeśli wydzielimy obiekt forma sprawdzenia wiedzy (kolokwium, egzamin, praca domowa). W takim przypadku powiązanie studentów z formą sprawdzenia wiedzy jest relacją N:M: każdy student brał udział w wielu formach sprawdzenia wiedzy, ale też danej formie sprawdzenia wiedzy badano umiejętności wielu studentów. Postaci normalne. • • • • 1NF (pierwsza postać normalna, ang. normal form), pola zawierają tylko wartości atomowe. 1NF jest konieczna, aby tabelę w ogóle można było nazwać relacją. Wiele systemów baz danych nie ma wręcz możliwości zbudowania tabel nie będących w pierwszej postaci normalnej. 2NF (druga postać normalna), spełniona jest 1NF, a ponadto kolumny nie wchodzące w skład klucza (dowolnego klucza kandydującego) zależą funkcyjnie od całego klucza głównego. W przypadku gdy klucz relacji jest jednoelementowy i tabela jest w 1NF, to jest ona również w 2NF. Uwaga. Mówimy, że kolumna B zależy (funkcyjnie) od kolumny A (zapis: A B ), jeżeli dla dowolnej wartości w kolumnie A istnieje dokładnie jedna związana z nią wartość kolumny B. 3NF (trzecia postać normalna), spełniona jest 2NF a ponadto kolumny nie wchodzące w skład klucza głównego powinny zależeć funkcyjnie od klucza głównego. 3NF Atrybuty powinny być zależne od klucza, całego klucza i tylko od klucza relacji. Ludzkim(?) językiem o normalizacji tabeli • 1NF — tylko wartości atomowe. • 2NF — atrybuty zależą od całego klucza. • 3NF — elementy danych wyłącznie opisują klucz. Może jakiś przykład. Wyobraźmy sobie, że firma Bubel i S-ka dojrzała do komputerowej rejestracji zamówień (klient składa zamówienie na wyroby). Najpierw powstała taka oto mocarna tabela zawierające dane o klientach, zamówieniach i wyrobach, gdzie do klucza kandyduje pole Knr: Knr KNazwa KMiasto 1 Karo Puck 2 Kier Reda Znr ZData Wyrób Ilość Cena 001/2004 12.02.2004 Salceson 5 7.20 Kaszanka 8 4.20 001/2005 17.01.2005 Kaszanka 6 4.30 002/2004 24.04.2004 Kaszanka 10 4.20 Zauważmy kilka faktów: zarzutu o nadmiar informacji (powtórzenia, redundancję) trudno postawić (to plus), ale… Podobno zawsze jest jakieś ale. Taka tabela jest podatna na tzw. anomalie: • anomalia wstawiania — nie mogę wstawić informacji tylko o kliencie nie podając danych zamówienia; • anomalia usuwania — gdyby usunąć pierwszy wiersz tabeli utracę całą informację raz o kliencie Karo, dwa – o zamówieniu 001/2004; o salcesonie już nie wspomnę… Przystępujemy do procesu normalizacji. Najpierw doprowadzamy tabelę do 1NF. Oto wynik: Knr KNazwa KMiasto 1 Karo Puck 1 Karo 1 2 Znr ZData Wyrób Ilość Cena 001/2004 12.02.2004 Salceson 5 7.20 Puck 001/2004 12.02.2004 Kaszanka 8 4.20 Karo Puck 001/2005 17.01.2005 Kaszanka 6 4.30 Kier Reda 002/2004 24.04.2004 Kaszanka 10 4.20 Zauważmy, do klucza tym razem kandyduje kombinacja kolumn Znr+Wyrób. Co z anomaliami: • anomalia wstawiania — bez zmian, kłopoty pozostały; • anomalia modyfikacji — to nowość, składając drugie zamówienie klient zgłosił, że jego nazwa to Karol; wypada poprawić w kilku(nastu, set) miejscach – może boleć; • anomalia usuwania — tylko kłopot z salcesonem pozostał, ale pozostał. Kolejna transformacja; następny etap 2NF: • wyrzucić poza tabelę wszelkie kolumny, które nie zależą od klucza głównego; • utworzyć nowe tabele dla wszystkich logicznie współzależnych kombinacji kolumn i tam dodać (zdefiniować) klucz główny; • usunąć powtórzenia. Znr Knr KNazwa KMiasto ZData Znr WNr Ilość Cena 001/2004 1 Karo Puck 12.02.2004 001/2004 1 5 7.20 002/2004 2 Kier Reda 24.04.2004 001/2004 2 8 4.20 001/2005 1 Karo Puck 17.01.2005 002/2004 2 10 4.20 001/2005 2 6 4.30 Wnr Wyrób 1 Salceson 2 Kaszanka Powstały trzy odrębne tabele. Proszę osądzić jak ma się rzecz z anomaliami. Powoli zbliżamy się do stanu, kiedy jedna tabela będzie opisywać jeden byt tego mikroświata. Następna transformacja doprowadzi do 3NF: • wyrzucić poza tabele wszelkie kolumny, które nie zależą wyłącznie od klucza głównego; • utworzyć nowe tabele dla wszystkich logicznie współzależnych kombinacji kolumn i tam dodać (zdefiniować) klucz główny; • usunąć powtórzenia. Uwaga. W pierwszej tabeli Knazwa i Kmiasto zależy (funkcyjnie) nie tylko od klucza głównego ale i od Knr. To zależność przechodnia: Znr Knr Kmiasto. Zapisujemy to Znr ⇒ KMiasto. Oznacza to, że tabela opisuje więcej niż jeden temat (tu: i zamówienie, i klienta). Knr KNazwa KMiasto Znr WNr Ilość Cena 1 Karo Puck 001/2004 1 5 7.20 2 Kier Reda 001/2004 2 8 4.20 002/2004 2 10 4.20 001/2005 2 6 4.30 Znr Knr ZData 001/2004 1 12.02.2004 002/2004 2 24.04.2004 Wnr Wyrób 001/2005 1 17.01.2005 1 Salceson 2 Kaszanka Wyjściowa tabela po przejściach; osiągneliśmy 3NF. Niejako przy okazji tabela jest również w postaci normalnej Boyce'a-Codd'a (ang. Boyce-Codd Normal Form), skrót BCNF. Jest to trochę silniejsza (bardziej restrykcyjna) odmiana 3NF. Jeżeli relacja spełnia warunki BCNF to jest również w 3NF. Odwrotne twierdzenie nie zawsze jest prawdziwe. Uzupełnienie postaci normalnych. • BCNF — relacja jest w postaci BCNF wtedy i tylko wtedy gdy jedynymi wartościami determinującymi są klucze kandydujące. Uwaga. Gdy mamy do czynienia z zależnością funkcyjną A B , to mówimy, że A determinuje (wyznacza) B, zaś B funkcyjnie zależy od A lub A jest elementem determinującym (wyznacznikiem, ang. determinant) a B jest elementem zależnym (ang. dependent). Jeżeli relacja ma tylko jeden klucz kandydujący i jest w 3NF, to jest również w BCNF. Tak właśnie zdarzyło się w rozważanym wyżej przykładzie. • 4NF — tabela jest w 3NF i atrybuty spoza klucza głównego to jedyna kolumna poza kolumnami klucza głównego. Dotychczas prezentowane postacie normalne (1NF, 2NF, 3NF, BCNF) bazowały na zależności funkcyjnej; 4NF dotyczy zależności wielowartościowych, czyli takich, że A determinuje (wyznacza) wiele wartości B; wtedy używamy zapisu: A B. Zgrubsza chodzi znów o to, żeby tabela była na (tylko) jeden temat i w związku z tym, aby w jednej tabeli wyrugować obecność naraz kolumn typu: jeździ na rowerze (lub lata szybowcem), mówi po francusku (i nie tylko), ma kota. Algebra relacyjna Codd zdefiniował osiem operatorów relacyjnych: 1. 2. 3. 4. 5. 6. 7. 8. SELECT (w oryginale było RESTRICT) — restrykcja PROJECT — rzut JOIN — złączenie PRODUCT — iloczyn UNION — suma INTERSECT — przecięcie DIFFERENCE — różnica DIVIDE — podział SELECT Ogranicza; tylko te wiersze tabeli, które spełniają warunek: SELECT * FROM tabela WHERE warunek PROJECT Wybór kolumn tabeli; utworzona tabel zawierać będzie tylko wskazane kolumny: SELECT KOL1, KOL2 FROM tabela PRODUCT Tworzy nową relację składającą się ze wszystkich możliwych kombinacji wierszy obu (lub więcej) tabel: A: a b c B: d e => A product B: a a b b c c d e d e d e B: a e => A union B: a b c e B: a e => A intersect B: a B: a e => UNION A: a b c INTERSECT A: a b c DIFFERENCE A: a b c A - B: b c and B - A: e DIVIDE Pierwsza tabela jest dwukolumnowa, druga składa się z jednej kolumny. Przykład (i interpretacja działania zarazem). Tabela A zawiera informacje o klientach (a,b,c), którzy kupili towary (x,y,z). Pierwszy wariant operacji podziału daje odpowiedź na pytanie: kto kupił towar x, drugi – kto kupił towar x i y. A: a a a b c x y z x y B: x => A divide B: a b B: x y => A divide B: a JOIN Możliwości złączeń jest kilka. Załóżmy, że sytuacja jest następująca: na parkingu firmy parkują swoje samochody nie tylko pracownicy tej firmy. Walczymy z następującymi tabelami: osoby ma_auto dział nazwisko Marka Model Nowak Kadry Kowalski Skoda Fabia ID nazwisko N01 K01 Kowalski FK Kowalski C01 Cypis BHP Figiel B01 Baca FK Baca B02 Bąk FK Kia Opel Astra Fiat Nowak Nissan Uno CROSS JOIN (to samo co PRODUCT) SELECT * FROM osoby, ma_auto; ID nazwisko N01 dział nazwisko Marka Model Nowak Kadry Kowalski Skoda Fabia K01 Kowalski FK Kowalski Skoda Fabia C01 Cypis BHP Kowalski Skoda Fabia B01 Baca FK Kowalski Skoda Fabia B02 Bąk FK Kowalski Skoda Fabia N01 Nowak Kadry Kowalski K01 Kowalski Kia FK Kowalski Kia C01 Cypis BHP Kowalski Kia B01 Baca FK Kowalski Kia B02 Bąk FK Kowalski Kia ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ Tabela utworzona w wyniku operacji zawiera więcej wierszy (ile?); powyżej to jej początek. Formalnie rzecz ujmując, to podane polecenie SQL ma wadę; utworzona tabela ma kolumny o tych samych nazwach – to grzech. Można to skorygować np. tak (inny nagłówek – jaki, treść b.z.): SELECT L.ID, L.nazwisko, L.dział, R.nazwisko, R.Marka, R.Model FROM osoby L, ma_auto R; (Właściwe) Operacje JOIN służą do rekonstrukcji wyjściowych tabel z tabel powstałych po normalizacji. Poniższy rysunek próbuje pokazać zakres pól, które trafią do wyniku operacji. LEFT OUTER JOIN (INNER) JOIN NULL NULL NULL NULL INNER JOIN Operacja złączenia naturalnego może być zadana różnie, oto dwie możliwości: 1) 2) SELECT * FROM osoby JOIN ma_auto ON osoby.nazwisko=ma_auto.nazwisko; SELECT * FROM osoby, ma_auto WHERE osoby.nazwisko=ma_auto.nazwisko; FULL OUTER JOIN RIGHT OUTER JOIN W wyniku operacji powstanie tabela, która zawiera następujące wiersze: ID nazwisko N01 dział nazwisko Marka Model Nowak Kadry Nowak Nissan K01 Kowalski FK Kowalski Skoda Fabia K01 Kowalski FK Kowalski Kia B01 FK Fiat Baca Baca Uno Złączenia wewnętrzne zawierają tylko te wiersze, gdzie występują obaj aktorzy; i w tabeli osoby, i w tabeli ma_auto. Złączenia zewnętrzne charakteryzują się tym, że jeden z aktorów może być nieobecny; w takim przypadku do tabeli w odpowiednim miejscu trafiają wartości puste (NULL): • • • LEFT – do tabeli trafia to co w złączeniu naturalnym oraz pola lewej tabeli bez pary; RIGHT – do tabeli trafia to co w złączeniu naturalnym oraz pola prawej tabeli bez pary; FULL – do tabeli suma tabel LEFT i RIGHT bez powtórzeń. Brak informacji też jest informacją; gdyby rozpatrzeć przykład: lewa tabela to paragony sklepowe, prawa to towary na stanie, a operacja robiona jest za jakiś okres czasu, to brak pary z lewej oznacza, że towar zalega i nie sprzedaje się. Są przesłanki do podjęcia akcji typu promocja… LEFT OUTER JOIN SELECT * FROM osoby LEFT OUTER JOIN ma_auto ON osoby.nazwisko=ma_auto.nazwisko; ID nazwisko N01 dział nazwisko Marka Model Nowak Kadry Nowak Nissan K01 Kowalski FK Kowalski Skoda Fabia K01 Kowalski FK Kowalski C01 Cypis BHP B01 Baca FK B02 Bąk FK Baca Kia Fiat Uno RIGHT OUTER JOIN SELECT * FROM osoby RIGHT OUTER JOIN ma_auto ON osoby.nazwisko=ma_auto.nazwisko; ID nazwisko N01 dział nazwisko Marka Model Nowak Kadry Nowak Nissan K01 Kowalski FK Kowalski Skoda Fabia K01 Kowalski FK Kowalski Kia B01 FK Baca Fiat Uno Figiel Opel Astra Baca FULL OUTER JOIN SELECT * FROM osoby FULL OUTER JOIN ma_auto ON osoby.nazwisko=ma_auto.nazwisko; ID nazwisko N01 dział nazwisko Marka Model Nowak Kadry Nowak Nissan K01 Kowalski FK Kowalski Skoda Fabia K01 Kowalski FK Kowalski C01 Cypis BHP B01 Baca FK B02 Bąk FK Kia Baca Fiat Uno Figiel Opel Astra