SQL :: Data Definition Language
Transkrypt
SQL :: Data Definition Language
SQL :: Data Definition Language 1. Zaproponuj wydajną strukturę danych (tabela) do przechowywania macierzy o dowolnych wymiarach w bazie danych. Propozycja struktury powinna zostać zapisana z wykorzystaniem polecenia CREATE TABLE zgodnie z aktualnie obowiązującym standardem języka SQL. CREATE TABLE macierz ( id INTEGER PRIMARY KEY, wiersze INTEGER NOT NULL CHECK(wiersze > 0), kolumny INTEGER NOT NULL CHECK(kolumny > 0), matrix REAL[][] NOT NULL ); 2. Zaproponuj wydajną strukturę danych (tabela) do przechowywania danych w postaci drzewa o dowolnym rozmiarze w bazie danych. Propozycja struktury powinna zostać zapisana z wykorzystaniem polecenia CREATE TABLE zgodnie z aktualnie obowiązującym standardem języka SQL. CREATE TABLE drzewo ( id INTEGER PRIMARY KEY, wartosc INTEGER NOT NULL, rodzic INTEGER REFERENCES drzewo(id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED ); 3. Zaproponuj wydajną strukturę danych (tabela) do przechowywania danych w postaci drzewa binarnego o dowolnym rozmiarze w bazie danych. Propozycja struktury powinna zostać zapisana z wykorzystaniem polecenia CREATE TABLE zgodnie z aktualnie obowiązującym standardem języka SQL. CREATE TABLE drzewo_BST ( id INTEGER PRIMARY KEY, wartosc INTEGER NOT NULL, rodzic INTEGER REFERENCES drzewo(id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, lewy INTEGER, prawy INTEGER, ); 4. Zaproponuj wydajną strukturę danych (tabela) do przechowywania danych w postaci grafu nieskierowanego o dowolnym rozmiarze w bazie danych. Propozycja struktury powinna zostać zapisana z wykorzystaniem polecenia CREATE TABLE zgodnie z aktualnie obowiązującym standardem języka SQL. Wskazówka: Wykorzystaj reprezentację grafu nieskierowanego w postaci listy sąsiedztwa. CREATE TABLE graf_niesk ( id INTEGER , powiazanie INTEGER REFERENCES graf_niesk(id) ON UPDATE CASCADE ON DELETE CASCADE ); PL/pgSQL 5. Utwórz funkcję obliczającą cenę brutto towaru. Przekazywanymi do funkcji argumentami powinny być: CENA_NETTO oraz GRUPA. CENA_NETTO - cena przed naliczeniem podatku VAT; GRUPA - grupa podatkowa {1 - PODSTAWOWA - 22%; 2 - OBNIŻONA- 7%; 3 ZWOLNIONA – 0%} CREATE OR REPLACE FUNCTION cena_towaru(cena_netto REAL, grupa INTEGER) RETURNS REAL AS $BODY$ DECLARE wynik REAL; BEGIN wynik = CASE WHEN grupa = 1 THEN cena_netto * 22 / 100 + cena_netto WHEN grupa = 2 THEN cena_netto * 7 / 100 + cena_netto WHEN grupa = 3 THEN cena_netto ELSE 0 END; return wynik; END $BODY$ LANGUAGE 'plpgsql' 6. Utwórz funkcję sprawdzającą czy przekazana wartość jest liczbą pierwszą. Funkcja powinna zwracać informację w postaci: Liczba a jest/nie jest liczbą pierwszą. CREATE OR REPLACE FUNCTION liczba_pierwsza(liczba INTEGER) RETURNS VARCHAR AS $BODY$ DECLARE i INTEGER; wynik VARCHAR(64); BEGIN IF liczba <= 2 THEN wynik := 'Liczba ' || liczba || ' jest liczbą pierwszą.'; return wynik; END IF; FOR i IN 2..liczba-1 LOOP IF (liczba%i)= 0 THEN wynik := 'Liczba ' || liczba || ' nie jest liczbą pierwszą.'; return wynik; END IF; END LOOP; wynik := 'Liczba ' || liczba || ' jest liczbą pierwszą.'; return wynik; END $BODY$ LANGUAGE 'plpgsql' 7. Utwórz funkcję która oblicza cenę jednostkową przelotu z miasta A do miasta B, przy założeniu, że koszty są określone następująco a) KOSZTY LOTNISKOWE (WYLOT) = 20 000 PLN b) KOSZTY LOTNISKOWE (PRZYLOT) = 10 000 PLN c) KOSZTY MIĘDZYLĄDOWAŃ (TANKOWANIE) = 15 000 PLN d) KOSZTY PALIWA - 100 PLN / 1 km (pierwsze 10 km po starcie) - 50 PLN / 1 km (lot) - 75 PLN / 1 km (ostanie 10 km przed lądowaniem) Zakładamy, że minimalna odległość lotu wynosi 20 km (lub inaczej ujmując minimalny koszt lotu jest równy pokonaniu 20 km). Zakładamy, że maksymalny zasięg samolotu (przy pełnych zbiornikach paliwa) wynosi 10 000 km. W przypadku gdy trasa przelotu jest większa od maks. zasięgu należy doliczyć KOSZTY MIĘDZYLĄDOWAŃ. Argumentami przekazywanymi do funkcji powinny być: ODLEGŁOŚĆ [km] LICZBA_PASAŻERÓW Cena jednostkowa jest to koszt lotu / liczba pasażerów. CREATE OR REPLACE FUNCTION koszt_przelotu(odleglosc INTEGER, liczba_pasazerow INTEGER) RETURNS INTEGER AS $BODY$ DECLARE WYLOT CONSTANT INTEGER := 20000; PRZYLOT CONSTANT INTEGER := 10000; TANKOWANIE CONSTANT INTEGER := 15000; MAXPALIWA_NA_KM CONSTANT INTEGER := 10000; LOT_START CONSTANT INTEGER := 100; LOT CONSTANT INTEGER := 50; LOT_KONIEC CONSTANT INTEGER := 75; wynik INTEGER; koszt INTEGER; ile INTEGER; BEGIN --Przylot i odlot koszt := WYLOT + PRZYLOT; --10 km startu i końca koszt := koszt + (LOT_START * 10) + (LOT_KONIEC * 10); --Międzylądowania IF odleglosc > MAXPALIWA_NA_KM THEN ile := odleglosc / MAXPALIWA_NA_KM; koszt := koszt + TANKOWANIE * ile; END IF; --cena czystego lotu IF odleglosc > 20 THEN koszt := koszt + ((odleglosc - 20) * LOT); END IF; --koszt jednostkowy wynik = koszt / liczba_pasazerow; return wynik; END $BODY$ LANGUAGE 'plpgsql' 8. Utwórz funkcję obliczającą odległość między dwoma miastami wg metryki miejskiej (Manhattan). Argumentami przekazywanymi powinny być: MIASTO_A (x1, y1) oraz MIASTO_B (x2, y2). CREATE OR REPLACE FUNCTION odleglosc(x1 INTEGER, y1 INTEGER, x2 INTEGER, y2 INTEGER) RETURNS INTEGER AS $BODY$ DECLARE wynik INTEGER; BEGIN wynik := x2-x1 + y2-y1; return wynik; END $BODY$ LANGUAGE 'plpgsql' 9. Utwórz funkcję realizującą szyfrowanie/deszyfrowanie danych wg nieskomplikowanych metod wykorzystujących np.: a) szyfrowanie przestawieniowe; b) szyfrowanie blokowe (np. Cipher Feedback) /DLA AMBITNYCH/ Argumentem funkcji powinien być nr_albumu studenta na podstawie którego będzie realizowane odczytanie z tabeli studenci wartość kolumny nazwisko a następnie zapisanie w jej miejsce wartości zaszyfrowanej (w przypadku fukcji szyfrującej) lub odszyfrowanej (w przypadku fukcji deszyfrującej). CREATE OR REPLACE FUNCTION szyfr_przestawny(indeks INTEGER) RETURNS VARCHAR AS $BODY$ DECLARE --zapytanie studenci%ROWTYPE; wynik VARCHAR(256); tekst VARCHAR(256); i INTEGER; BEGIN wynik := ''; SELECT nazwisko INTO tekst FROM studenci WHERE nr_albumu = indeks; --tekst := zapytanie.nazwisko; FOR i IN REVERSE length(tekst)..1 LOOP wynik := wynik || substr(tekst, i, 1); END LOOP; UPDATE studenci SET nazwisko = wynik WHERE nr_albumu = indeks; return wynik; END $BODY$ LANGUAGE 'plpgsql' Wyzwalacze i procedury wyzwalane 1. Załóżmy, że baza danych nie wspiera mechanizmów integralności referencyjnej (związki KLUCZ GŁÓWNY - KLUCZ OBCY). Utwórz wyzwalacz oraz procedurę wyzwalaną, które zapewnią zachowanie integralności referencyjnej przy dodawaniu rekordów do dwóch powiązanych tabel. W zadaniu można wykorzystać np. tabele FAKULTETY oraz ZAPISY usuwając wcześniej ograniczenie kl_ob_zapisy_fakultety (DROP CONSTRAINT...). CREATE OR REPLACE FUNCTION integralnosc_fakultet() RETURNS TRIGGER AS $operacje$ DECLARE istnieje BOOLEAN; BEGIN IF (TG_OP = 'INSERT') THEN SELECT true INTO istnieje FROM fakultety WHERE id_fakultetu = NEW.id_fakultetu; IF istnieje THEN RETURN NEW; ELSE RETURN NULL; END IF; END IF; RETURN NEW; END; $operacje$ LANGUAGE plpgsql; ------------------------CREATE TRIGGER sprawdz_zapisy BEFORE INSERT ON zapisy FOR EACH ROW EXECUTE PROCEDURE integralnosc_fakultet() 2. Utwórz wyzwalacz oraz procedurę wyzwalaną realizujące archiwizację danych usuwanych z tabeli ZAPISY. CREATE TABLE logs_zapisy ( nr_albumu INTEGER, id_fakultetu INTEGER, log_when TIMESTAMP ); ------------------------------------------CREATE OR REPLACE FUNCTION usuwane_zapisy() RETURNS TRIGGER AS $logs$ BEGIN IF (TG_OP = 'DELETE') THEN INSERT INTO logs_zapisy SELECT OLD.nr_albumu, OLD.id_fakultetu, now(); END IF; RETURN NULL; END; $logs$ LANGUAGE plpgsql; -----------------------------------------CREATE TRIGGER log_zapisy AFTER DELETE ON zapisy FOR EACH ROW EXECUTE PROCEDURE usuwane_zapisy() 3. Utwórz tabelę KRAJE zawierającą dwa pola KOD VARCHAR(3) oraz NAZWA VARCHAR(100) oraz wyzwalacz wraz z procedurą wyzwalaną realizujące następujące funkcje: a) odrzucanie KOD-ów krajów, które nie zawierają dokładnie 2 znaków (np. niepoprawnymi wartościami są: P, POL); b) odrzucanie KOD-ów krajów, które nie zawierają tylko liter z zakresu [A-Z]; c) odrzucanie NAZW krajów o długości mniejszej niż 3 znaki; d) zamianę wszystkich liter KOD-u na litery duże; e) zamianę wszystkich członów NAZWY na człony rozpoczynające się od dużej litery (np. polsKA -> Polska, POLSKA -> Polska, polska -> Polska, Wielka brytania -> Wielka Brytania); f) eliminację "białych znaków" (spacji, tabulatorów etc.) z początku i końca NAZWY oraz KOD-u; CREATE TABLE kraje ( kod VARCHAR(3) NOT NULL, nazwa VARCHAR(100) NOT NULL ); ------------------------------------------CREATE OR REPLACE FUNCTION fun_tg_kraje() RETURNS TRIGGER AS $logs$ DECLARE znak1 CHAR; znak2 CHAR; kod VARCHAR(3); nazwa VARCHAR(100); BEGIN kod := NEW.kod; nazwa := NEW.nazwa; -- d) kod := UPPER(kod); -- e) nazwa := INITCAP(nazwa); -- f) nazwa := TRIM(nazwa); -- a) IF length(kod)<> 2 THEN RETURN NULL; END IF; -- b) znak1 = substr(kod, 1, 1); znak2 = substr(kod, 2, 1); IF ascii(znak1) < ascii('A') OR ascii(znak1) > ascii('Z') THEN RETURN NULL; END IF; IF ascii(znak2) < ascii('A') OR ascii(znak2) > ascii('Z') THEN RETURN NULL; END IF; -- c) IF length(nazwa) < 3 THEN RETURN NULL; END IF; NEW.kod = kod; NEW.nazwa = nazwa; RETURN NEW; END; $logs$ LANGUAGE plpgsql; ---------------------------------------CREATE TRIGGER tg_kraje BEFORE INSERT OR UPDATE ON kraje FOR EACH ROW EXECUTE PROCEDURE fun_tg_kraje() 4. Utwórz tabelę TERMINARZ z polami DATA_GODZINA_POCZATKOWA TIMESTAMP, DATA_GODZINA_KONCOWA TIMESTAMP oraz SPOTKANIE VARCHAR oraz wyzwalacz wraz z procedurą wyzwalaną, która będzie weryfikować i nie zezwalać na zapis kolidujących (nakładających się) terminów spotkań. CREATE TABLE terminarz ( data_godzina_poczatkowa TIMESTAMP NOT NULL, data_godzina_koncowa TIMESTAMP NOT NULL, spotkanie VARCHAR NOT NULL ); ------------------------------------------CREATE OR REPLACE FUNCTION fun_tg_terminarz() RETURNS TRIGGER AS $logs$ DECLARE zawiera BOOLEAN; BEGIN SELECT true INTO zawiera FROM terminarz WHERE (data_godzina_poczatkowa, data_godzina_koncowa) OVERLAPS (NEW.data_godzina_poczatkowa, NEW.data_godzina_koncowa) LIMIT 1; IF zawiera THEN RETURN NULL; ELSE RETURN NEW; END IF; END; $logs$ LANGUAGE plpgsql; ------------------------------------------CREATE TRIGGER tg_terminarz BEFORE INSERT OR UPDATE ON terminarz FOR EACH ROW EXECUTE PROCEDURE fun_tg_terminarz()