Bazy danych Projekt prostej biblioteki 26 stycznia 2015 Hubert Anisimowicz, 275859
Spis treści Rozdział 1 Schemat bazy danych... 2 Rozdział 2 Opis bazy danych... 2 Rozdział 3 Skrypt generujący bazę danych... 3 1. Relacje... 3 2. Klucze główne... 4 3. Klucze obce... 4 4. Klucze unikalne i domyślne wartości atrybutów... 5 5. Więzy check... 5 6. Funkcje... 5 7. Widoki... 6 8. Wyzwalacze... 6 9. Przykładowe dane... 7 10. Przykładowe wypożyczenia... 8 Rozdział 4 Elementy interfejsu graficznego... 9 1
Rozdział 1 Schemat bazy danych Rozdział 2 Opis bazy danych Niniejsza baza danych jest przykładowym projektem stworzonym na potrzeby prostej biblioteki. Przyjęto jako narzucone z góry dwa warunki: biblioteka wymusza na czytelniku podanie przynajmniej jednego numeru telefonu i przynajmniej jednego adresu e-mail, w danym momencie można mieć wypożyczone co najwyżej 3 książki. Baza składa się z 8 tabel: trzy z nich przechowują dane czytelników, jedna śledzi bieżące ilości wypożyczonych książek przez każdego z czytelników, kolejne trzy przechowują dane o książkach dostępnych w bibliotece oraz ostatnia tabela łącząca informacje o konkretnych wypożyczeniach. 2
Rozdział 3 Skrypt generujący bazę danych W tej części raportu zostaną przedstawione polecenia generujące bazę danych prostej biblioteki. Dla przejrzystości w niniejszym raporcie pominięto polecenia DROP [obiekt]. CREATE DATABASE biblioteka; \c biblioteka 1. Relacje Większość atrybutów przyjęto jako NOT NULL, oprócz tych, których nie uznano za niezbędne dla poprawnego funkcjonowania bazy danych. Dla automatycznego numerowania krotek (a tym samym dla łatwego utworzenia kluczy głównych) oraz tam, gdzie miało to sensowne zastosowanie posłużono się typem SERIAL. CREATE TABLE czytelnicy( id_czyt SERIAL NOT NULL, nazwisko VARCHAR(100) NOT NULL, imie VARCHAR(50) NOT NULL, adres VARCHAR(100) NOT NULL, pesel VARCHAR(11) NOT NULL, uwagi VARCHAR(200) ); CREATE TABLE telefony( id_czyt INTEGER NOT NULL, nr_tel VARCHAR(14) NOT NULL ); CREATE TABLE maile( id_czyt INTEGER NOT NULL, mail VARCHAR(100) NOT NULL ); CREATE TABLE dzialy( dzial INTEGER NOT NULL, opis VARCHAR(100) NOT NULL ); CREATE TABLE ksiazki( ksiazka SERIAL NOT NULL, autor VARCHAR(100), tytul VARCHAR(100) NOT NULL, wydawnictwo VARCHAR(100), dzial INTEGER NOT NULL, isbn VARCHAR(13), uwagi VARCHAR(200) ); CREATE TABLE egzemplarze( sygnatura SERIAL NOT NULL, ksiazka INTEGER NOT NULL, uwagi VARCHAR(200) ); CREATE TABLE liczba_wyp( id_czyt INTEGER NOT NULL, liczba INTEGER NOT NULL); 3
CREATE TABLE wypozyczenia( id_wyp SERIAL NOT NULL, id_czyt INTEGER NOT NULL, sygnatura INTEGER NOT NULL, data_wyp DATE NOT NULL, uwagi VARCHAR(200) ); 2. Klucze główne Dla każdej z tabel ustanowiono klucz główny. ALTER TABLE czytelnicy ADD PRIMARY KEY (id_czyt); ALTER TABLE telefony ADD PRIMARY KEY (nr_tel); ALTER TABLE maile ADD PRIMARY KEY (mail); ALTER TABLE dzialy ADD PRIMARY KEY (dzial); ALTER TABLE ksiazki ADD PRIMARY KEY (ksiazka); ALTER TABLE egzemplarze ADD PRIMARY KEY (sygnatura); ALTER TABLE liczba_wyp ADD PRIMARY KEY (id_czyt); ALTER TABLE wypozyczenia ADD PRIMARY KEY (id_wyp); 3. Klucze obce Odpowiednio zdefiniowane klucze obce zapobiegają niepożądanym operacjom, np. usunięciu z zasobów książki, która jest aktualnie wypożyczona. ALTER TABLE telefony ADD FOREIGN KEY (id_czyt) REFERENCES czytelnicy(id_czyt) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE maile ADD FOREIGN KEY (id_czyt) REFERENCES czytelnicy(id_czyt) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ksiazki ADD FOREIGN KEY (dzial) REFERENCES dzialy(dzial) ON UPDATE CASCADE ON DELETE RESTRICT; ALTER TABLE egzemplarze ADD FOREIGN KEY (ksiazka) REFERENCES ksiazki(ksiazka) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE wypozyczenia ADD FOREIGN KEY (id_czyt) REFERENCES czytelnicy(id_czyt) ON UPDATE CASCADE ON DELETE RESTRICT; ALTER TABLE liczba_wyp ADD FOREIGN KEY (id_czyt) REFERENCES czytelnicy(id_czyt) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE wypozyczenia ADD FOREIGN KEY (sygnatura) REFERENCES egzemplarze(sygnatura) ON UPDATE CASCADE ON DELETE RESTRICT; 4
4. Klucze unikalne i domyślne wartości atrybutów Zadbano także aby wartości takie jak nr PESEL czytelnika czy numer ISBN książki były unikalne. Dodatkowo zostały ustalone domyślne wartości dwóch atrybutów. ALTER TABLE czytelnicy ADD UNIQUE (pesel); ALTER TABLE ksiazki ADD UNIQUE (isbn); ALTER TABLE wypozyczenia ADD UNIQUE (sygnatura); ALTER TABLE wypozyczenia ALTER COLUMN data_wyp SET DEFAULT current_date; ALTER TABLE liczba_wyp ALTER COLUMN liczba SET DEFAULT 0; 5. Więzy check Zostało odpowiednio wprowadzone więzy check dbające aby do bazy nie dostały się błędne dane, np. numer telefonu zawierający litery. ALTER TABLE czytelnicy ADD CHECK (pesel~'^[0-9]*$'); ALTER TABLE czytelnicy ADD CHECK (length(pesel) IN (11)); ALTER TABLE telefony ADD CHECK (nr_tel~'^[0-9]*$'); ALTER TABLE telefony ADD CHECK (length(nr_tel) IN (9,11,12,13,14)); ALTER TABLE ksiazki ADD CHECK (isbn~'^[0-9]*$'); ALTER TABLE ksiazki ADD CHECK (length(isbn) IN (10,13)); 6. Funkcje Zaprojektowano także dwie funkcje ułatwiające wypożyczanie I zwrot książek. CREATE OR REPLACE FUNCTION wypozycz(id INTEGER, s INTEGER) RETURNS TEXT AS $$ INSERT INTO wypozyczenia(id_czyt, sygnatura, data_wyp) VALUES (id, s, current_date); RETURN 'Czytelnikowi ' id ' wypozyczono ksiazke ' s '!'; CREATE OR REPLACE FUNCTION zwroc(id INTEGER, s INTEGER) RETURNS TEXT AS $$ DELETE FROM wypozyczenia WHERE id=id_czyt AND s=sygnatura; RETURN 'Ksiazka ' s ' zostala zwrocona!'; 5
7. Widoki Dla ułatwienia korzystania z bazy zaprojektowano dwa widoki wyświetlające dane wszystkich czytelników oraz wszystkie dostępne książki. CREATE VIEW wszyscy_czyt AS ( SELECT c.id_czyt AS "id czytelnika", c.imie AS "imie", c.nazwisko AS "nazwisko", c.adres AS "adres", c.pesel AS "pesel", t.nr_tel AS "nr telefonu", m.mail AS "adres e-mail" FROM czytelnicy AS c, telefony AS t, maile AS m WHERE c.id_czyt=t.id_czyt AND c.id_czyt=m.id_czyt ORDER BY nazwisko ASC ); CREATE VIEW wszystkie_ksiazki AS ( SELECT ksiazka AS "id ksiazki", autor, tytul, dzial, isbn, uwagi FROM ksiazki ORDER BY autor ASC ); 8. Wyzwalacze Nad egzekwowaniem zasad panujących w bibliotece czuwają wyzwalacze śledzące ilość wypożyczonych książek i uniemożliwiające wypożyczenie zbyt dużej ilości książek. CREATE OR REPLACE FUNCTION wpisz_liczbe() RETURNS TRIGGER AS $$ INSERT INTO liczba_wyp(id_czyt, liczba) VALUES (NEW.id_czyt, 0); RETURN OLD; DROP TRIGGER wpisz_liczbe_trigger ON czytelnicy CASCADE; CREATE TRIGGER wpisz_liczbe_trigger AFTER INSERT ON czytelnicy FOR EACH ROW EXECUTE PROCEDURE wpisz_liczbe(); CREATE OR REPLACE FUNCTION jeden_wiecej() RETURNS TRIGGER AS $$ UPDATE liczba_wyp SET liczba=liczba+1 WHERE NEW.id_czyt=liczba_wyp.id_czyt; RETURN OLD; DROP TRIGGER jeden_wiecej_trigger ON wypozyczenia CASCADE; CREATE TRIGGER jeden_wiecej_trigger AFTER INSERT ON wypozyczenia FOR EACH ROW EXECUTE PROCEDURE jeden_wiecej(); 6
CREATE OR REPLACE FUNCTION liczba_wypozyczen() RETURNS TRIGGER AS $$ IF liczba_wyp.liczba=3 FROM liczba_wyp WHERE liczba_wyp.id_czyt=new.id_czyt THEN RAISE EXCEPTION 'Czytelnik wypozyczyl juz 3 ksiazki!'; END IF; RETURN NEW; DROP TRIGGER liczba_wypozyczen_trigger ON wypozyczenia CASCADE; CREATE TRIGGER liczba_wypozyczen_trigger BEFORE INSERT ON wypozyczenia FOR EACH ROW EXECUTE PROCEDURE liczba_wypozyczen(); CREATE OR REPLACE FUNCTION jeden_mniej() RETURNS TRIGGER AS $$ UPDATE liczba_wyp SET liczba=liczba-1 WHERE OLD.id_czyt=liczba_wyp.id_czyt; RETURN NEW; DROP TRIGGER jeden_mniej_trigger ON wypozyczenia CASCADE; CREATE TRIGGER jeden_mniej_trigger AFTER DELETE ON wypozyczenia FOR EACH ROW EXECUTE PROCEDURE jeden_mniej(); 9. Przykładowe dane Do bazy wprowadzono przykładowe krotki ilustrujące jej działanie. Dane zostały wprowadzone poprawnie, z zachowaniem wymagań więzów check i wyzwalaczy. INSERT INTO czytelnicy(nazwisko, imie, adres, pesel) VALUES ('Abacki', 'Adam', 'Trzebnicka 12, 51-130 Wroclaw', '91062484665'), ('Babacki', 'Bronislaw', 'Lindego 20, 51-138 Wroclaw','91042908329'), ('Cabacka', 'Czeslawa', 'Slaska 15, 42-222 Legnica', '62051851224'), ('Dabacki', 'Dariusz', 'Bardzka 8, 34-242 Kobierzyce', '74091584241'), ('Ebacka', 'Elzbieta', 'Wroclawska 7, 32-543 Walbrzych', '92070951482'); INSERT INTO telefony(id_czyt, nr_tel) VALUES (1, '512487954'), (2, '214569874'), (3, '548632145'), (4, '548756321'), (5, '521632521'), (5, '00447154263145'); 7
INSERT INTO maile(id_czyt, mail) VALUES (1, 'abacki@wp.pl'), (1, 'abacki.adam@onet.eu'), (2, 'babacki@wp.pl'), (3, 'cabacka@wp.pl'), (4, 'dabacki@wp.pl'), (5, 'ebacka@wp.pl'); INSERT INTO dzialy(dzial, opis) VALUES (4, 'Informatyka'), (5, 'Zarzadzanie'), (8, 'Kultura'), (303, 'Metodologia badan'), (613, 'Uzaleznienia'); INSERT INTO ksiazki(autor, tytul, dzial, isbn) VALUES ('Herbata Z.', 'Relacyjne bazy danych', 4, '5487562314'), ('Ogorek M.', 'Metodologia badan w socjologii', 303, '5947361886142'); INSERT INTO ksiazki(autor, tytul, wydawnictwo, dzial, isbn) VALUES ('Freud S.', 'Psychoterapia uzaleznien', 'PWN', 613, '5412459865214'), ('Pajolek M.', 'Zarzadzanie stresem', 'UwP', 5, '8456217845100'); INSERT INTO egzemplarze(ksiazka) VALUES (1), (2), (3), (3), (4), (4); INSERT INTO egzemplarze(ksiazka, uwagi) VALUES (1, 'lekko zniszczony grzbiet'), (3, 'brak strony tytulowej'); 10. Przykładowe wypożyczenia Dokonano też kilku przykładowych wypożyczeń książek. SELECT wypozycz(1,4); SELECT wypozycz(1,7); SELECT wypozycz(2,3); SELECT wypozycz(5,8); SELECT wypozycz(1,1); SELECT zwroc(1,1); 8
Rozdział 4 Elementy interfejsu graficznego Interfejs graficzny bazy danych wykonano w oparciu programu OpenOffice Base, który uzyskał połączenie z lokalną bazą danych, a więc również dostęp do tabel, więzów integralności, wyzwalaczy czy też wprowadzonych danych. Widok tabel w OpenOffice Base: W tabeli czytelnicy widać uprzednio wprowadzone dane. Zgodnie z ustalonymi więzami wprowadzenie np. zbyt długiego numeru PESEL kończy się błędem: Poprawnie wprowadzony czytelnik: 9
Poniżej zaprezentowano wprowadzenie poprawnego wypożyczenia czytelnikowi 4 książki 1, oraz nieudaną próbę wypożyczenia czytelnikowi 3 książki 3 ponieważ ta jest już wypożyczona przez czytelnika 2: 10