Normalizacja i postacie normalne.

Poprawność modeu danych

Przystępując do procesu projektowania nowej bazy danych, czyli tworzenia nowego modelu danych, należy dążyć do zapewnienia jego podstawowych cech:

Wszelkie działania mające na celu realizację powyższych założeń powinny zostać podjęte na samym początku procesu projektowania, w ścisłym kontakcie z przyszłym użytkownikiem. Po skonstruowaniu modelu danych użytkownicy powinni rozumieć utworzony model danych i po dokładnym przeanalizowaniu wszystkich szczegółów, biorąc za to odpowiedzialność, zatwierdzić go. Z kolei projektant bazy danych musi traktować uzgodniony z użytkownikami model danych, jako wierny obraz rzeczywistości i dla tego modelu budować bazę danych i wszystkie aplikacje z nią współpracujące.

Normalizacja

Postulat normalizacji daje się wyrazić w następujący sposób:

Każdy fakt przechowywany w bazie danych powinien być wyrażalny w niej tylko na jeden sposób.

Przedstawienie zasad normalizacji wymaga zastosowania formalnego, matematycznego modelu relacji. W wersji uproszczonej zostanie on zaprezentowany w dalszej części tego wykładu. Konieczność przeprowadzenia normalizacji, oraz jej zasady wprowadzimy najpierw poprzez przykłady.

Jeżeli w modelu danych istnieje możliwość wystąpienia problemów podobnych do wynikających z powyższych przykładów, oznacza to istnienie błędów w konstrukcji takiego modelu. Mówimy tu o przyjęciu w modelu złych schematów relacji (tabel).

Tabele o złych schematach

Problem złych schematów tabel zaprezentujemy na dwóch przykładach. Klucz główny schematów będzie zaznaczany pogrubioną czcionką.

Problem złych schematów tabel zaprezentujemy na dwóch przykładach. Klucz główny schematów będzie zaznaczany pogrubioną czcionką.

Przykład 1

Schemat relacji definiowany jest następująco:

Dostawcy_Towary = {Nazwa_dostawcy, Nazwa_towaru, Adres_dostawcy, Cena}

Implementacją tego schematu jest tabela, z przykładowymi danymi.

Tabela 7.1 Relacja opisana przez schemat Dostawcy_Towary

Nazwa_dostawcy Adres_dostawcy Nazwa_Towaru Cena
Kowalski Krótka 1 Telewizor 3000
Kowalski Krótka 1 Pralka 2000
Jaworski Długa 12 Lodówka 2500
Jaworski Długa 12 Zmywarka 2800
Kowalski Krótka 1 Lodówka 1800
Piotrowski Polna 33 Laptop 4500

Analizując przykładowe dane zapisane według powyższego schematu, łatwo jest zidentyfikować jego wady, które utrudnią eksploatację danych i uniemożliwią realizację postulatów opisanych na początku tego rozdziału.

Przyczyną powstania tych wad jest zły schemat relacji, który łączy w jednej encji atrybuty dwóch różnych rodzajów (klas) obiektów (encji) – dostawców i towarów.

Rozwiązanie stanowi poprawienie schematu, polegające na rozłożeniu wyjściowego schematu na dwa. Każdy z nowych schematów reprezentuje osobny typ obiektów, czyli odpowiednio dostawców i towary.

Dostawcy = {Nazwa_dostawcy, Adres}

Towary = {Nazwa_dostawcy, Nazwa_towaru, Cena}

Implementacją tych schematów będą dwie tabele, zawierające rozdzielone dane.

Tabela 7.2 Dane dostawców.

Nazwa_dostawcy Adres_dostawcy
Kowalski Krótka 1
Kowalski Krótka 1
Jaworski Długa 12
Jaworski Długa 12
Kowalski Krótka 1
Jaworski Polna 33

Tabela 7.3 Dane towarów.

Nazwa_dostawcy Nazwa_Towaru Cena
Kowalski Telewizor 3000
Kowalski Pralka; 2000
Jaworski Lodówka; 2500
Jaworski Zmywarka 2800
Jaworski Lodówka 1800
Jaworski Laptop 4500

Przykład 2

Schemat relacji definiowany jest następująco:

Pracownicy = {Id_pracownika, Nazwisko, Nazwa_uczelni, Adres}

