Składniki diagramu ER

Diagram związków encji (ang. entity‑relationship – ER) to graficzny sposób przedstawienia modeli danych używanych w projektach informatycznych. Jego podstawowymi składnikami są:

  • encjeencjaencje – rzeczywiste lub wyobrażone obiekty oznaczane prostokątami, w bazie danych są to tabele,

  • atrybuty – cechy (właściwości) encji reprezentowane przez elipsy, w bazie danych to kolumny poszczególnych tabel,

  • złączenia – związki między encjami, oznaczane rombami lub liniami ciągłymi lub przerywanymi, w bazie danych są to relacje.

Istnieją różne konwencje tworzenia diagramów ER. Przykładowe kształty i symbole graficzne możemy zobaczyć na zrzucie.

Polecenie 1

Przeanalizuj poniższy zrzut prezentujący przykładowe kształty i symbole graficzne stosowane w różnych konwencjach tworzenia diagramów ER. Zastanów się, co mogą oznaczać litery MN.

RdZeFnstVYTbJ
Oprac. na podst.: Olczyk D., Modelowanie strukturalne – Definicje, notacja, techniki i narzędzia, „Zeszyty Naukowe Warszawskiej Wyższej Szkoły Informatyki”, nr 4, 2010.
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Dalej w materiale wykorzystujemy notację Information Engineering Style.

Modelowanie bazy

Analizę diagramu ER dla potrzeb naszej restauracji zacząć możemy od dwóch encji, tzn. klientów i zamówień.

Rqv4ytLTD0goV
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Na zrzucie widzimy, że encja Klienci może być opisana przez trzy atrybuty: Imię, NazwiskoIdentyfikator. Z kolei właściwościami encji Zamówienia mogą być Data realizacji oraz Identyfikator. Związek Zamawia łączący obydwie encje to opcjonalne złączenie typu jeden‑do‑wielu, co oznacza, że jeden klient może złożyć wiele zamówień.

Biorąc pod uwagę ustalone wcześniej wymagania naszej restauracji, do diagramu dodamy kolejne encje z atrybutami, aby zilustrować możliwość dokonywania rezerwacji przez klientów:

  • Stoliki, atrybuty: NumerLiczba miejsc,

  • Rezerwacje, atrybuty: IdentyfikatorTermin,

  • Rabaty, atrybuty: Identyfikator, Data przyznania, Data zakończenia.

Polecenie 2

Przeanalizuj poniższą grafikę i odpowiedz na pytanie: Jakie związki łączą dodane encje (Stoliki, RezerwacjeRabaty)?

RsUHdXxR84pkm
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Teraz zajmiemy się daniami oraz zamówieniami. Do diagramu dodamy następujące encje:

  • Półprodukty, atrybuty: Identyfikator, Nazwa, Liczba i Liczba kilogramów,

  • Dania, atrybuty: Identyfikator, Nazwa, Cena, Czy w menu,

  • Zamówienia, atrybuty: Identyfikator, Data realizacji, Rabat.

Związek pomiędzy daniami i półproduktami polega na tym, że danie może składać się z wielu półproduktów, ale także jeden półprodukt może wystąpić w wielu daniach. Podobny związek łączy dania i zamówienia. Jedno zamówienie może obejmować wiele dań, z kolei to samo danie może wystąpić w wielu zamówieniach. W tego typu związkach mamy zatem do czynienia ze złączeniem N‑M, tj. wiele‑do‑wielu.

Polecenie 3

Przeanalizuj grafikę i odpowiedz na pytanie: W jaki sposób na diagramie zobrazowano złączenia wiele‑do‑wielu?

RJjSntgQVie3D
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Tabele i warunki integralności

Dotychczasowy model bazy zapisany jako diagram ER może wyglądać następująco:

RSxBJxcPmMBeR1
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Uwzględnia on etap normalizacji danych, tzn. wyodrębniono encje, np. Stoliki czy Rabaty, aby wyeliminować powtarzanie się danych. Na diagramie wskazano również klucze główne poszczególnych encji poprzez podkreślenie odpowiednich atrybutów. Klucze obce występują na diagramie jako związki łączące encje relacjami.

