Przykładowa baza danych BIBLIOTEKA 1. Opis problemu W ramach zajęć zostanie przedstawiony przykład prezentujący prosty system biblioteczny. System zawiera informację o czytelnikach oraz książkach dostępnych w bibliotece. System umożliwia wypożyczenie książki czytelnikowi, śledzenie historii wypożyczeń przez czytelnika oraz historię wypożyczeń danego egzemplarza książki. Dodatkowo wprowadzono możliwość przypisania książek do odpowiednich grup tematycznych. 2. Opis encji i tabel bazodanowych w relacyjnym modelu W ramach opracowanej bazy danych wyróżniamy następujące encje główne: czytelnik (opisuje użytkownika biblioteki), książka (zawiera opis książki) i egzemplarz (opisuje poszczególne egzemplarze książek dostępnych w bibliotece). Dodatkowo wyróżnimy w projekcie dwie encje: dział ( encja słownikowa) i wypożyczenie (opisuje relację pomiędzy czytelnikiem, a konkretnym egzemplarzem książki). Na rys. 1 przedstawiono diagram ERD (Entity Relation Diagram) pomiędzy poszczególnymi encjami wyróżnionymi w projekcie. Pomiędzy encją czytelnik i wypożyczenie występuje relacja jeden do wielu czytelnik może wypożyczyć kilka książek (egzemplarzy), natomiast książka (egzemplarz) może być w danym momencie wypożyczona przez jednego czytelnika. Relacja pomiędzy egzemplarzem a książką jest typu jeden do wielu, poszczególne książki mogą mieć po kilka egzemplarzy w bibliotece. Relacja pomiędzy encjami wypożyczenie i egzemplarz jest jeden do wielu. Poszczególne egzemplarze książek mogą być wypożyczone przez różnych czytelników, oczywiście w różnym czasie. Encja dział jest encją słownikową zawierającą nazwy działów, do których przypiszemy książkę. Pomiędzy encjami książka i dział występuje relacja jeden do wielu, do jednego działu należy N książek. Rys. 1 Diagram ERD bazy danych BIBLIOTEKA Wersja 0.91 1.05.2017 Strona 1
W tabelach od 1 do 5 zostały przedstawione struktury tabel utworzone na podstawie opisanych wcześniej encji z szczegółowym opisem każdego atrybutu. Na uwagę zasługują atrybuty status występujące w tabelach WYPOZYCZENIE i EGZEMPLARZ. Atrybut status w tabeli WYPOZYCZENIE zawiera dwie wartości 1 i 2. Wartość 1 określa, że książka opisana tym rekordem jest wypożyczona określonemu w tym rekordzie czytelnikowi, natomiast wartość 2 oznacza, że książka została zwrócona do biblioteki. Natomiast atrybut status w tabeli EGZEMPLARZ posiada następujące wartości: 0 egzemplarz w bibliotece (możliwość wypożyczenia), 1 egzemplarz pożyczony. Możliwe są też dodatkowe wartości dla tego atrybutu, np. 2 egzemplarz książki dostępny tylko w bibliotece czy 3 książka zarezerwowana. id_czytelnik SERIAL PRIMARY KEY Klucz główny generowany automatycznie nazwisko NOT NULL imie NOT NULL kod_pocztowy miasto adres email Tabela 1. Tabela bazodanowa CZYTELNIK id_ksiazka SERIAL PRIMARY KEY Klucz główny generowany automatycznie tytul varchar(300) NOT NULL autor varchar(300) NOT NULL ISBN rok_wydania char(10) wydanie char(20) id_dzial Int FOREIGN KEY Klucz obcy do tabeli opisującej dział Tabela 2. Tabela bazodanowa KSIAZKA id_egzemplarz Int PRIMARY KEY Identyfikator egzemplarza w bibliotece id_ksiazka Int FOREIGN KEY Klucz obcy do tabeli książka Status Int NOT NULL Parametr opisujący stan książki Tabela 3. Tabela bazodanowa EGZEMPLARZ id_wypozyczenie SERIAL PRIMARY KEY Klucz główny generowany automatycznie id_czytelnik Int FOREIGN KEY Klucz obcy do tabeli czytelnik id_egzemplarz Int FOREIGN KEY Klucz obcy do tabeli egzemplarz data_wypozyczenie Date data_oddane Date status Int Parametr opisujący stan wypożyczenia Tabela 4. Tabela bazodanowa WYPOZYCZENIE id_dzial SERIAL PRIMARY KEY Klucz główny generowany automatycznie nazwa NOT NULL Tabela 5. Tabela bazodanowa DZIAL Wersja 0.91 1.05.2017 Strona 2
3. Wprowadzanie danych i przykładowa funkcjonalność bazy danych. 3.1. Wprowadzanie danych do bazy danych Poprawność działania bazy danych zależy od mechanizmów kontrolujących spójność i integralność danych wprowadzonych do tabel bazodanowych. W ramach przedstawionej bazy mechanizmy kontroli integralności i spójności zaimplementowano wprowadzając klucze główne, ograniczenia na poziomie atrybutów i więzy referencyjne. Poniżej przedstawiono przykładowe poprawne polecenia wprowadzające dane do bazy danych. Dane czytelnika wprowadzamy do bazy danych realizując poniższe polecenie: INSERT INTO czytelnik (imie, nazwisko,email) VALUES ('Malwina','Wierzbicka','wierzbicka@onet.pl') ; Dane książki wprowadzamy poleceniem: INSERT INTO ksiazka (tytul,autor,id_dzial) VALUES ('Duma i uprzedzenie','jane Austen',1); Uwaga. Wstawiając dane dotyczące książki należy podać numer działu( atrybut id_dzial ), do którego należy książka (więzy referencyjne z tabelą DZIAL). Wprowadzanie pozycji egzemplarza książki do tabeli EGZEMPLARZ. INSERT INTO egzemplarz (id_egzemplarz,id_ksiazka,status) VALUES (1,1,0) ; Uwaga. Wstawiając dane dotyczące egzemplarza należy podać numer identyfikacyjny egzemplarza książki w bibliotece (atrybut id_egzemplarz), numer identyfikacyjny książki w tabeli KSIAZKA (atrybut id_ksiazka -referencja ) i wprowadzić wartość dla atrybutu status (0 egzemplarz dostępny w bibliotece). Wprowadzanie danych dotyczących pożyczenia książki wymaga modyfikacji informacji w dwóch tabelach tabeli WYPOZYCZENIE i EGZEMPLARZ. Poprawność wprowadzanie danych do tabel jest kontrolowana poprzez transakcję. Poniżej przedstawiono przykładową operację wypożyczenia książki. BEGIN; INSERT INTO wypozyczenie (id_czytelnik, id_egzemplarz, data_pozyczenie, status) VALUES ( 1, 1,'2012-10-10',1); UPDATE egzemplarz SET status=1 WHERE id_egzemplarz=1; END; Uwaga. Atrybuty id_czytelnik i id_egzemplarz muszą być zgodne z odpowiednimi wartościami atrybutów w tabelach CZYTELNIK i EGZEPLARZ, więzy referencyjne. Ostatnią omówioną operacją modyfikującą dane w bazie danych będzie oddanie książki do biblioteki. Operacja ta jest również realizowana poprzez modyfikację informacji w dwóch tabelach: WYPOZYCZENIE i EGZEMPLARZ. Wersja 0.91 1.05.2017 Strona 3
BEGIN; UPDATE wypozyczenie SET (data_oddanie,status) = ('2013-02-04',2) WHERE id_egzemplarz=1 AND id_czytelnik=1 AND status=1; UPDATE egzemplarz SET status=0 WHERE id_egzemplarz=1; END; 3.2. Raporty i zestawienia Normalizacja bazy danych umożliwia poprawne przetwarzanie danych przez system zarządzania bazą danych, jednak informacja jest najczęściej rozmieszczona w wielu tabelach i nie jest czytelna dla użytkownika bazy danych. Tworzenie raportów i odpowiednich zestawień przez użytkownika bazy danych wymaga tworzenia odpowiednich połączeń pomiędzy tabelami. Powiązania te realizujemy wykorzystując polecenie SELECT i klauzulę JOIN. Pomocnym obiektem bazodanowym do realizacji zestawień są widoki (perspektywy). Widok jest wirtualną tabelą realizującą polecenie bazodanowe na podstawie którego został on utworzony. Na początek utworzymy raport informujący o liczbie książek wypożyczonych przez poszczególnych czytelników nazwisko, imię i liczba pożyczonych książek. Dodatkowo posortujemy dane alfabetycznie po nazwisku. Informacja o pożyczonych książkach znajduje się w tabeli WYPOZYCZENIE w rekordach dla których atrybut status ma wartość 1. Pozostałe atrybuty rekordu zawierają identyfikator czytelnika (klucz obcy do tabeli CZYTELNIK) oraz identyfikator egzemplarza książki (klucz obcy do tabeli EGZEMPLARZ). W celu otrzymania raportu zawierającego imię i nazwisko musimy połączyć tabelę WYPOZYCZENIE i CZYTELNIK po atrybucie złączenia id_czytelnik. Opracowany raport zostanie umieszczony w widoku. Poniżej przedstawiono polecenie SQL realizujące przedstawioną funkcjonalność. -- czytelnicy posiadający wypożyczone książki CREATE VIEW v_czytelnik_wypozyczenia AS SELECT c.nazwisko, c.imie, count(*) AS liczba_ksiazek FROM czytelnik c JOIN wypozyczenie w ON c.id_czytelnik = w.id_czytelnik WHERE w.status=1 GROUP BY c.id_czytelnik ORDER BY c.nazwisko; Kolejnym raportem, który utworzymy będzie zestawienie zawierające czytelników, którzy obecnie nie mają pożyczonych książek. Zestawienie to zostanie zrealizowane w oparciu o tabelę CZYTELNIK. Poprzez polecenie selekcji z klauzulą NOT IN zostaną usunięte z tabeli CZYTELNIK rekordy czytelników, którzy mają pożyczone książki. Informacja o czytelnikach posiadających wypożyczone książki znajduje się w tabeli WYPOZYCZENIE atrybut status równy 1. Polecenie tworzące odpowiedni widok przedstawiono poniżej. -- czytelnicy nieposiadający wypożyczonych książek CREATE VIEW v_czytelnik_brak_wypozyczen AS SELECT c.nazwisko, c.imie FROM czytelnik c WHERE c.id_czytelnik NOT IN Wersja 0.91 1.05.2017 Strona 4
( SELECT DISTINCT w.id_czytelnik FROM wypozyczenie w WHERE w.status=1 ) ORDER BY c.nazwisko; Tabela WYPOZYCZENIE zawiera oprócz informacji o aktualnie wypożyczonych egzemplarzach książek, dodatkowo informację historyczną. Oddając egzemplarz książki wprowadzamy do tabeli datę oddania książki oraz zmieniamy wartość atrybutu status na 2. Analizując rekordy z wartością atrybutu status ustawioną na 2 uzyskamy informację o czytelnikach, którzy pożyczyli dany egzemplarz książki lub informację o książkach, które pożyczył dany czytelnik. Poniżej przedstawione zostanie zestawienie o czytelnikach, którzy nigdy nie pożyczyli żądnej książki. Czytelnik, który nigdy nie pożyczył książki nie będzie miał wpisu w tabeli WYPOZYCZENIE. -- czytelnicy którzy nigdy nie pożyczyli książek CREATE VIEW v_czytelnik_nie_pozyczal AS SELECT nazwisko,imie FROM czytelnik WHERE id_czytelnik NOT IN ( SELECT DISTINCT id_czytelnik FROM wypozyczenie ) ORDER BY nazwisko ; Kolejne zestawienia będą prezentowały tytuły książek wypożyczonych i dostępnych w bibliotece. Informacja o wypożyczeniu książki jest dostępna poprzez atrybut status w tabeli EGZEMPLARZ. Wartość atrybutu równa 0 książka dostępna w bibliotece, natomiast 1 książka pożyczona. Tabela EGZEMPLARZ zawiera tylko informację identyfikującą egzemplarz i identyfikator książki. W celu uzyskania informacji zawierającej dodatkowo tytuł i autora pozycji należy połączyć tabelę EGZEMPLARZ z tabelą KSIAZKA po atrybucie złączenia id_ksiazka. Poniżej przedstawiono dwa widoki zawierające odpowiednio książki dostępne w bibliotece i pożyczone. -- ksiazki wypozyczone CREATE VIEW v_ksiazki_pozyczone AS SELECT k.tytul, k.autor FROM egzemplarz e JOIN ksiazka k ON e.id_ksiazka=k.id_ksiazka WHERE e.status=1 ORDER BY k.tytul ; -- ksiazki w bibliotece CREATE VIEW v_ksiazki_w_bibliotece AS SELECT k.tytul, k.autor FROM egzemplarz e JOIN ksiazka k ON e.id_ksiazka=k.id_ksiazka WHERE e.status=0 ORDER BY k.tytul ; Zestawienia statystyczne informujące o liczbie książek dostępnych w bibliotece, pożyczonych, liczbie egzemplarzy w poszczególnych kategoriach (działach) przedstawiają poniższe polecenia. -- liczba ksiazek w bibliotece i pożyczonych CREATE VIEW v6 (opis, liczba_ksiazek) AS SELECT 'Ksiazki w bibliotece', count(*) FROM egzemplarz WHERE status=0 UNION SELECT 'Ksiazki pozyczone', count(*) FROM egzemplarz WHERE status=1 ORDER BY 1; Wersja 0.91 1.05.2017 Strona 5
-- liczba książek w poszczególnych kategoriach CREATE VIEW v7 AS SELECT d.nazwa, count(*) FROM dzial d JOIN ksiazka k ON d.id_dzial = k.id_dzial GROUP BY d.nazwa; -- liczba książek w poszczególnych kategoriach (pożyczone, w bibliotece) CREATE VIEW v8 (Dzial,Opis,Liczba_pozycji) AS SELECT d.nazwa, CASE WHEN e.status=0 THEN 'W bibliotece' WHEN e.status=1 THEN 'Pozyczone' END, count(*) FROM dzial d JOIN ksiazka k ON d.id_dzial = k.id_dzial JOIN egzemplarz e ON k.id_ksiazka = e.id_ksiazka GROUP BY d.nazwa,e.status ORDER BY d.nazwa,e.status; -- książki najczęściej wypożyczane CREATE VIEW v9 AS SELECT k.tytul, k.autor, count(*) as liczba_wypozyczen FROM ksiazka k JOIN egzemplarz e ON k.id_ksiazka = e.id_ksiazka JOIN wypozyczenie w ON e.id_egzemplarz = w.id_egzemplarz GROUP BY k.id_ksiazka HAVING count(*) > 1 ORDER BY liczba_wypozyczen DESC; Wersja 0.91 1.05.2017 Strona 6