Implementacją tego schematu jest tabela, z przykładowymi danymi.

Tabela 7.4 Relacja opisana przez schemat Pracownicy.

Id_pracownika Nazwisko Uczelnia Adres_uczelni
102 Kowalski PJWSTK Koszykowa 86
103 Kalinowski PW Nowowiejska 24
112 Jaworski PJWSTK Koszykowa 86
105 Makowski PJWSTK Koszykowa 86
105 Piotrowski PW Nowowiejska 24

Tak jak w poprzednim przykładzie, tutaj też możemy zaobserwować podobne wady jak poprzednio, mimo, że tym razem klucz główny jest jednoelementowy.

Przyczyną tych wad także jest zły schemat relacji, łączący w jednej encji dwa różne rodzaje (klas) obiektów (encji), czyli pracowników i uczelni.

Rozwiązaniem, tak jak i poprzednio, jest rozłożenie początkowego schematu na dwa, z których każdy reprezentuje osobny typ obiektów, czyli odpowiednio pracowników i uczelnie.

Pracownicy = {Id_pracownika, Nazwisko, Uczelnia}

Uczelnie = {Uczelnia, Adres}

Implementacją tych schematów będą także dwie tabele, zawierające rozdzielone dane.

Tabela 7.5 Dane pracowników:

Id_pracownika Nazwisko Uczelnia
102 Kowalski PJWSTK
103 Kalinowski PW
112 Jaworski PJWSTK
105 Makowski PJWSTK
121 Piotrowski PW

Tabela 7.6 Dane uczelni:

Uczelnia Adres_uczelni
PJWSTK Koszykowa 86
PW Nowowiejska 24

Wyjaśnienie złych schematów

Przyczyny występowania błędów w schematach wyjaśnimy wprowadzając pojęcie zależności funkcyjnych częściowej i przechodniej.

Zależność częściowa

Dla schematu:

Dostawcy_towary = {Nazwa_dostawcy, Nazwa_towaru, Adres_dostawcy, Cena}

kluczem jest para atrybutów: Nazwa_dostawcy i Nazwa_towaru, a atrybut Adres_dostawcy zależy od części klucza - od atrybutu Nazwa_dostawcy. Wartość atrybutu Nazwa_dostawcy jednoznacznie określa wartość atrybutu Adres_dostawcy, czyli znając nazwę dostawcy, znamy również jego adres.

Mówimy, że wartość atrybutu Adres zależy częściowo od klucza:

Nazwa_dostawcy -> Adres_dostawcy

a samą zależność nazywamy zależnością częściową. Po przeniesieniu atrybutów: Nazwa_dostawcy i Adres_dostawcy do osobnej encji, atrybut Nazwa_dostawcy staje się kluczem, a zależność częściowa Nazwa_dostawcy -> Adres_dostawcy staje się zależnością od całego klucza.

Korekta złego schematu Dostawcy_towary poprzez rozłożenie go na dwa powiązane schematy Towary i Dostawcy.

Rysunek 7.1 Rozłożenie "złego" schematu na dwa, nie zawierające zależności częściowych

Korekta złego schematu Dostawcy_towary poprzez rozłożenie go na dwa powiązane schematy Towary i Dostawcy.

Zależność przechodnia

Dla schematu tabeli:

Pracownicy = {Id_pracownika, Nazwisko, Uczelnia, Adres_uczelni}

Kluczem jest atrybut Id_pracownika, a atrybut Adres_uczelni zależy od innego atrybutu Uczelnia, który nie jest kluczem. Wartość atrybutu Uczelnia jednoznacznie określa wartość atrybutu Adres_uczelni, czyli znając nazwę uczelni, znamy także jej adres.

Mówimy w takim przypadku, że wartość atrybutu Adres zależy przechodnio od klucza:

 Uczelnia -> Adres_uczelni

a samą zależność nazywamy zależnością przechodnią. Po przeniesieniu atrybutów: Nazwa_uczelni i Adres do osobnej encji, atrybut Nazwa_uczelni staje się kluczem, a zależność częściowa Nazwa_uczelni-> Adres staje się zależnością od całego klucza.

Korekta złego schematu Pracownicy poprzez rozłożenie go na dwa powiązane schematy Pracownicy i Uczelnie.