Na podstawie diagramu ER, czyli logicznego modelu bazy, możemy przygotować jej schemat w postaci tabel. Mógłby on wyglądać następująco:

R13H3QVripTL61
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Każda encja została przekształcona na osobną tabelę. Atrybuty encji stały się polami (kolumnami) tabel. Klucze główne oznaczone zostały skrótem PK (ang. primary key), klucze obce skrótem FK (ang. foreign key). Litera N wskazuje, że pole nie może zawierać wartości NULL (ang. not null). Relacje oznaczono tak jak na diagramie. Wreszcie każdemu polu przypisano odpowiedni typ danych:

  • int – inaczej INTEGER, liczba całkowita,

  • float – liczba zmiennoprzecinkowa pojedynczej precyzji, w nawiasach podano dokładność,

  • decimal – liczba zmiennoprzecinkowa przechowywana w postaci znakowej, w nawiasach podano dokładność,

  • varchar – inaczej TEXT, ciąg znaków o zmiennej długości podawanej w nawiasach,

  • timestamp – data i czas, przechowywane w formacie RRRR‑MM‑DD GG:MM:SS.

Więcej informacji na temat typów danych i definiowania schematu bazy w języku SQL znajdziesz w serii materiałów:

Implementacja w języku SQL

Kolejnym krokiem będzie przygotowanie skryptu, w którym użyjemy instrukcji i klauzul języka SQL do zapisania i utworzenia tabel, pól, relacji oraz określenia warunków integralności.

Ważne!

Nazwy i składania instrukcji oraz klauzul języka SQL różnią się w zależności od wybranego systemu bazodanowego. W naszym przypadku będziemy używali bazy SQLite, o której więcej możesz się dowiedzieć z multimedium zawartego w materiale Instrukcje wyszukiwania w języku SQL, etap IPQU2IRer7Instrukcje wyszukiwania w języku SQL, etap I.

Kolejność tworzenia tabel ma znaczenie ze względu na warunki integralności, na początku powinny być tworzone tabele, które nie zawierają kluczy obcych. Zaczniemy od grupy tabel związanych z klientami i rezerwacjami.

Linia 1. DROP TABLE IF EXISTS klienci średnik. Linia 2. CREATE TABLE klienci otwórz nawias okrągły. Linia 3. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 4. imie TEXT NOT NULL przecinek. Linia 5. nazwisko TEXT NOT NULL. Linia 6. zamknij nawias okrągły średnik. Linia 8. DROP TABLE IF EXISTS stoliki średnik. Linia 9. CREATE TABLE stoliki otwórz nawias okrągły. Linia 10. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 11. l podkreślnik miejsc INTEGER NOT NULL DEFAULT 0. Linia 12. zamknij nawias okrągły średnik. Linia 14. DROP TABLE IF EXISTS rezerwacje średnik. Linia 15. CREATE TABLE rezerwacje otwórz nawias okrągły. Linia 16. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 17. termin TIMESTAMP NOT NULL DEFAULT CURRENT podkreślnik TIMESTAMP przecinek. Linia 18. id podkreślnik stolika INTEGER przecinek. Linia 19. id podkreślnik klienta INTEGER przecinek. Linia 20. FOREIGN KEY otwórz nawias okrągły id podkreślnik stolika zamknij nawias okrągły REFERENCES stoliki otwórz nawias okrągły id zamknij nawias okrągły ON DELETE CASCADE przecinek. Linia 21. FOREIGN KEY otwórz nawias okrągły id podkreślnik klienta zamknij nawias okrągły REFERENCES klienci otwórz nawias okrągły id zamknij nawias okrągły ON DELETE CASCADE. Linia 22. zamknij nawias okrągły średnik. Linia 24. DROP TABLE IF EXISTS rabaty średnik. Linia 25. CREATE TABLE rabaty otwórz nawias okrągły. Linia 26. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 27. data podkreślnik od TIMESTAMP NOT NULL DEFAULT CURRENT podkreślnik TIMESTAMP przecinek. Linia 28. data podkreślnik do TIMESTAMP NOT NULL DEFAULT CURRENT podkreślnik TIMESTAMP przecinek. Linia 29. id podkreślnik klienta INTEGER przecinek. Linia 30. FOREIGN KEY otwórz nawias okrągły id podkreślnik klienta zamknij nawias okrągły REFERENCES klienci otwórz nawias okrągły id zamknij nawias okrągły ON DELETE CASCADE. Linia 31. zamknij nawias okrągły średnik.

