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 CHECKwiersze > 0), kolumny INTEGER NOT NULL CHECKkolumny > 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 drzewoid) 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 drzewoid) 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_nieskid) 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_towarucena_netto REAL, grupa INTEGER) RETURNS REAL AS wynik REAL; 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 ; 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_pierwszaliczba INTEGER) RETURNS VARCHAR AS i INTEGER; wynik VARCHAR64 IF liczba <= 2 THEN wynik := 'Liczba ' liczba ' jest liczbą pierwszą.'; FOR i IN 2..liczba-1 LOOP IF liczba%i)= 0 THEN wynik := 'Liczba ' liczba ' nie jest liczbą pierwszą.'; LOOP; wynik := 'Liczba ' liczba ' jest liczbą pierwszą.'; 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_przelotuodleglosc INTEGER, liczba_pasazerow INTEGER) RETURNS INTEGER AS 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; --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; --cena czystego lotu IF odleglosc > 20 THEN koszt := koszt + odleglosc - 20) * LOT --koszt jednostkowy wynik = koszt / liczba_pasazerow; 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 odlegloscx1 INTEGER, y1 INTEGER, x2 INTEGER, y2 INTEGER)
RETURNS INTEGER AS wynik INTEGER; wynik := x2-x1 + y2-y1; 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_przestawnyindeks INTEGER) RETURNS VARCHAR AS --zapytanie studenci%rowtype; wynik VARCHAR256 tekst VARCHAR256 i INTEGER; wynik := ''; SELECT nazwisko INTO tekst FROM studenci WHERE nr_albumu = indeks; --tekst := zapytanie.nazwisko; FOR i IN REVERSE lengthtekst)..1 LOOP wynik := wynik substrtekst, i, 1 LOOP; UPDATE studenci SET nazwisko = wynik WHERE nr_albumu = indeks;
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$ istnieje BOOLEAN; IF TG_OP = 'INSERT') THEN SELECT true INTO istnieje FROM fakultety WHERE id_fakultetu = NEW.id_fakultetu; IF istnieje THEN ELSE ; $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$ IF TG_OP = 'DELETE') THEN INSERT INTO logs_zapisy SELECT OLD.nr_albumu, OLD.id_fakultetu, now ; $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 VARCHAR3) oraz NAZWA
VARCHAR100) 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 VARCHAR3) NOT NULL, nazwa VARCHAR100) NOT NULL CREATE OR REPLACE FUNCTION fun_tg_kraje) RETURNS TRIGGER AS $logs$ znak1 CHAR; znak2 CHAR; kod VARCHAR3 nazwa VARCHAR100 kod := NEW.kod; nazwa := NEW.nazwa; -- d) kod := UPPERkod -- e) nazwa := INITCAPnazwa -- f) nazwa := TRIMnazwa -- a) IF lengthkod)<> 2 THEN -- b) znak1 = substrkod, 1, 1 znak2 = substrkod, 2, 1 IF asciiznak1) < ascii'a') OR asciiznak1) > ascii'z') THEN IF asciiznak2) < ascii'a') OR asciiznak2) > ascii'z') THEN -- c) IF lengthnazwa) < 3 THEN NEW.kod = kod; NEW.nazwa = nazwa;
; $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$ zawiera BOOLEAN; 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 ELSE ; $logs$ LANGUAGE plpgsql; CREATE TRIGGER tg_terminarz BEFORE INSERT OR UPDATE ON terminarz FOR EACH ROW EXECUTE PROCEDURE fun_tg_terminarz)