Rysunek 7.2 Rozłożenie "złego" schematu na dwa, nie zawierające zależności przechodnich.

Korekta złego schematu Pracownicy poprzez rozłożenie go na dwa powiązane schematy Pracownicy i Uczelnie.

Korektę schematów zawierających atrybuty zależne przechodnio lub częściowa, można opisać następująco:

Atrybut wzajemnie zależne przenieś do nowej encji, w której atrybut stojący po lewej stronie zależności jest kluczem. Utwórz związek encji nowej i wyjściowej, w którym nowa encja będzie encją nadrzędną (po stronie „jeden”). Jeżeli zależność była zależnością częściową, związek będzie identyfikujący.

 Realizacja tego rozwiązania pokazana jest na powyższym rysunku.

Reasumując, istnienie zależności częściowych i przechodnich wskazuje, że schemat tabel ma niepoprawne właściwości. Poprawne są tylko zależności funkcyjne od całego klucza. Stwierdzenie istnienia w schemacie bazy danych takich zależności, wskazuje na konieczność rozłożenia istniejących schematów na takie, które opisują pojedyncze klasy obiektów, oraz wprowadzenie związków pomiędzy nimi.

Formalny model relacyjny bazy danych

Relacja a tabela

Relacja jest abstrakcyjnym, matematycznym pojęciem zawierającym w sobie istotę modelu relacyjnego. Relacyjna baza danych to zbiór relacji.

Tabela jest konkretną reprezentacją relacji – jedna relacja ma (może mieć) wiele różnych reprezentacji za pomocą tabel.

W relacji kolejność wierszy i kolejność kolumn są nieistotne. Dwa wiersze w tabeli zawierające te same wartości są uznawane za identyczne, to znaczy za ten sam element relacji.

Schemat relacji

Schematem relacji nazywamy listę

R = {A1, A2, ...., An}

Gdzie A1, A2, ...., An są atrybutami (nazwami kolumn).

Na przykład:

Tabela 7,6 Relacja opisana przez schemat Loty

Flight From To Departure Arrival
BA0849 WAW (Warsaw) Htw (London) 07:30 09:15
BA0847 Htw (London) WAW (Warsaw)‏ 12:25 14:00
AF1247 WAW (Warsaw) CDG (Paris) 07:05 09:30
AF1246 CDG (Paris) WAW (Warsaw)‏ 18:40 20:55
LO0006 WAW (Warsaw)‏ JFK (New York) 12:50 16:20
LO0007 JFK (New York) WAW (Warsaw)‏ 18:40 09:05 +1
LH710 FRA (Frankfurt) NRT (Tokyo) 13:45 07:40 +1
LH711 NRT (Tokyo) FRA (Frankfurt) 09:45 14:25
LO3907 WAW (Warsaw)‏   08:30 09:20

Moglibyśmy zmienić kolejność wierszy w tabeli. Moglibyśmy zmienić kolejność kolumn w tej tabeli. I nie miałoby to żadnego znaczenia dla relacji, będącej zawartością tabeli. Będzie to ciągle ta sama relacja.

Dziedziny atrybutów

Każdemu atrybutowi A przyporządkowana jest dziedzina oznaczana przez Dom(A), czyli zbiór dopuszczalnych wartości atrybutu A.

Np:

Dom(Flight) = CHAR(10)

Dom(From) = CHAR(15)

Dom(To) = CHAR(15)

Dom(Departure) = DATE/TIME

Dom(Arrival) = DATE/TIME

Dziedzina relacji

Dziedziną relacji o schemacie:

R = {A1, A2,..., An}

nazywamy sumę dziedzin wszystkich atrybutów relacji

Dom(R) = Dom(A1) U Dom(A2) U ... U Dom(An)‏

gdzie znak „U” oznacza operację sumowania zbiorów.

Relacja

Relacją o schemacie:

R = {A1, A2,..., An}

nazywamy skończony zbiór

r = {t1, t2,...,tm}

takich odwzorowań

ti: R -> Dom(R)‏

że dla każdego

j, 1 <= j <= n, ti(Aj) należy do dziedziny Dom(Aj)‏

Każde takie odwzorowanie t nazywa się krotką (lub wierszem).