Zadaniem klauzul DROP jest usunięcie podanej tabeli, jeżeli znajduje się już w bazie, co będzie przydatne podczas tworzenia interfejsu. Klauzule CREATE TABLE tworzą tabele o podanych polach. Nazwy pól ze względu na późniejsze ich wykorzystanie w kodzie aplikacji internetowej ujednolicamy i skracamy – np. wszystkie klucze główne nazywają się id, a klucze obce nazywamy wg schematu id_nazwa.

W większości przypadków nakładamy na pola warunki integralności:

  • PRIMARY KEY – klucz główny, pole nie może zawierać wartości NULL i wartości nie mogą się powtarzać,

  • AUTOINCREMENT – wartość pola (kolejne liczby naturalne) jest tworzona automatycznie przez bazę,

  • FOREIGN KEY (klucz_obcy) REFERENCES tabela(klucz_glowny) – wskazanie klucza obcego, czyli utworzenie relacji między tabelami,

  • ON DELETE CASCADE – jeżeli klucz główny w tabeli nadrzędnej zostanie usunięty, usunięte zostaną również wszystkie powiązane rekordy z tabeli zależnej,

  • NOT NULL – jak wspominaliśmy, pole nie może przechowywać wartości NULL, tj. nie może być puste,

  • DEFAULT – określenie wartości domyślnej wprowadzanej w polu przez bazę, jeżeli wartość ta nie zostanie podana,

  • CURRENT_TMESTAMP – zwraca aktualną datę i czas w formacie znakowym RRRR‑MM‑DD GG:MM:SS, np.: 2023‑07‑18 14:16:52.

Oprócz użytych i omówionych warunków mamy również ograniczenie UNIQUE nakładane w tabeli na pole lub kilka pól, w których wartości nie mogą się powtarzać, ale mogą zawierać wartość NULL. Warunek może również występować w polach klucza obcego.

Po tych wyjaśnieniach możemy zaimplementować tabele dań i zamówień:

