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