Krotka

Krotka odpowiada wierszowi (rekordowi) w tabeli. Można ją formalnie określić przez podanie wartości dla poszczególnych atrybutów np.

t(Flight) = BA0849

t(From) = Warsaw

t(To) = London

t(Departure) = 07:30

t(Arrival) = 09:15

Tabela 7.7  Graficzne przedstawienie opisanej krotki.

Flight From To Departure Arrival
BA0849 WAW (Warsaw) Htw (London) 07:30 09:15

Ograniczenie krotki

Ograniczeniem krotki t relacji r o schemacie R do zbioru atrybutów X z R nazywamy odwzorowanie będące ograniczeniem t do zbioru atrybutów X

t|x: X -> Dom(R)

to znaczy t|x(x) = t(x) dla x w X, a dla x w (R – X) wartość t|x(x) jest nieokreślona.

Na przykład, gdy:

X = {From, To}

to dla krotki t z poprzedniego przykładu

t|x (From) = Warsaw t|x (To) = London

Tabela 7.8 Graficzne przedstawienie ograniczenia krotki.

From To
WAW (Warsaw) Htw (London)

Zależność funkcyjna

Relacja r o schemacie R = {A1, A2,..., An} spełnia zależność funkcyjną

X -> Y (X, Y - podzbiory R)‏

jeśli dla każdych dwóch krotek t, u relacji r spełniony jest warunek:

Jeśli t|X = u|X to t|Y = u|Y

to znaczy, w ramach krotek relacji r wartości atrybutów zbioru X determinują jednoznacznie wartości atrybutów zbioru Y.

W przykładowej relacji Loty, wartości atrybutu Flight jednoznacznie identyfikują cały lot, a więc w szczególności jednoznacznie identyfikują wartości wszystkich atrybutów tej relacji:

Flight -> {From, To, Departure, Arrival}

Przykład zależności funkcyjnej

Relacja Znaki Zodiaku o schemacie:

ZnakiZodiaku = {Id, Imię, Nazwisko, DzienUrodzenia, ZnakZodiaku}.

Mamy do czynienia z zależnością funkcyjną

DzieńUrodzenia -> ZnakZodiaku

czyli temu samemu dniu urodzenia odpowiada zawsze ten sam znak zodiaku.

Znaki zodiaku

Rysunek 7.3 Tabela pokazująca zależność znaku zodiaku od dnia urodzenia.

Tabela 7.8 Tabela pokazująca zależność znaku zodiaku od dnia urodzenia.

Id Imie Nazwisko DzienUrodzenia ZnakZodiaku
1 Jan Kowalski 23 stycznia Wodnik
2 Anna Pawłowska 1 kwietnia Baran
3 Krzysztof Tomaszewski 23 kwietnia Byk
4 Agata Jaworska 31 lipca Lew
5 Hermenegilda Kociubińska 13 kwietnia Baran
6 Apolinary Paprocki 5 września Panna
7 Onufry Zawacki 13 kwietnia Baran

W rzeczywistości mamy tutaj do czynienia z czymś więcej, mianowicie z funkcją

f: DzieńUrodzenia -> ZnakZodiaku

przyporządkowującą dniu urodzenia znak zodiaku. Jednak ta funkcja nie daje się wyrazić za pomocą zależności funkcyjnej w sensie podanej powyżej definicji.

Identyfikacja zależności funkcyjnych

W procesie projektowania, dla każdego schematu relacji, identyfikujemy zbiór spełniających ją zależności funkcyjnych (zależny od konkretnego zastosowania). Na przykład dla relacji Loty identyfikujemy następujący zbiór zależności funkcyjnych między jej atrybutami:

{Flight} -> {From, To, Departure, Arrival}

{From, To, Departure} -> {Flight, Arrival}

{From, To, Arrival} -> {Flight, Departure}

Często jest stosowana skrócona forma zapisu polegająca na opuszczaniu przecinków i nawiasów klamrowych:

Flight -> From To Departure Arrival

From To Departure -> Flight Arrival

Nadklucz relacji

Nadkluczem relacji r o schemacie R = {A1, A2,..., An}

nazywamy każdy dowolny zbiór atrybutów

X z R

taki, że zachodzi zależność funkcyjna

