-- Usunięcie tabel, jeśli istnieją DROP TABLE IF EXISTS Historia; DROP TABLE IF EXISTS Instytucja; DROP TABLE IF EXISTS Galeria; DROP TABLE IF EXISTS Eksponat; DROP TABLE IF EXISTS Artysta; -- Tworzenie tabel CREATE TABLE Artysta ( artysta_id SERIAL PRIMARY KEY, imię VARCHAR(20) NOT NULL, nazwisko VARCHAR(20) NOT NULL, rok_urodzenia VARCHAR(4) NOT NULL, rok_śmierci VARCHAR(4), CONSTRAINT sprawdz_rok CHECK ( rok_śmierci IS NULL OR CAST(rok_urodzenia AS INT) < CAST(rok_śmierci AS INT) ) ); CREATE TABLE Eksponat ( eksponat_id SERIAL PRIMARY KEY, tytuł VARCHAR(30) NOT NULL, typ VARCHAR(10) NOT NULL, wysokość INTEGER NOT NULL, szerokość INTEGER NOT NULL, waga INTEGER NOT NULL, mozna_wypozyczac BOOLEAN DEFAULT TRUE, artysta_id INTEGER REFERENCES Artysta(artysta_id) ON DELETE SET NULL ); CREATE TABLE Galeria ( galeria_id SERIAL PRIMARY KEY, nazwa VARCHAR(30) NOT NULL, adres VARCHAR(30) NOT NULL, liczba_sal INTEGER NOT NULL ); CREATE TABLE Instytucja ( instytucja_id SERIAL PRIMARY KEY, nazwa VARCHAR(30) NOT NULL, miasto VARCHAR(20) NOT NULL ); CREATE TABLE Historia ( historia_id SERIAL PRIMARY KEY, eksponat_id INTEGER NOT NULL REFERENCES Eksponat(eksponat_id), galeria_id INTEGER REFERENCES Galeria(galeria_id), instytucja_id INTEGER REFERENCES Instytucja(instytucja_id), data_rozpoczęcia DATE NOT NULL, data_zakończenia DATE, typ_zdarzenia VARCHAR(20) NOT NULL CHECK (typ_zdarzenia IN ('Wystawa', 'Wypożyczenie', 'Magazynowanie')) ); -- Warunek: żaden eksponat nie może być poza muzeum dłużej niż 30 dni rocznie CREATE OR REPLACE FUNCTION sprawdz_wypozyczenia() RETURNS TRIGGER AS $$ BEGIN IF NEW.typ_zdarzenia = 'Wypożyczenie' THEN -- Sprawdź sumę dni wypożyczeń dla danego eksponatu w roku IF ( SELECT COALESCE(SUM((data_zakończenia - data_rozpoczęcia)::int), 0) FROM Historia WHERE eksponat_id = NEW.eksponat_id AND typ_zdarzenia = 'Wypożyczenie' AND EXTRACT(YEAR FROM data_rozpoczęcia) = EXTRACT(YEAR FROM NEW.data_rozpoczęcia) ) + ((NEW.data_zakończenia - NEW.data_rozpoczęcia)::int) > 30 THEN RAISE EXCEPTION 'Eksponat nie może być wypożyczony dłużej niż 30 dni rocznie'; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER sprawdz_wypozyczenia_trigger BEFORE INSERT OR UPDATE ON Historia FOR EACH ROW EXECUTE FUNCTION sprawdz_wypozyczenia(); CREATE OR REPLACE FUNCTION sprawdz_ostatnie_dzielo() RETURNS TRIGGER AS $$ DECLARE pozostale_dziela INT; BEGIN -- Oblicz liczbę dzieł artysty, które pozostaną w magazynie lub galerii SELECT COUNT(*) INTO pozostale_dziela FROM Eksponat e WHERE e.artysta_id = (SELECT artysta_id FROM Eksponat WHERE eksponat_id = NEW.eksponat_id) AND e.eksponat_id NOT IN ( SELECT eksponat_id FROM Historia WHERE typ_zdarzenia = 'Wypożyczenie' AND data_zakończenia >= CURRENT_DATE ); -- Jeśli liczba dzieł wynosi 0, zablokuj wypożyczenie IF pozostale_dziela <= 1 THEN RAISE EXCEPTION 'Nie można wypożyczyć ostatniego dzieła artysty – co najmniej jedno musi pozostać w magazynie lub galerii.'; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Utworzenie wyzwalacza CREATE TRIGGER sprawdz_ostatnie_dzielo_trigger BEFORE INSERT ON Historia FOR EACH ROW WHEN (NEW.typ_zdarzenia = 'Wypożyczenie') EXECUTE FUNCTION sprawdz_ostatnie_dzielo(); CREATE OR REPLACE FUNCTION sprawdz_mozliwosc_wypozyczenia() RETURNS TRIGGER AS $$ BEGIN -- Sprawdź, czy eksponat ma mozna_wypozyczac = FALSE IF (SELECT mozna_wypozyczac FROM Eksponat WHERE eksponat_id = NEW.eksponat_id) = FALSE THEN RAISE EXCEPTION 'Nie można wypożyczać tego eksponatu: eksponat_id = %', NEW.eksponat_id; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Trigger wywołujący funkcję przed wstawieniem lub aktualizacją w tabeli Historia CREATE TRIGGER trigger_sprawdz_mozliwosc_wypozyczenia BEFORE INSERT OR UPDATE ON Historia FOR EACH ROW WHEN (NEW.typ_zdarzenia = 'Wypożyczenie') -- Działa tylko dla wypożyczeń EXECUTE FUNCTION sprawdz_mozliwosc_wypozyczenia(); INSERT INTO Artysta (imię, nazwisko, rok_urodzenia, rok_śmierci) VALUES ('Leonardo', 'da Vinci', '1452', '1519'), ('Vincent', 'van Gogh', '1853', '1890'), ('Pablo', 'Picasso', '1881', '1973'), ('Claude', 'Monet', '1840', '1926'), ('Salvador', 'Dali', '1904', '1989'), ('Johannes', 'Vermeer', '1632', '1675'), ('Edvard', 'Munch', '1863', '1944'), ('Rembrandt', 'van Rijn', '1606', '1669'), ('Andy', 'Warhol', '1928', '1987'), ('Caravaggio', 'Merisi', '1571', '1610'), ('Francisco', 'Goya', '1746', '1828'), ('AGustav', 'Klimt', '1862', '1918'), ('Paul', 'Cézanne', '1839', '1906'), ('Henri', 'Matisse', '1869', '1954'), ('Kazimir', 'Malevich', '1879', '1935'), ('Jackson', 'Pollock', '1912', '1956'); INSERT INTO Eksponat (tytuł, typ, wysokość, szerokość, waga, mozna_wypozyczac, artysta_id) VALUES ('Mona Lisa', 'Obraz', 77, 53, 10, TRUE, '1'), ('Ostatnia Wieczerza', 'Fresk', 460, 880, 200, TRUE, '1'), ('Gwiaździsta noc', 'Obraz', 74, 92, 15, TRUE, '2'), ('Słoneczniki', 'Obraz', 92, 73, 12, TRUE, '2'), ('Guernica', 'Obraz', 349, 776, 50, TRUE, '3'), ('Panny z Awinionu', 'Obraz', 244, 234, 30, TRUE, '3'), ('Impresja, wschód słońca', 'Obraz', 48, 63, 8, TRUE, '4'), ('Lilie wodne', 'Obraz', 200, 300, 20, TRUE, '4'), ('Trwałość pamięci', 'Obraz', 24, 33, 6, TRUE, '5'), ('Dziewczyna z perłą', 'Obraz', 44, 39, 9, TRUE, '6'), ('Krzyk', 'Obraz', 91, 73, 10, TRUE, '7'), ('Straż nocna', 'Obraz', 363, 437, 50, TRUE, '8'), ('Puszka zupy Campbell', 'Obraz', 51, 41, 5, TRUE, '9'), ('Narcyz', 'Obraz', 110, 92, 10, TRUE, '10'), ('Maja naga', 'Obraz', 97, 190, 18, TRUE, '11'), ('Pocałunek', 'Obraz', 180, 180, 25, TRUE, '12'), ('Martwa natura z jabłkami', 'Obraz', 65, 81, 10, TRUE, '13'), ('Taniec', 'Obraz', 260, 391, 35, TRUE, '14'), ('Czarny kwadrat', 'Obraz', 79, 79, 5, TRUE, '15'); INSERT INTO Galeria (nazwa, adres, liczba_sal) VALUES ('Galeria Renesansu', 'Plac Muzealny 1', 10), ('Galeria Matematyki', 'Banacha 2', 8); INSERT INTO Instytucja (nazwa, miasto) VALUES ('Muzeum Narodowe', 'Warszawa'), ('Galeria Sztuki Współczesnej', 'Berlin'), ('Fundacja Sztuki', 'Paryż'), ('Instytut Sztuki Nowoczesnej', 'Nowy Jork'), ('Centrum Sztuki', 'Londyn'), ('Akademia Sztuk Pięknych', 'Kraków'), ('Muzeum Sztuki Współczesnej', 'Barcelona'); INSERT INTO Historia (eksponat_id, galeria_id, instytucja_id, data_rozpoczęcia, data_zakończenia, typ_zdarzenia) VALUES ('1', NULL, '1', '2024-01-01', '2024-01-30', 'Wypożyczenie'), ('3', '2', NULL, '2024-02-15', '2024-03-10', 'Wystawa'), ('5', NULL, '3', '2024-04-01', '2024-04-25', 'Wypożyczenie'), ('7', '1', NULL, '2024-05-10', '2024-06-05', 'Wystawa');