Linia 1. DROP TABLE IF EXISTS polprodukty średnik. Linia 2. CREATE TABLE polprodukty otwórz nawias okrągły. Linia 3. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 4. nazwa TEXT NOT NULL przecinek. Linia 5. l podkreślnik kg FLOAT otwórz nawias okrągły 5 przecinek 2 zamknij nawias okrągły. Linia 6. zamknij nawias okrągły średnik. Linia 8. DROP TABLE IF EXISTS dania średnik. Linia 9. CREATE TABLE dania otwórz nawias okrągły. Linia 10. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 11. nazwa TEXT NOT NULL przecinek. Linia 12. cena DECIMAL otwórz nawias okrągły 5 przecinek 2 zamknij nawias okrągły DEFAULT 0 przecinek. Linia 13. menu BOOLEAN NOT NULL CHECK otwórz nawias okrągły menu IN otwórz nawias okrągły 0 przecinek 1 zamknij nawias okrągły zamknij nawias okrągły. Linia 14. zamknij nawias okrągły średnik. Linia 16. DROP TABLE IF EXISTS sklady podkreślnik dan średnik. Linia 17. CREATE TABLE sklady podkreślnik dan otwórz nawias okrągły. Linia 18. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 19. l podkreślnik kg FLOAT otwórz nawias okrągły 5 przecinek 2 zamknij nawias okrągły przecinek. Linia 20. id podkreślnik dania INTEGER przecinek. Linia 21. id podkreślnik polproduktu INTEGER przecinek. Linia 22. FOREIGN KEY otwórz nawias okrągły id podkreślnik dania zamknij nawias okrągły REFERENCES dania otwórz nawias okrągły id zamknij nawias okrągły ON DELETE CASCADE przecinek. Linia 23. FOREIGN KEY otwórz nawias okrągły id podkreślnik polproduktu zamknij nawias okrągły REFERENCES polprodukty otwórz nawias okrągły id zamknij nawias okrągły ON DELETE CASCADE. Linia 24. zamknij nawias okrągły średnik. Linia 26. DROP TABLE IF EXISTS zamowienia średnik. Linia 27. CREATE TABLE zamowienia otwórz nawias okrągły. Linia 28. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 29. id podkreślnik klienta INTEGER NOT NULL przecinek. Linia 30. data TIMESTAMP NOT NULL DEFAULT CURRENT podkreślnik TIMESTAMP przecinek. Linia 31. rabat DECIMAL otwórz nawias okrągły 5 przecinek 2 zamknij nawias okrągły DEFAULT 0 przecinek. Linia 32. FOREIGN KEY otwórz nawias okrągły id podkreślnik klienta zamknij nawias okrągły REFERENCES klienci otwórz nawias okrągły id zamknij nawias okrągły ON DELETE CASCADE. Linia 33. zamknij nawias okrągły średnik. Linia 35. DROP TABLE IF EXISTS sklady podkreślnik zamowien średnik. Linia 36. CREATE TABLE sklady podkreślnik zamowien otwórz nawias okrągły. Linia 37. id INTEGER PRIMARY KEY AUTOINCREMENT przecinek. Linia 38. id podkreślnik zamowienia INTEGER przecinek. Linia 39. id podkreślnik dania INTEGER przecinek. Linia 40. liczba INTEGER DEFAULT 1 przecinek. Linia 41. FOREIGN KEY otwórz nawias okrągły id podkreślnik zamowienia zamknij nawias okrągły REFERENCES zamowienia otwórz nawias okrągły id zamknij nawias okrągły ON DELETE CASCADE przecinek. Linia 42. FOREIGN KEY otwórz nawias okrągły id podkreślnik dania zamknij nawias okrągły REFERENCES zamowienia otwórz nawias okrągły id zamknij nawias okrągły ON DELETE CASCADE. Linia 43. zamknij nawias okrągły średnik.

W powyższym kodzie wyjaśnienia wymagają dwie rzeczy. Pierwsza to definicja pola, które przechowuje informacje o tym, czy danie jest dostępne w menu: menu BOOLEAN NOT NULL CHECK (menu IN (0, 1)). Jest to pole logiczne, które może przyjmować tylko dwie wartości podane w klauzuli CHECK IN, tzn. 0 – FAŁSZ lub 1 – PRAWDA.

Druga rzecz to dodatkowe pole o nazwie liczba w tablicy sklady_zamowien, które pozwoli na zapisanie liczby tych samych dań w danym zamówieniu.

Na koniec cały omówiony wyżej zestaw instrukcji SQL obejmiemy transakcją, tzn. na początku skryptu dodamy klauzulę BEGIN;, a na końcu COMMIT;. Dzięki temu zmiany w bazie danych, tj. utworzenie tabel, zostaną zatwierdzone tylko wtedy, kiedy wszystkie instrukcje zostaną poprawnie wykonane.

Przygotowany kod SQL zapiszmy na dysku w pliku restauracja.sql.

Utworzenie bazy i tabel

W następnym materiale zajmiemy się tworzeniem aplikacji internetowej, która pozwoli na utworzenie bazy i wygodne korzystanie z niej bez znajomości poleceń SQL. Jednak już teraz możemy sprawdzić poprawność utworzonego kodu za pomocą wiersza poleceń bazy SQLite lub programu SQLiteStudio. Narzędzia te omówione zostały na początku materiału Definiowanie schematu bazy danych w języku SQL, etap IIPkXbedRKMDefiniowanie schematu bazy danych w języku SQL, etap II.

W przypadku wiersza poleceń bazy SQLite w katalogu ze skryptem zawierającym omówione wyżej instrukcje SQL otwieramy terminal i wydajemy polecenie:

Linia 1. sqlite3 restauracja kropka db otwórz nawias ostrokątny restauracja kropka sql.