X -> R

Inaczej mówiąc, wartość każdego atrybutu ma być jednoznacznie zdeterminowana przez wartości atrybutów zbioru X. Jednym z nadkluczy jest zawsze zbiór wszystkich atrybutów R.

Klucz relacji

Kluczem relacji r o schemacie R = {A1, A2,..., An}

nazywamy każdy minimalny nadklucz (nie zawierający w sobie żadnego innego nadklucza). Oznacza to, że zbiór atrybutów X jest kluczem, jeżeli wartość każdego atrybutu w R jest jednoznacznie zdeterminowana przez wartości atrybutów zbioru X i żaden podzbiór zbioru X nie ma już tej własności. Zawsze istnieje co najmniej jeden nadklucz - całe R, stąd wniosek, że istnieje co najmniej jeden minimalny nadklucz, czyli klucz. Jednak kluczy może być więcej, jak to pokazuje przykład relacji Loty. Zależności funkcyjne schematu Loty określają trzy klucze:

{Flight} {From, To, Departure} {From, To, Arrival}

Klucze relacji i klucz główny

Dla każdej relacji możemy arbitralnie wyróżnić jeden spośród kluczy. Wyróżniony klucz nazywa się kluczem głównym. Wchodzące w jego skład atrybuty są w zapisach schematów relacji podkreślane lub pogrubiane.

Dla relacji Loty wybieramy jako klucz główny atrybut Flight:

Loty = {Flight, From, To, Departure, Arrival}

Należy podkreślić fakt, że klucz główny to rola, arbitralnie narzucana podczas projektowania schematu relacji. Kluczy kandydujących do tej roli może być wiele, ale wybrany zostaje tylko jeden. Przy wyborze kierujemy się głównie wygodą użytkowania, o której w dużej mierze decyduje liczba atrybutów wchodzących w skład klucza (im mniej, tym lepiej), a także typ danych (preferowane typy liczb naturalnych).

Znaczenie zależności funkcyjnych

Zależność od czegokolwiek innego niż klucz wprowadza wewnętrzną zależność między atrybutami tabeli. Powoduje możliwość determinowania wartości jednych atrybutów przez inne, czyli redundancję.

Pokazuje to tabelka, w której istnieje zależność X -> Y.

Zależność funkcyjna

Rysunek 7.4 Schematyczne przedstawienie roli zależności funkcyjnych.

Jeśli X nie jest nadkluczem, to przedstawiona w tabelce sytuacja oznacza redundancję. Wartość w polu oznaczonym przez "?" jest już jednoznacznie zdeterminowana – musi to być y. Natomiast, gdy X jest nadkluczem, to przedstawiona sytuacja jest niemożliwa. Nie mogą istnieć dwa różne wiersze z tą samą wartością klucza.

„Złe” zależności funkcyjne

Zależności „nie od klucza”

Zależność funkcyjna X -> Y jest zależnością od klucza, jeśli zbiór atrybutów X jest nadkluczem.

Zależność funkcyjna X -> Y jest zależnością nie od klucza, jeśli:

Istnieją dwa typy zależności nie od klucza:

Poprawa "złych" schematów

W schematach Dostawcy i Pracownicy występują zależności nie od klucza, odpowiednio:

Nazwa_dostawcy -> Adres_dostawcy (zależność częściowa)‏

Uczelnia -> Adres_uczelni (zależność przechodnia)‏

Poniżej przedstawiamy eliminację ze schematów relacji zależności „nie od klucza” dla przykładowych schematów.

Schemat dostawców

Dostawcy_towary {Nazwa_dostawcy, Nazwa_towaru, Adres_dostawcy, Cena}

dodajemy schemat

Dostawcy {Nazwa_dostawcy, Adres_dostawcy}

i usuwamy z oryginalnego schematu atrybut Adres_dostawcy, otrzymując schemat:

Towary {Nazwa_dostawcy, Towar, Cena}.

Schemat pracowników

Pracownicy = {Id_pracownika, Nazwisko, Nazwa_uczelni, Adres}

dodajemy schemat tabeli

Uczelnia {Uczelnia, Adres_uczelni}

i usuwamy z oryginalnego schematu atrybut Adres_uczelni, otrzymując schemat:

