Rozdział 3
Wskazówki i przykłady tworzenia diagramów związków encji
Narzędziem wykorzystywanym do tworzenia diagramów jest MS Visio. Opis narzędzia znajduje się w poprzednim rozdziale. Tutaj skupiam się na fazie tworzenia samego diagramu.
Wstęp
Tworzenie poprawnych diagramów związków encji nie jest łatwe. Moi studenci bardzo często prosili mnie o wskazanie im książki, w której mogliby znaleźć kilka przykładów z opisem jak zostały one stworzone. Ponieważ wśród wielu pożytecznych i ciekawych skądinąd tomów nie znalazłam takiego, w którym rozwiązano by pewną liczbę zadań dotyczących modelowania diagramów związków encji, postanowiłam sama coś dla nich napisać. Efektem tej pracy jest tenże rozdział. Mam nadzieję, że ktoś z niego skorzysta.
Dodatek ten zawiera osiem przykładowych zadań wraz z rozwiązaniami. Są one ułożone według stopnia trudności. Pierwsze trzy przykłady, które zatytułowałam Geografia, Hotel i Drużyny piłkarskie są typowo „akademickie”. Biblioteka jest również przykładem mającym łatwy opis problemu, aczkolwiek sam diagram jest już nieco bardziej rozbudowany. Kolejne zadania, czyli Plan zajęć i Komunikacja miejska, są oczko trudniejsze. Przede wszystkim w treści zadania podany jest wykaz funkcji, które będzie musiała zrealizować nasza baza, a nie opis liczności związków. Poza tym diagram planu zajęć jest relatywnie dość rozbudowany. Ogólnie jednak pierwsze sześć zadań to zadania standardowe. Dwa ostatnie przykłady - Koktajle i Urząd Stanu Cywilnego - odbiegają nieco od schematu. Nie są może trudne, ale dość ciekawe, gdyż przy ich tworzeniu najbardziej liczy się pomysł rozwiązania.
Dziękuję Lechowi Banachowskiemu i Elżbiecie Mrówce-Matejewskiej za pomoc i cenne uwagi dotyczące tego rozdziału. Dziękuję również moim studentom, bez których inspiracji na pewno by on nie powstał.
1. Geografia
Opracuj schemat bazy danych Geografia. Uwzględnij wiadomości o państwach, miastach, morzach, językach urzędowych i kontynentach, wiedząc, że:
Jedno państwo leży na jednym lub wielu kontynentach.
Każde miasto znajduje się w jednym państwie.
Każdy język może być językiem urzędowym dla jednego lub wielu państw, a każde państwo może mieć jeden lub wiele języków urzędowych.
Każde morze oblewa jedno lub kilka państw, natomiast państwo może graniczyć z jednym, z kilkoma lub z żadnym z mórz (uwzględnij długość granicy morskiej).
Pierwszym etapem tworzenia diagramu związków encji jest zidentyfikowanie encji, które będą nam potrzebne. W tym zadaniu mamy wyraźnie powiedziane, że musimy uwzględnić wiadomości o państwach, miastach, morzach, językach urzędowych i kontynentach, a zatem bez trudu wyodrębniamy encje: Panstwo, Miasto, Morze, Jezyk i Kontynent. Musimy jednak zdawać sobie sprawę, że tak naprawdę to podczas projektowania realnego systemu informacje o potrzebnych encjach musimy wyłowić z rozmów z przyszłymi użytkownikami tegoż systemu. Wróćmy jednak do naszego przykładu. Wiemy już jakie encje będziemy uwzględniać. Teraz przyszedł czas na określenie atrybutów każdej z nich. Czyli będziemy zastanawiać się, jakie wiadomości chcemy trzymać o państwach, miastach, morzach, językach urzędowych i kontynentach. Musimy pamiętać o dwóch podstawowych zasadach:
Atrybut powinien opisywać encję, przy której się go umieszcza!
Chodzi o to, żeby nie umieszczać w encji atrybutów, które od niej nie zależą, bądź zależą od niej tylko częściowo. Nikt zapewne nie wpisze do encji Panstwo atrybutu NrRejestracyjnySamochodu, bo to nie miałoby sensu. Ale już np. czy taką DługośćGranicyzMorzem należy dać jako atrybut państwa czy morza czy może encji asocjacyjnej? Tu mógłby pojawić się problem. W tym przypadku musimy dokładnie zastanowić się, o co nam chodzi. Jeśli chodzi nam o długość granicy morskiej państwa, wyrażony jedną liczbą dla każdego państwa (np. 1222 km), to jest to atrybut encji Panstwo i tam go umieszczamy. Ale jeśli chodzi nam o długość granicy państwa z każdym oblewającym go morzem, to wtedy musimy naszą DługośćGranicyzMorzem umieścić jako atrybut encji łączącej państwo i morze, ponieważ zależy ona i od morza i od państwa jednocześnie. Inna sprawa, że czasem jest problem. Bo np. czy NumerTelefonu w pracy jest atrybutem pokoju czy pracownika?
W pierwszej fazie projektowania identyfikuje się tylko atrybuty opisujące daną encję!
Tutaj chodzi o to, aby nie wpisywać kluczy obcych (przychodzących z innej tabeli). Np. w encji Miasto, nie należy wpisywać atrybutu Panstwo, ponieważ ten atrybut reprezentuje związek encji Miasto z encją Panstwo. A więc nie traktuje się go jako atrybut opisujący encję Miasto, ale atrybut opisujący związek.
Na tym etapie projektowania diagramu trzeba jeszcze zastosować zasadę zwaną pierwszą postacią normalną: Każdy atrybut musi zawierać wartość jednostkową. Oznacza to, że nie wolno nam np. w encji Pracownik umieszczać pola takiego jak DzieciPracownika, ponieważ pracownik może mieć wiele dzieci. Należy też unikać pól segmentowych, takich jak np. ImieINazwisko.
Dla każdej encji warto również ustalić klucz główny (jednoznaczny identyfikator).
Po zastosowaniu wszystkich tych wskazówek nasz diagram wygląda tak:
Kolejnym niezmiernie istotnym etapem tworzenia diagramu jest zidentyfikowanie związków między encjami. Pamiętajmy, że bardzo często podczas projektowania diagramów związków encji, my sami musimy znaleźć zależności pomiędzy poszczególnymi encjami. Bardzo rzadko zostanie nam podana tak dokładna specyfikacja (czyli opis problemu) jak w tym zadaniu. Najczęściej klient poda nam, co powinno być możliwe do wykonania po stworzeniu systemu, a my w rozmowie z nim musimy ustalić jak kolejne encje (oczywiście w rozmowie z klientem unikamy tego słowa) łączą się ze sobą. Niektóre rzeczy są jasne od razu, niektóre zaś trzeba przedyskutować, poczynić pewne założenia. W naszym zadaniu podano nam następującą specyfikację:
Jedno państwo leży na jednym lub wielu kontynentach.
Każde miasto znajduje się w jednym państwie.
Każdy język może być językiem urzędowym dla jednego lub wielu państw, a każde państwo może mieć jeden lub wiele języków urzędowych.
Każde morze oblewa jedno lub kilka państw, natomiast państwo może graniczyć z jednym, z kilkoma lub z żadnym z mórz.
Niektóre zależności nie zostały napisane, ale są one dość oczywiste. Np. nikt nie ma wątpliwości, że w jednym państwie jest wiele miast.
Napiszmy kolejno związki łączące nasze encje:
Encja 1 |
Encja 2 |
Opis związku |
Typ związku |
Panstwo |
Miasto |
W jednym państwie jest wiele miast (oczywiste). |
związek jednoznaczny (jedno państwo - wiele miast, jedno miasto - jedno państwo) |
|
|
Każde miasto znajduje się w jednym państwie (podane w zadaniu). |
|
Panstwo |
Język |
Każde państwo może mieć jeden lub wiele języków urzędowych (podane w zadaniu). |
związek wieloznaczny (jedno państwo - wiele języków, jeden język - wiele państw) |
|
|
Każdy język może być językiem urzędowym dla jednego lub wielu państw (podane w zadaniu). |
|
Panstwo |
Morze |
Państwo może graniczyć z jednym, z kilkoma lub z żadnym z mórz (podane w zadaniu). |
związek wieloznaczny (jedno państwo - wiele mórz, jedno morze - wiele państw) |
|
|
Każde morze oblewa jedno lub kilka państw (podane w zadaniu). |
|
Panstwo |
Kontynent |
Jedno państwo leży na jednym lub wielu kontynentach (podane w zadaniu). |
związek wieloznaczny (jedno państwo - wiele kontynentów, jeden kontynent - wiele państw) |
|
|
Na jednym kontynencie leży wiele państw (oczywiste). |
|
Teraz zastanawiamy się, analizując podany opis problemu, czy to już wszystkie zależności. Jeśli tak, to przechodzimy do łączenia encji na diagramie. Wiemy, że w przypadku związku jednoznacznego prowadzimy relację między encjami będącymi stronami związku. Jak opisano wcześniej, w Visio po stronie jeden jest strzałka. W przypadku związku wieloznacznego tworzymy tabelę pośrednią (asocjacyjną). Mimo, że niektóre narzędzia (np. Oracle Designer) same tworzą tabelę pośrednią, więc na etapie projektowania można po prostu wprowadzić relację wiele do wiele, należy pamiętać, że związków wieloznacznych nie można bezpośrednio reprezentować w relacyjnej bazie danych. Jedynie dysponując narzędziem, które na etapie generowania tabel tworzy tabelę pośrednią, możemy pozwolić sobie na diagramie na relację wiele do wiele. Możemy zapytać, który sposób stosować, jeśli już w ogóle mamy możliwość wyboru? Otóż, jeśli wystarczy nam, aby w wygenerowanej później tabeli pośredniej, znalazły się jedynie klucze tabel, które ona łączy, to możemy wykorzystać relację wiele do wiele. W naszym przykładzie taka sytuacja miałaby miejsce w przypadku relacji łączącej encje Panstwo i Kontynent oraz Panstwo i Jezyk. Jeśli natomiast chcemy, aby nasza encja pośrednia miała poza kluczami obcymi jakieś dodatkowe atrybuty, wówczas sami tworzymy encję asocjacyjną. W rozpatrywanym przykładzie encja łącząca Panstwo i Morze ma atrybut Długosc_Granicy (wymieniony w treści zadania), mówiący o długości granicy danego państwa z danym morzem, więc, niezależnie od używanego narzędzia, powinna zostać stworzona ręcznie. MS Visio nie potrafi samodzielnie generować tabel pośrednich, w związku z powyższym zawsze musimy narysować encję asocjacyjną, niezależnie od występowania w niej dodatkowych atrybutów. O tej
drugiej możliwości wspominam z uwagi na to, że w załączniku znajdują się te same diagramy w notacji Oracle Designera. Pełny diagram wygląda tak:
Jak widzimy, w tabelach pojawiły się klucze obce z adnotacją FK. Warto wspomnieć, że Oracle Designer nie wpisuje kluczy obcych podczas tworzenia relacji (patrz załącznik). Natomiast umieszcza je w tabelach podczas ich generowania.
2. Hotel
W hotelu jest potrzebna baza danych. Mają się w niej znaleźć informacje o gościach, pokojach podzielonych na kategorie (zaproponuj je), rezerwacjach zamówionych - na kategorię i rezerwacjach przydzielonych - na konkretny pokój. Zaproponuj schemat bazy w trzeciej postaci normalnej, dodatkowo wiedząc, że:
Każdy pokój ma jedną kategorię, ale w każdej kategorii może być wiele pokoi
Gość może dokonywać rezerwacji na wiele kategorii
Gościowi może być kilka razy przydzielony ten sam pokój w różnych terminach
Gościowi przydzielany jest pokój, nie kategoria
Tak jak powiedzieliśmy wcześniej, musimy najpierw zidentyfikować encje, które będą nam potrzebne. W zadaniu czytamy, że mamy gromadzić informacje o gościach, pokojach podzielonych na kategorie, rezerwacjach zamówionych - na kategorię i rezerwacjach przydzielonych - na konkretny pokój. A więc potrzebne nam będą encje: Gosc, Pokoj, Kategoria, Rezerwacja_Zamowiona i Rezerwacja_Przydzielona. Teraz kolej na określenie, jakie informacje chcemy zbierać, czyli na ustalenie atrybutów. Pamiętamy, że nie wpisujemy atrybutów reprezentujących związki (kluczy obcych). Ostatecznie w tej fazie projektowania otrzymujemy diagram:
Zauważmy, że w encji Pokoj nie ma atrybutu Kategoria. Wynika to właśnie stąd, że Kategoria jest atrybutem związku łączącego encję Pokoj z encją Kategoria.
Teraz przystąpimy do etapu identyfikowania związków między encjami. Tym razem też mamy dość dokładną specyfikację, choć może już nie tak klarowną jak w poprzednim przykładzie:
Każdy pokój ma jedną kategorię, ale w każdej kategorii może być wiele pokoi
Gość może dokonywać rezerwacji na wiele kategorii
Gościowi może być kilka razy przydzielony ten sam pokój w różnych terminach
Gościowi przydzielany jest pokój, nie kategoria
Encja 1 |
Encja 2 |
Opis związku |
Typ związku |
Kategoria |
Pokoj |
W każdej kategorii może być wiele pokoi (podane w zadaniu). |
związek jednoznaczny (jedna kategoria - wiele pokoi, jeden pokój - jedna kategoria) |
|
|
Każdy pokój ma jedną kategorię (podane w zadaniu). |
|
Gosc |
Kategoria |
Każdy pokój ma jedną kategorię (podane w zadaniu). |
związek wieloznaczny (jeden gość - wiele kategorii, jedna kategoria - wielu gości) |
|
|
Jedna kategoria może być zamawiana przez wielu gości (oczywiste). |
|
Gosc |
Pokoj |
Gościowi może być kilka (czyli wiele) razy przydzielony ten sam pokój (w różnych terminach) (podane w zadaniu). |
związek wieloznaczny (jeden gość - wiele pokoi, jeden pokój - wielu gości) |
|
|
Jeden pokój może być przydzielany wielu gościom (w różnych terminach) (oczywiste). |
|
Warto zwrócić uwagę, że w powyższej tabeli nie uwzględniliśmy encji Rezerwacja_Zamowiona i Rezerwacja_Przydzielona. Ale czymże tak naprawdę jest Rezerwacja_Zamowiona? Otóż niczym innym niż reprezentacją opisanego związku wieloznacznego pomiędzy encjami Gosc i Kategoria, czyli naturalną encją pośrednią pomiędzy nimi. Możemy więc pominąć ją w powyższym wykazie. Analogiczna sytuacja ma miejsce w przyypadku encji Rezerwacja_Przydzielona, tyle, że jest ona encją asocjacyjną pomiędzy encjami Gosc i Pokoj.
Żeby dobrze zrozumieć ideę tego diagramu trzeba już cokolwiek wiedzieć o funkcjonowaniu hotelu. Ewentualnie, w przypadku braku informacji, poczynić pewne założenia. Przede wszystkim należy wiedzieć (przynajmniej na potrzeby tego zadania), że nawet jeśli w jednym pokoju zamieszka więcej osób, to przydzielany jest on jednej (zamawiającej). Stąd jeden pokój może być przydzielany wielu gościom w różnych terminach. W jednym terminie przydzielany jest jednemu gościowi. Druga ważna informacja podana została na końcu specyfikacji: gościowi przydzielany jest pokój, nie kategoria. I tu i na początku zadania wyraźnie sugeruje się stworzenie oddzielnie zamówień (na kategorię) i przydziałów (na pokój). Wszak gość zamawiając pokój w hotelu rzadko życzy sobie konkretnego pokoju (np. 223), znacznie częściej zamawia kategorię (np. apartament). A oto jak przedstawia się nasz diagram.
Drużyny piłkarskie.
Zaproponuj diagram związków encji do gromadzenia informacji na temat rozgrywek piłkarskich. Uwzględnij informacje o drużynach, piłkarzach, meczach oraz „czerwonych kartkach”. Zaproponuj schemat bazy danych w trzeciej postaci normalnej pamiętając, że:
W jednej drużynie jest wielu piłkarzy.
Jeden piłkarz gra w dokładnie jednej drużynie.
Jeden piłkarz gra w wielu meczach.
W jednym meczu gra wielu piłkarzy.
W jednym meczu grają dwie drużyny.
Piłkarz w danym meczu może dostać maksimum jedną „czerwona kartkę”.
„Czerwona kartka” może być w danym meczu przyznana wielu piłkarzom.
I znów na początku identyfikujemy encje, które będą nam potrzebne. W zadaniu czytamy, że mamy gromadzić informacje o drużynach, piłkarzach, meczach oraz „czerwonych kartkach”. A więc potrzebne nam będą encje: Druzyna, Pilkarz oraz Mecz. To w bezpośredni sposób możemy wyczytać z treści zadania. Możemy również, choć nie musimy, stworzyć osobną encję, w której będziemy gromadzić nazwy miejscowości, w których rozgrywają się mecze i w których powstały drużyny. Wprawdzie moglibyśmy nazwę miejscowości umieścić jako atrybut encji Druzyna i Mecz, ale warto stworzyć dla nich osobną encję, zwana encją słownikową, aby uniknąć błędów wynikających z nieuwagi piszącego, no i dla wygody tegoż ostatniego.
Mamy zatem encje, określmy jeszcze ich atrybuty, pomijając te, które reprezentują związki. Ostatecznie w tej fazie projektowania otrzymujemy diagram:
Łatwo zauważyć, że pominęliśmy encję Czerwona_Kartka, mimo, że w zadaniu jest wyraźnie wspomniane o gromadzeniu informacji na ten temat. Przyjrzyjmy się jednak czym właściwie jest „czerwona kartka”. W zadaniu czytamy, że piłkarz w danym meczu może dostać maksimum jedną „czerwona kartkę” oraz, że w jednym meczu „czerwoną kartkę” może dostać wielu piłkarzy. A zatem fakt jej otrzymania nie jest atrybutem ani samego piłkarza (nie jest do niego przypisana na stałe, a poza tym może mieć ich wiele), ani samego meczu (w jednym meczu może być ich wiele). Jest ona atrybutem piłkarza i meczu jednocześnie. I tam też (czyli w encji asocjacyjnej Granie, którą stworzymy ręcznie) umieścimy fakt jej otrzymania. Nie musimy też tworzyć osobnej encji Czerwona_Kartka, bo składałaby się ona tylko z jednego rekordu, więc nie bardzo miałaby sens.
Zidentyfikujmy związki między encjami. Znów nie będzie to trudne, ponieważ mamy bardzo wyraźne wskazówki. Przypatrzmy się im:
W jednej drużynie jest wielu piłkarzy.
Jeden piłkarz gra w dokładnie jednej drużynie.
Jeden piłkarz gra w wielu meczach.
W jednym meczu gra wielu piłkarzy.
W jednym meczu gra dwie drużyny.
Piłkarz w danym meczu może dostać maksimum jedną „czerwona kartkę”.
„Czerwona kartka” może być w danym meczu przyznana wielu piłkarzom.
Encja 1 |
Encja 2 |
Opis związku |
Typ związku |
Pilkarz |
Druzyna |
Każdy piłkarz gra w dokładnie jednej drużynie (podane w zadaniu). |
związek jednoznaczny (jedna drużyna - wielu piłkarzy, jeden piłkarz - jedna drużyna) |
|
|
W każdej drużynie gra wielu piłkarzy (podane w zadaniu). |
|
Pilkarz |
Mecz |
Jeden piłkarz gra w wielu meczach (podane w zadaniu). |
związek wieloznaczny (jeden piłkarz - wiele meczy, jeden mecz - wielu piłkarzy) |
|
|
W jednym meczu gra wielu piłkarzy (podane w zadaniu). |
|
Druzyna |
Mecz |
W jednym meczu gra dwie drużyny (podane w zadaniu) |
Związek liczności 2 |
|
|
Jedna drużyna rozgrywa wiele meczy (oczywiste) |
|
Druzyna |
Miejscowosc |
Każda drużyna jest z jednej miejscowości (możemy tak przyjąć) |
związek jednoznaczny (jedna miejscowość - wiele drużyn, jedna drużyna - jedna miejscowość) |
|
|
W każdej miejscowości może być wiele drużyn (oczywiste). |
|
Mecz |
Miejscowosc |
Każdy mecz rozgrywa się w jednej miejscowości (oczywiste). |
związek jednoznaczny (jedna miejscowość - wiele meczy, jeden mecz - jedna miejscowość) |
|
|
W jednej miejscowości może być rozegranych wiele meczy. |
|
Po uważnym prześledzeniu poprzednich przykładów bez trudu możemy stworzyć ten diagram. Jedynym miejscem, w którym możemy mieć wątpliwości jest powiązanie pomiędzy drużyną a meczem. W tabelce pojawił się napis: Związek liczności 2. Wiemy, skądinąd, nie tylko z tego zadania, że w jednym meczu gra zawsze dwie drużyny. Czy zatem dwie to wiele? Czy warto tworzyć pomiędzy encją Druzyna, a encją Mecz encję asocjacyjną z informacją, czy dana drużyna jest w danym meczu gościem, czy gospodarzem? Można by było, ale można też rozwiązać ten problem inaczej. Ponieważ tamto rozwiązanie było już omówione, przyjrzyjmy się rozwiązaniu alternatywnemu (i w tym kontekście chyba lepszemu). Skoro wiemy, że drużyn w meczu jest zawsze dwie, możemy połączyć encje Druzyna i Mecz dwiema relacjami (nazywając klucze obce „Druzyna_Gosci” i „Druzyna_Gospodarzy”).
Warto może przypomnieć, że w przypadku, kiedy dwie encje połączone są dwoma związkami, w MS Visio trzeba ręcznie nazwać klucze obce, przy czym jeden z nich należy również ręcznie dodać i później połączyć. Procedura ta opisana jest w poprzednim rozdziale. W Oracle Designerze problemu rzecz jasna nie ma, bo obydwa klucze obce widać dopiero na poziomie tabel i wówczas są oba.
4. Biblioteka
Zaprojektuj diagram związków encji dla Biblioteki uwzględniając informacje o książkach, tj. dostępnych tytułach, autorach, tłumaczach, redaktorach i innych osobach zaangażowanych w tworzenie książki, wydawnictwach, egzemplarzach książek występujących w bibliotece, czytelnikach i wypożyczeniach. Uwzględnij następujące fakty:
Każda książka ma jednego lub więcej autorów (tłumaczy, ilustratorów, itd.).
Każda książka jest wydana przez jedno wydawnictwo, ale wydawnictwo może wydać wiele książek.
Każda książka pisana jest w dokładnie jednym języku.
Książka należy do jednej dziedziny, ale dziedziny mają swoje dziedziny nadrzędne.
W bibliotece może być wiele egzemplarzy jednej książki, ale dany egzemplarz dotyczy dokładnie jednej książki.
Czytelnik wypożycza wiele egzemplarzy, egzemplarz jest wypożyczany przez wielu czytelników (oczywiście nie jednocześnie).
Jak zwykle na początku sprawdźmy, jakie encje będą nam potrzebne. Mamy uwzględnić informacje o książkach, tj. dostępnych tytułach, autorach, tłumaczach, redaktorach i innych osobach zaangażowanych w tworzenie książki, wydawnictwach, egzemplarzach książek występujących w bibliotece, czytelnikach i wypożyczeniach. Zwróćmy szczególną uwagę na fakt, że czytelnik nie wypożycza książek, ale ich konkretne egzemplarze. Czym innym jest książka, jako tytuł wydany w pewnym wydawnictwie (dobrze opisuje to numer ISBN), a czym innym jej konkretny egzemplarz, który bierzemy do ręki. Tych egzemplarzy danej książki może być w bibliotece wiele. Po tej informacji bez trudu wyodrębnimy encje: Ksiazka, Egzemplarz, Wydawnictwo, Czytelnik i Wypozyczenie. Bez trudu też określimy dla nich atrybuty. Pozostaje pytanie co zrobić z tymi autorami, tłumaczami, redaktorami i innymi osobami zaangażowanymi w tworzenie książki. Autor pisze wiele książek, ale zdarza się, że i książka ma wielu autorów (patrz książka, którą trzymasz w ręku). Nie możemy zatem umieścić autora pośród atrybutów encji Ksiazka. Podobnie jest z tłumaczem i innymi osobami zaangażowanymi w tworzenie książki. Jak zatem poradzić sobie z tym problemem? Tworzyć osobne encje: Autor, Tlumacz, Redaktor, itd.? Ale jedna osoba może być i tłumaczem i autorem, jak choćby autorzy tej książki. To może stworzyć encję Tworca i umieścić tam dane tych wszystkich osób? Ale gdzie trzymać informację kto jest autorem, a kto tłumaczem? W encji Tworca na pewno nie, bo to, czy się jest autorem, czy tłumaczem, nie zależy jedynie od twórcy. Zależy także od książki. A zatem widzimy, że rolę należałoby umieścić w encji asocjacyjnej, łączącej twórcę z książką. Na rysunku jest taka encja. Nazywa się Autorstwo. W niej określimy rolę, jaką pełni dana osoba w danym dziele. Na tym etapie nasz diagram wygląda jak następuje:
Po przyjrzeniu się naszej pracy możemy dojść do wniosku, że warto byłoby wprowadzić pewną korektę. Mianowicie stworzyć tabele słownikowe: Jezyk, Dziedzina i Rola. W przypadku języka i roli jest to tylko i wyłącznie spowodowane wygodą i chęcią uniknięcia pomyłek przy wpisywaniu danych. W przypadku dziedziny jest to konieczne z uwagi na to, że dziedziny mają swoje dziedziny nadrzędne, jak zostało podane w treści zadania. Wprowadźmy zatem nasze korekty i zobaczmy jak wygląda zmieniona część diagramu:
Widzimy, że z encji Ksiazka zniknęły atrybuty Dziedzina i Jezyk, a z encji Autorstwo - atrybut Rola. Będą one na naszym diagramie reprezentowane przez odpowiednie związki. Warto też zwrócić uwagę na rozwiązanie problemu dotyczącego dziedziny nadrzędnej. Stworzyliśmy hierarchię dziedzin. Każda dziedzina ma bezpośrednio nad sobą co najwyżej jedną dziedzinę. Może spójrzmy na przykładowe dane w tabeli Dziedzina:
Id_Dziedziny |
Dziedzina |
Dziedzina_Nadrzedna |
|
Matematyka |
|
2 |
Analiza Matematyczna |
1 |
3 |
Rachunek Prawdopodobieństwa |
1 |
4 |
Rachunek Różniczkowy |
2 |
6 |
Informatyka |
|
7 |
Bazy Danych |
6 |
8 |
Oracle |
7 |
Ten przykład chyba wystarczająco ilustruje, w jaki sposób czytać taki związek tabeli samej ze sobą (czyli związek rekurencyjny). Na koniec przyjrzyjmy się specyfikacji i na tej podstawie zdefiniujmy związki pomiędzy naszymi encjami:
Każda książka ma jednego lub więcej autorów (tłumaczy, ilustratorów, itd.).
Każda książka jest wydana przez jedno wydawnictwo, ale wydawnictwo może wydać wiele książek.
Każda książka pisana jest w dokładnie jednym języku.
Książka należy do jednej dziedziny, ale dziedziny mają swoje dziedziny nadrzędne.
W bibliotece może być wiele egzemplarzy jednej książki, ale dany egzemplarz dotyczy dokładnie jednej książki.
Czytelnik wypożycza wiele egzemplarzy, egzemplarz jest wypożyczany przez wielu czytelników (oczywiście nie jednocześnie).
Encja 1 |
Encja 2 |
Opis związku |
Typ związku |
Ksiazka |
Dziedzina |
Książka należy do jednej dziedziny (podane w zadaniu). |
związek jednoznaczny (jedna dziedzina - wiele książek, jedna książka - jedna dziedzina) |
|
|
W każdej dziedzinie napisano wiele książek (oczywiste). |
|
Dziedzina |
Dziedzina |
Dziedziny mają swoje dziedziny nadrzędne (możemy przyjąć, że co najwyżej jedną). |
związek jednoznaczny |
Ksiazka |
Wydawnictwo |
Każda książka jest wydana przez jedno wydawnictwo (podane w zadaniu). |
związek jednoznaczny (jedna dziedzina - wiele książek, jedna książka - jedna dziedzina) |
|
|
Każde wydawnictwo może wydać wiele książek (podane w zadaniu). |
|
Encja 1 |
Encja 2 |
Opis związku |
Typ związku |
Ksiazka |
Jezyk |
Każda książka wydana jest w dokładnie jednym języku (podane w zadaniu). |
związek jednoznaczny (jeden język - wiele książek, jedna książka - jeden język) |
|
|
W jednym języku wydano wiele książek (oczywiste). |
|
Ksiazka |
Jezyk |
Każda książka ma dokładnie jeden język oryginału (możemy przyjąć) |
związek jednoznaczny (jeden język - wiele książek, jedna książka - jeden język) |
|
|
W jednym języku napisano wiele książek (oczywiste). |
|
Ksiazka |
Egzemplarz |
W bibliotece może być wiele egzemplarzy jednej książki (podane w zadaniu). |
związek jednoznaczny (jedna książka - wiele egzemplarzy, jeden egzemplarz - jedna książka) |
|
|
Każdy egzemplarz dotyczy dokładnie jednej książki (podane w zadaniu). |
|
Czytelnik |
Egzemplarz |
Każdy czytelnik wypożycza wiele egzemplarzy (podane w zadaniu). |
związek wieloznaczny (jeden czytelnik - wiele egzemplarzy, jeden egzemplarz - wielu czytelników) |
|
|
Egzemplarz jest wypożyczany przez wielu czytelników (podane w zadaniu). |
|
Pozostaje tylko opisać związek, który kryje się za sformułowaniem: każda książka ma jednego lub więcej autorów (tłumaczy, ilustratorów, itd.). Nieco wcześniej zastanawialiśmy się nad tym, jakie encje będą nam tu potrzebne. Doszliśmy do wniosku, że najlepszym rozwiązaniem będzie encja Tworca, gromadząca dane o osobach zaangażowanych w tworzenie książki oraz encja słownikowa Rola, przechowująca nazwy pełnionych ról (autor, tłumacz, redaktor, itd.). Pomiędzy encjami Ksiazka, Tworca i Rola tworzy się nam trójargumentowa zależność wiele do wiele. Przecież książka może mieć wielu twórców, twórca w danej książce może pełnić wiele ról, jedną rolę może pełnić wielu twórców, itd. Łatwo wymienić wszystkie sześć sytuacji, a każda wiele do wiele. Najlepszym rozwiązaniem będzie encja asocjacyjna Autorstwo, w której klucze główne encji Ksiazka, Tworca i Rola znajdą się w kluczu.
5. Plan zajęć
Opracuj schemat bazy danych dla szkoły wyższej zawierający informacje o studentach, zajęciach, prowadzących zajęcia, stopniach z zaliczeń / egzaminów, salach i godzinach odbywanych zajęć. W bazie danych powinno być możliwe wykonanie następujących zadań:
Wyświetl tygodniowy plan zajęć dla studenta (tylko w bieżącym roku akademickim, nie chcemy trzymać historii planów zajęć).
Wyświetl tygodniowy plan zajęć dla pracownika (tylko w bieżącym roku akademickim).
Wyświetl wszystkie oceny z zaliczeń / egzaminów uzyskane przez studenta (w czasie dotychczasowych studiów, w ostatnim roku).
Mając dane nazwisko i imię sprawdzić czy osoba o takim nazwisku i imieniu studiuje bądź studiowała w naszej szkole, kiedy została przyjęta, itp.
Nie uszło to chyba niczyjej uwadze, że to zadanie nie jest już takie podręcznikowe, ale bardziej przypomina to, z czym styka się projektant rzeczywistej bazy. Raczej mało prawdopodobne, aby na początku poinformowano nas, jakie są zależności między encjami. Samo pojęcie encja w ogóle nie powinno pojawić się w rozmowach z osobą zlecającą projekt. Raczej dostaniemy specyfikację wymagań i oczekiwania, co do przyszłego działania systemu. I to z tego właśnie musimy odczytać zarówno encje, jak i łączące je zależności. Z tego i z naszej wiedzy na temat funkcjonowania tworzonego systemu. No i z rozmów z przyszłymi użytkownikami. Teraz nasz problem jest nieco fikcyjny, ponieważ nie znamy przyszłych użytkowników, nie mamy więc z kim rozmawiać. Ale wszyscy chyba wiemy, jak funkcjonuje szkoła wyższa. Nie będzie więc raczej problemu z wytypowaniem encji i ich atrybutów. Tym bardziej, że w treści zadania podano nam, że mamy gromadzić informacje o studentach, zajęciach, prowadzących zajęcia, stopniach z zaliczeń / egzaminów, salach i godzinach odbywanych zajęć. Na tej podstawie z łatwością wytypujemy encje: Student, Wykładowca, Przedmiot (synonim zajęć), Ocena i Sala. Krótki rzut oka na rysunek utwierdza nas w przekonaniu, że odbiega on nieco od tego co zostało napisane. Wyjaśnijmy te nieścisłości. Ponieważ szkoła wyższa może mieć sale w różnych budynkach, pojawiła się dodatkowa encja Budynek, gromadząca informacje o budynkach. Pominięcie jej w tym zadaniu nie byłoby błędem. Wszak nic nie zostało o tym wspomniane, a nie jest to informacja na tyle oczywista, abyśmy mieli obowiązek ją wywnioskować. Encja Rok_Akademicki jest encją słownikową, jak wiemy dość przydatną. I też możemy się na nią zdecydować lub nie. Inaczej rzecz ma się z encją Grupa. Jest ona konieczna, mimo, że nic nie było o niej wspomniane w zadaniu. Jednakże jej istnienia nie wolno nam pominąć. Dlaczego? Otóż plan zajęć układany jest dla grup, a nie dla pojedynczych studentów. Musimy zatem trzymać gdzieś o nich informacje. Potrzebna jest również encja Plan, co dla nikogo nie jest chyba zaskoczeniem. Zatrzymajmy się chwilę przy kluczu głównym encji Plan. Wiemy, że klucz główny nie może być powtórzony i musi być minimalny (no i żaden atrybut klucza nie może być pusty). Faktem jest, że w danym dniu, o danej godzinie, dana grupa będzie miała co najwyżej jedne zajęcia, zatem wydaje się, że trójka Dzien_Tygodnia, Godzina_Lekcyjna i Grupa jest dobrym kandydatem na jednoznaczny identyfikator. Oczywiście przy założeniu, że nie trzymamy planów z lat poprzednich. Ale to zostało powiedziane w treści zadania. Można byłoby stworzyć jeszcze dwie encje słownikowe Dzien_Tygodnia i Godzina_Lekcyjna. W poniższym rozwiązaniu nie zostało to zrealizowane. Na koniec przyjrzyjmy się encji Osoba. Po co tworzyć osobne encje Wykladowca i Student. Przecież wielu studentów zostaje potem wykładowcami. A niektórzy w czasie studiów (choćby doktoranckich) prowadzą ćwiczenia. Po co zatem wprowadzać ich podstawowe dane do obydwu tabel? Lepiej stworzyć encję Osoba i podencję Student oraz Wykladowca. Do encji nadrzędnej wstawiamy atrybuty wspólne dla encji podrzędnych, np. imię, nazwisko i adres, a do encji podrzędnych atrybuty dla nich charakterystyczne.
Spójrzmy na nasze encje:
Przejdźmy do definiowania związków między naszymi encjami. Wiemy, że przy użyciu naszej późniejszej bazy będziemy chcieli:
Wyświetlić tygodniowy plan zajęć dla studenta (tylko w bieżącym roku akademickim, nie chcemy trzymać historii planów zajęć).
Wyświetlić tygodniowy plan zajęć dla pracownika (tylko w bieżącym roku akademickim).
Wyświetlić wszystkie oceny z zaliczeń / egzaminów uzyskane przez studenta (w czasie dotychczasowych studiów, w ostatnim roku).
Mając dane nazwisko i imię sprawdzić czy osoba o takim nazwisku i imieniu studiuje bądź studiowała w naszej szkole, kiedy została przyjęta, itp.
Z tych informacji i z naszego doświadczenia dochodzimy do następujących wniosków, które przedstawię w nieco już uproszczonej formie:
Encja 1 |
Encja 2 |
Opis związku |
Typ związku |
Budynek |
Sala |
W budynku jest wiele sal. |
związek jednoznaczny |
|
|
Sala jest w jednym budynku. |
|
Grupa |
Plan |
Grupa jest na planie wiele razy. |
związek jednoznaczny |
|
|
Jeden rekord encji Plan dotyczy jednej grupy. |
|
Encja 1 |
Encja 2 |
Opis związku |
Typ związku |
Przedmiot |
Plan |
Przedmiot jest na planie wiele razy. |
związek jednoznaczny |
|
|
Jeden rekord encji Plan dotyczy jednego przedmiotu. |
|
Sala |
Plan |
Sala jest na planie wiele razy. |
związek jednoznaczny |
|
|
Jeden rekord encji Plan dotyczy jednej sali. |
|
Wykladowca |
Plan |
Jeden rekord encji Plan dotyczy jednego wykładowcy |
związek jednoznaczny |
|
|
Wykładowca ma wiele zajęć. |
|
Do powyższych związków dochodzą jeszcze związki wieloznaczne łączące trzy encje:
Encja 1 |
Encja 2 |
Encja 3 |
Encja pośrednia - tercjalna |
Student |
Grupa |
Rok Akademicki |
Sklad_Grupy |
Wykladowca |
Przedmiot |
Rok Akademicki |
Wykladanie |
Student |
Wykladanie |
Rok Akademicki |
Ocena |
Rok akademicki jest nam tu potrzebny, aby móc wyświetlić oceny studenta w czasie dotychczasowych studiów.
Powróćmy jeszcze na chwilę do związku pomiędzy Studentem a Wykladaniem. Jasne jest, że w encji Ocena mają być przechowywane informacje, który student, u którego wykładowcy, otrzymał jaką ocenę z jakiego przedmiotu, w którym roku akademickim. Widać, że tak naprawdę jest to encja łącząca studenta, przedmiot, wykładowcę i rok akademicki. W związku z tym, że diagram i tak jest skomplikowany, zdecydowałam się na połączenie encji Ocena z encją Wykladanie (w której jest informacja o przedmiocie, wykładowcy i roku akademickim jednocześnie), zamiast z trzema encjami: Wykladowca, Przedmiot i Rok_Akademicki, co byłoby równie poprawne. W następnym przykładzie zobaczymy oba alternatywne rozwiązania (tyle, że dla dwóch encji) na nieco mniej rozbudowanym schemacie.
Warto może jeszcze zwrócić uwagę na fakt, że w encji Wykladowca i Student zmieniłam nazwy kluczy głównych, mimo że nadal są to klucze obce Id_Osoba. Uczyniłam tak z uwagi na ułatwienie czytania diagramu.
6. Komunikacja Miejska
Opracuj schemat bazy danych dla komunikacji autobusowej w Warszawie zawierający informacje o liniach autobusowych, przystankach i godzinach odjazdu z nich autobusów. W bazie danych powinno być możliwe wykonanie następujących zadań:
Dla danego przystanku podać jakie linie autobusowe zatrzymują się na tym przystanku i dla każdej z tych linii - czasy odjazdów.
Dla danej linii autobusowej podać na jakich przystankach zatrzymują się autobusy tej linii i jakie są czasy odjazdu z tych przystanków.
Oto kolejny przykład, w którym powiedziano nam, co ma być możliwe do zrealizowania przy użyciu bazy, a nie - jakie są zależności pomiędzy encjami. Przyjrzyjmy się zatem czemu ma służyć nasza baza. Właściwie tylko temu, aby na przystanku wywiesić informację jakie linie autobusowe się na nim zatrzymują i dla każdej z tych linii - czasy odjazdów. Oraz dla danej linii autobusowej podać na jakich przystankach zatrzymują się autobusy tej linii i jakie są czasy odjazdu z tych przystanków. Na podstawie tej informacji bez trudu typujemy encje: Linia, Przystanek oraz Rozklad, w której wprowadzamy atrybut Godzina_Odjazdu. Ponieważ wiemy, że rozkład zależy również od dnia (dzień powszedni, niedziela, święta), musimy umieścić na nim informację o czasowym zakresie kursowania. Możemy również zdecydować się na encję słownikową Atrybut_Kursowania i tam umieścić atrybut Kiedy_Kursuje, co też zostało zrealizowane:
Zastanówmy się, już wszystko uwzględniliśmy? Czy na przystanku powiesimy rozkład jazdy? Czy dla linii podamy przystanki z godzinami odjazdów? Na pierwszy rzut oka wszystko jest, ale po uważnym przyjrzeniu się dostrzegamy, że całkowicie pominęliśmy informację o kolejności przystanków. A jak wywiesić listę przystanków dla danej linii autobusowej bez znajomości ich kolejności? Niemożliwe, prawda? A zatem musimy się tą kolejnością zająć. Na pewno nie byłoby dobrym pomysłem umieszczenie w encji Rozklad atrybutu Kolejnosc, ponieważ na danym przystanku dana linia zatrzymuje się wiele razy. Nadmiar informacji widać natychmiast. Najlepiej stworzyć osobną encję Kolejnosc_Przystankow, w której przechowamy informację o tym, który to jest przystanek dla danej linii:
Zajmijmy się relacjami łączącymi nasz encje:
Encja 1 |
Encja 2 |
Opis związku |
Typ związku |
|
Linia |
Przystanek |
Dana linia zatrzymuje się na wielu przystankach. |
Dwa związki wieloznaczne - Rozkład i Kolejność Przystanków |
|
|
|
Na danym przystanku zatrzymuje się wiele linii. |
|
|
Rozklad |
Atrybut_ Kursowania |
Jeden rekord encji Rozkład ma dokładnie jeden atrybut kursowania |
Związek jednoznaczny |
|
|
|
Jeden atrybut kursowania dotyczy wielu rozkładów. |
|
Nietrudno, na podstawie powyższych informacji zbudować taki diagram:
Możemy jednak wymodelować nasz diagram nieco inaczej:
Dlaczego takie rozwiązanie jest również poprawne? Wiemy, że kluczem encji Kolejnosc_Przystankow są Nr_Linii i ID_Przystanku. A zatem relacja łącząca encje Kolejnosc_Przystankow i Rozklad zagwarantuje nam obecność (też w kluczu) atrybutów Nr_Linii i ID_Przystanku. Czyli zagwarantuje nam dokładnie to samo, co dwie poprzednie relacje (łączącą encję Linia z encją Rozklad i encję Przystanek z encją Rozklad).
7. Koktajle.
Zaproponuj diagram związków encji dla bazy dany służącej do gromadzenia informacji dotyczącej wytwarzania koktajli alkoholowych. Baza ma zawierać dane o koktajlach (ich nazwie, rodzaju i zawartości alkoholu). Chcemy wiedzieć, z jakich składników składa się dany koktajl (alkohol, sok, inny koktajl) i w jakich proporcjach należy go wymieszać. Należy zagwarantować możliwość policzenia procentowej zawartości alkoholu w wytwarzanym koktajlu.
W pierwszej chwili po przeczytaniu tej skromnej poniekąd specyfikacji dostrzegamy kilka encji: Alkohol, Sok (jako składnik koktajlu), Koktajl oraz Skladnik (do przetrzymywania informacji co wchodzi w skład którego koktajlu i jaki jest tego udział procentowy). I problem byłby może prosty, gdyby nie to, że w skład danego koktajlu wchodzą inne koktajle. Jak to przedstawić na diagramie? A może stworzyć encję nadrzędną Napoj, w której poza nazwą wstawimy pole Procent_Alkoholu, które potrzebne nam będzie do wyliczenia procentowej zawartości alkoholu w wytwarzanym koktajlu? I trzy encje podrzędne: Sok, Alkohol i Koktajl? Zobaczmy jak wyglądają nasze nowe encje:
Powiązania pomiędzy tak skonstruowanymi encjami są już oczywiste. Dany napój występuje w wielu koktajlach w odpowiedniej ilości. W danym koktajlu wymieszanych jest wiele składników w odpowiednich proporcjach. Zatem występuje tu jeden związek wieloznaczny, przy czym encja Skladnik jest naturalną encją pośrednią. Dla formalności zobaczmy skonstruowany przez nas diagram:
Warto zwrócić uwagę, że w encji koktajl zmieniła się nazwa klucza głównego (z Id_Napoju na Id_Koktajlu). Warto dokonać takiej zmiany z uwagi na to, aby odróżnić koktajl od dowolnego napoju w encji Skladnik.
8. Urząd Stanu Cywilnego.
Zaproponuj schemat bazy danych dla USC, w której będą przechowywane podstawowe dane o obywatelach:
dane personalne,
informacje o pokrewieństwie,
informacje o miejscu zamieszkania,
informacje o małżeństwach.
Każdy obywatel może zawrzeć wiele związków małżeńskich, z tym że kolejne małżeństwo można zawrzeć dopiero po ustaniu poprzedniego. W bazie danych powinny być przechowywane także informacje o osobach zmarłych.
Z powyższej specyfikacji udaje nam się ustalić, że potrzebne są encje Obywatel, Zwiazek_Malzenski oraz ewentualnie Miejscowosc (jako encja słownikowa):
Widzimy, że w bazie opartej na takich encjach da się przechować prawie wszystkie żądane informacje. Prawie, ponieważ brakuje jednej istotnej - mianowicie informacji o pokrewieństwie. Gdzie zatem zapamiętywać, kto dla kogo jest ojcem, matką, siostrą, bratem, dziadkiem, babcią, itd.? Tworzyć osobną encję Pokrewienstwo? Spójrzmy:
Ale, czy tu nie ma informacji nadmiarowych? Czy aby na pewno musimy dla każdych dwóch osób połączonych więzami krwi opisywać, jakie to więzy. A jak jest w życiu? Czy aby dowiedzieć się, kto jest kim dla kogo w jakiejś rodzinie, musimy zapytać jaki rodzaj pokrewieństwa łączy każde dwie osoby? A może po uzyskaniu pewnych informacji, potrafimy resztę wywnioskować? Jeśli tak, to zastanówmy się jaka minimalna wiedza jest nam potrzebna. Co wystarczy wiedzieć, aby móc stwierdzić, że pan X jest dziadkiem pani Y, a pan Z bratem pana X? Po krótkim rozważeniu sprawy dochodzimy do wniosku, że musimy tylko i wyłącznie znać matkę i ojca każdej z rozpatrywanych osób (poza tymi rozpoczynającymi hierarchię rodzinną). Wówczas całe drzewo genealogiczne wygenerujemy sobie sami. A zatem sprawę pokrewieństwa można rozwiązać tak:
Na koniec rzućmy okiem na pełny diagram, który po powyższych rozważaniach nie jest już dla nikogo zaskoczeniem.
dodc-2
Dodatki