Wynikiem działania będzie utworzenie bazy w pliku restauracja.db i wykonanie w niej instrukcji SQL zawartych w skrypcie restauracja.sql. Jeżeli skrypt zawierał będzie błędy składniowe, wyświetlony zostanie odpowiedni komunikat. Po utworzeniu bazy i tabel możemy ją otworzyć za pomocą wiersza poleceń i wykonywać w niej różne operacje, np.:

Linia 1. sqlite3 restauracja kropka db. Linia 2. sqlite zamknij nawias ostrokątny kropka table. Linia 3. sqlite zamknij nawias ostrokątny kropka schema klienci. Linia 4. sqlite zamknij nawias ostrokątny INSERT INTO klienci VALUES otwórz nawias okrągły NULL przecinek apostrof Adam apostrof przecinek apostrof Kowalski apostrof zamknij nawias okrągły średnik. Linia 5. sqlite zamknij nawias ostrokątny SELECT asterysk FROM klienci średnik. Linia 6. sqlite zamknij nawias ostrokątny kropka quit.

Znaczenie kolejnych instrukcji:

  • .table – pokazuje listę tabel,

  • .schema [nazwa_tabeli] – pokaże kod SQL, który posłużył do utworzenia wszystkich tabel lub opcjonalnie podanej tabeli,

  • .quit – wyjście z wiersza poleceń bazy,

  • INSERT, SELECT – klauzule SQL, których używamy do dodawania i odczytywanie danych z tabel.

RseOVnslxwOaF
Operacje na bazie przy użyciu wiersza poleceń.
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Drugie rozwiązanie polega na skorzystaniu z programu SQLiteStudio. Po jego uruchomieniu wybieramy polecenie Baza danych / Dodaj bazę danych i w polu plik wpisujemy albo wskazujemy ścieżkę oraz podajemy nazwę pliku bazy danych, np. restauracja.db. Po kliknięciu OK zostanie utworzona pusta baza danych w podanym pliku, a jej nazwa pojawi się w panelu Bazy danych po lewej stronie okna programu.

R1SDdS7Uze0vv
Otwieranie / tworzenie bazy danych w SQLiteStudio.
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Nazwę bazy w panelu dwa razy klikamy, aby się z nią połączyć, i otwieramy okno edytora SQL: Narzędzia / Otwórz edytor SQL. Następnie do pola Zapytanie wklejamy zawartość skryptu restauracja.sql lub wczytujemy ją po wybraniu polecenia Wczytaj SQL z pliku dostępnego pod ikoną katalogu na pasku narzędzi edytora. Wszystkie polecenia zaznaczamy np. naciskając CTRL+A i wykonujemy klikając przycisk Wykonaj zapytanie lub naciskając F9.

RkVxDNv569asU
Wykonanie wielu instrukcji SQL w edytorze SQL programu SQLiteStudio.
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Utworzone tabele możemy przeglądać po wybraniu ich z listy w lewym panelu. Poniżej widać pola tabeli zamowienia:

RTow5RLWbnAOp1
Widok struktury tabeli zamowienia w programie SQLiteStudio.
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

Słownik

atrybut kluczowy
atrybut kluczowy

pole (lub kombinacja pól) zawierające niepowtarzalne wartości, jednoznacznie identyfikujące rekordy tabeli; najczęściej zawiera kolejne wartości liczbowe automatycznie tworzone przez aparat bazy danych

encja
encja

(ang. entity) schematyczny opis rzeczywistych lub abstrakcyjnych obiektów za pomocą tzw. atrybutów lub własności wskazujących ich cechy

klucz główny
klucz główny

kolumna w tabeli, w której żaden rekord nie może się powtarzać; służy on jako identyfikator wierszy; może to także być wiele kolumn, takich, że żadne dwa wiersze nie posiadają wszystkich wartości takich samych w tych kolumnach (oznacza to, że wartości klucza głównego nie mogą być takie same dla dwóch różnych rekordów)

normalizacja bazy danych
normalizacja bazy danych

modyfikacja bazy tak, aby spełniała reguły jednej z postaci normalnych; pozwala to na usunięcie powtórzeń z bazy, zwiększenie jej spójności oraz przejrzystości; seria e‑materiałów Normalizacja Baz Danych omawia w szczegółach ten proces