Pracownicy {Id_pracownika, Nazwisko, Uczelnia}.

Reasumując:

Metoda eliminowania „złych” zależności polega na wprowadzeniu dla zależności (częściowej lub przechodniej) osobnego schematu i usunięciu atrybutu stojącego po prawej stronie tej zależności z oryginalnego schematu.

Dostawcy = {Nazwa_dostawcy, Adres_dostawcy, Towar, Cena}.

Cross

Dostawcy = {Nazwa_dostawcy, Adres_dostawcy}

Towary = {Nazwa_dostawcy,Towar, Cena}.

W ten sposób zależności funkcyjne dyktują, jakie powinny być tabele w schemacie bazy danych. Najlepszym rozwiązaniem jest sytuacja, w której każda zależność funkcyjna określa pojedynczy schemat tabeli.

Postacie normalne

Postać normalna Boyce’a – Codd’a

Relacja o schemacie R znajduje się w postaci normalnej Boyce'a-Codda, jeśli nie zawiera zależności nie od klucza, czyli dla każdej zależności

X -> A w schemacie relacji R (gdzie X podzbiór R, A atrybut w R) zachodzi

albo

albo

Jeśli schemat relacji znajduje się w postaci normalnej Boyce'a-Codda, nie można w tabeli przewidzieć jednych wartości w oparciu o inne, chociaż jak to będzie pokazane dalej, nie mamy gwarancji, że nie będzie innego rodzaju redundancji niż zależność funkcyjna.

Przykłady schematów w postaci normalnej Boyce'a-Codda:

 F: Id_prac -> Nazwisko Funkcja Stanowisko

F: Flight -> From To Departure Arrival

F: From To Departure -> Flight Arrival

F: From To Arrival -> Flight Departure

Schemat niedający się sprowadzić do postaci normalnej Boyce’a-Codda

Nie każdy schemat tabeli da się sprowadzić do zbioru schematów tabel w postaci normalnej Boyce’a - Codda, bez utraty zawartych w tabelach informacji i z zachowaniem zależności funkcyjnych. Na przykład schematem takim jest

MUK = {Miasto, Ulica, Kod}

z zależnościami:

Miasto, Ulica -> Kod

Kod -> Miasto

Istnieją tutaj dwa klucze:

{Miasto, Ulica}

{Kod, Ulica}

Ze względu na zależność

Kod -> Miasto

schemat MUK nie jest w postaci normalnej Boyce'a-Codda. Tego schematu nie daje się rozłożyć z zachowaniem zależności funkcyjnych, ponieważ jedna z zależności funkcyjnych obejmuje wszystkie atrybuty.

Trzecia postać normalna

Atrybut kluczowy jest to atrybut wchodzący w skład jednego z kluczy relacji (tabeli). Relacja o schemacie R znajduje się w trzeciej postaci normalnej, jeśli wszystkie zależności nie od klucza są między atrybutami kluczowymi, tj. dla każdej zależności X -> A w schemacie relacji R (gdzie X podzbiór R, A atrybut w R) zachodzi:

Albo

Albo

Albo

W trzeciej postaci normalnej wykluczony jest więc przypadek zależności:

X -> A

Gdzie:

Zatem takich zależności należy poszukiwać, w celu przekształcenia schematu relacji ze "złej" zależności na dwie relacje.

Postać normalna B – C vs III-cia postać normalna

Przykład zależności funkcyjnej:

Kod -> Miasto

w schemacie MUK wskazuje, że schemat ten nie jest w postaci normalnej Boyce’a-Codda, ale jest w trzeciej postaci normalnej, bo atrybut Miasto jest atrybutem kluczowym – należy do jednego z kluczy:

{Miasto, Ulica}

Natomiast następujący schemat R, nie jest w trzeciej postaci normalnej.

R = {A,B,C,D}

F: AB -> C; B -> D; BC - >A

Kluczami są AB i BC. Istnieje zależność B -> D a D nie jest atrybutem kluczowym, B nie jest kluczem.

Czyli w powyższej relacji istnieje zależność częściowa, czyli relacja nie jest w trzeciej postaci normalnej (nie jest również w drugiej).

Pierwsza i druga postać normalna

Dla „porządku nomenklatury” wypada jeszcze uporządkować pojęcie pierwszej i drugiej postaci normalnej. I tak:

