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()