Pierwsza postać normalna

Tabela jest w pierwszej postaci normalnej, jeśli nie dopuszcza istnienia wartości nieatomowych. Jej istnienie to jeden z postulatów Codd’a.

Druga postać normalna

Schemat relacji jest w drugiej postaci normalnej, jeśli nie zawiera zależności funkcyjnych częściowych.

Brak "złych" zależności funkcyjnych nie gwarantuje jeszcze braku redundancji i anomalii. Zilustrujemy jeszcze dwa rodzaje zależności:
Wielowartościowe oznaczające brak Czwartej Postaci Normalnej

Złączeniowe oznaczające brak Piątej Postaci Normalnej‏

Ich istnienie implikuje redundancje i anomalie. Pominiemy dokładne definicje ograniczając się do przykładów.

Czwarta postać normalna

Schemat relacji znajduje się w czwartej postaci normalnej, jeśli nie zawiera zależności wielowartościowych.

Brak czwartej postaci normalnej

Rysunek 7.5 Relacja zawierająca zależności wielowartościowe.

Przedstawiony schemat relacji jest w postaci normalnej Boyce’a-Codda, bo jedynym kluczem są wszystkie trzy atrybuty, a jednak w tabeli jest redundancja i możliwe są anomalie!

W relacji:

R = {Nr_stud, Przedmiot, Sport}

mamy do czynienia z tak zwanymi zależnościami wielowartościowymi:

Nr_stud ->> Przedmiot; Nr_stud ->> Sport

Powyższy schemat R nie jest zatem w czwartej postaci normalnej. Aby wyeliminować zależności wielowartościowe rozkładamy R na dwie relacje o schematach:

{Nr_stud, Przedmiot}

i

{Nr_stud, Sport}.

Piąta postać normalna (zależności złączeniowe)


Zależność złączeniowa jest uogólnieniem zależności wielowartościowej w tym sensie, że jej eliminacja polega na rozbiciu relacji na więcej niż dwie relacje. Rozważmy zależności pomiędzy dostawcami, produktami i projektami, oraz przyjmijmy następującą zasadę biznesową:

jeżeli

to

Trzeba podkreślić, że zdefiniowane powyżej reguły nie wynikają z żadnych innych przesłanek, niż nasza wiedza o zależnościach zachodzących w modelowanej rzeczywistości.

Brak piątej postaci normalnej

Rysunek 7.6 Relacja zawierająca zależności złączeniowe.

Przy tych zasadach zapis informacji w tabeli jest redundantny, bo jeżeli:

to redundantna jest już informacja, że:

Rozwiązanie problemu eliminacji zależności złączeniowych

Rozwiązaniem problemu jest podział relacji na trzy relacje:

  1. {Dostawca, produkt}
  2. {Dostawca, projekt}
  3. {Projekt, produkt}

Podział na tylko dwie relacje jest niewystarczający!

W relacjach (1) - (3) nie ma już redundancji, a ich złączenie daje wyjściową relację.

Sytuacja uległaby zmianie gdybyśmy chcieli przechowywać informację o ilości lub cenie zamówionych produktów dla danego projektu u konkretnego dostawcy. Wówczas rozbicie na trzy relacje nie byłoby możliwe.

Granice normalizacji

Normalizacji nie doprowadza się czasem do końca, np:

  1. gdy stosuje się replikacje danych (planową i kontrolowaną!)
  2. gdy funkcje na danych preferują nieznormalizowane schematy relacji, na przykład gdy przy każdym wypisywaniu informacji o towarze załączamy także adres dostawcy.

Jeśli tak postępujemy, to musimy się liczyć ze wszystkimi konsekwencjami pozostawienia nieznormalizowanej tabeli i dlatego wszystkie zależności nie od klucza muszą być sprawdzane przy każdej modyfikacji bazy danych i wszystkie pozostające anomalie muszą mieć przygotowane specjalne traktowanie, np. przy użyciu dodatkowych tabel do obsługi anomalii wstawiania i usuwania i / lub procedur obsługujących anomalie.

Innym zagadnieniem baz o strukturze nieznormalizowanej, sa hurtownie danych, omawaine w oddzielnym wykładzie.