Bazy danych Zaawansowane przetwarzanie danych

Podobne dokumenty
PODSTAWY BAZ DANYCH 13. PL/SQL

DECLARE VARIABLE zmienna1 typ danych; BEGIN

Bloki anonimowe w PL/SQL

W PostgreSQL mamy do dyspozycji nie tylko funkcje wbudowane, ale również możemy tworzyć własne. Są one zapisywane w tabeli systemowej pg_proc.

Programowanie w SQL procedury i funkcje. UWAGA: Proszę nie zapominać o prefiksowaniu nazw obiektów ciągiem [OLIMP\{nr indeksu}] Funkcje użytkownika

DECLARE <nazwa_zmiennej> typ [(<rozmiar> )] [ NOT NULL ] [ { := DEFAULT } <wartość> ];

E.14 Bazy Danych cz. 18 SQL Funkcje, procedury składowane i wyzwalacze

Wyzwalacze (triggery) Przykład

Wykład 5 funkcje i procedury pamiętane widoki (perspektywy) wyzwalacze

Przykład 3 Zdefiniuj w bazie danych hurtownia_nazwisko przykładową funkcję użytkownika fn_rok;

Plan wykładu BAZY DANYCH II WYKŁAD 3. Zasięg zmiennych. Zasięg zmiennych

15. Funkcje i procedury składowane PL/SQL

Materiały. Technologie baz danych. Plan wykładu Kursory. Wykład 5: Kursory jawne. Podprogramy. Kursory jawne. Kursory niejawne

Przestrzenne bazy danych Podstawy języka SQL

Funkcje w PL/SQL Funkcja to nazwany blok języka PL/SQL. Jest przechowywana w bazie i musi zwracać wynik. Z reguły, funkcji utworzonych w PL/SQL-u

Trigger jest obiektem związanym z tablicą, który aktywuje się gdy do tablicy następuje odpowiednie zapytanie.

Plan wykładu Projekt fizyczny bazy danych Wprowadzenie PL/SQL PL/SQL Cechy PL/SQL

Plan bazy: Kod zakładający bazę danych: DROP TABLE noclegi CASCADE; CREATE TABLE noclegi( id_noclegu SERIAL NOT NULL,

Procedury wyzwalane. (c) Instytut Informatyki Politechniki Poznańskiej 1

Cheatsheet PL/SQL Andrzej Klusiewicz 1/9

Relacyjne bazy danych. Podstawy SQL

Wyzwalacz - procedura wyzwalana, składowana fizycznie w bazie, uruchamiana automatycznie po nastąpieniu określonego w definicji zdarzenia

Microsoft SQL Server Podstawy T-SQL

Bazy danych wykład dwunasty PL/SQL, c.d. Konrad Zdanowski ( Uniwersytet Kardynała Stefana Bazy danych Wyszyńskiego, wykładwarszawa)

PL/SQL. Zaawansowane tematy PL/SQL

SQL :: Data Definition Language

Blaski i cienie wyzwalaczy w relacyjnych bazach danych. Mgr inż. Andrzej Ptasznik

BAZA DANYCH SIECI HOTELI

SQL (ang. Structured Query Language)

Wykład 5. SQL praca z tabelami 2

Wykład 8. SQL praca z tabelami 5

SQL 4 Structured Query Lenguage

Procedury i funkcje składowane

Podstawy języka T-SQL : Microsoft SQL Server 2016 i Azure SQL Database / Itzik Ben-Gan. Warszawa, Spis treści

41. Zmienne lokalne muszą mieć nazwę, którą poprzedza (maksymalnie 128 znaków) oraz typ (każdy z wyjątkiem: text, ntext oraz image)

Zaawansowane bazy danych i hurtownie danych semestr I

Relacyjne bazy danych. Podstawy SQL

Pakiety podprogramów Dynamiczny SQL

Języki programowania wysokiego poziomu. PHP cz.4. Bazy danych

Język PL/SQL. Rozdział 5. Pakiety podprogramów. Dynamiczny SQL

w PL/SQL bloki nazwane to: funkcje, procedury, pakiety, wyzwalacze

Październik Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska. Systemy baz danych - wykład III. dr inż.

Hurtownia Świętego Mikołaja projekt bazy danych

Instrukcja podwaja zarobki osób, których imiona zaczynają się P i dalsze litery alfabetu zakładamy, że takich osbób jest kilkanaście.

Wykład 6. SQL praca z tabelami 3

Bazy danych. Bazy danych. Podstawy języka SQL. Dr inż. Paweł Kasprowski.

Systemy GIS Tworzenie zapytań w bazach danych

1. ELEMENTY JĘZYKA PL/SQL

Język SQL, zajęcia nr 1

Bloki anonimowe w PL/SQL

KOLEKCJE - to typy masowe,zawierające pewną liczbę jednorodnych elementów

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

Wykład V. Indeksy. Struktura indeksu składa się z rekordów o dwóch polach

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek].

Oracle PL/SQL. Paweł Rajba.

LAB 6 BEGIN TRANSACTION, COMMIT, ROLLBACK, SET TRANSACTION ISOLATION LEVEL,

Oracle PL/SQL. Paweł Rajba.

Język PL/SQL Procedury i funkcje składowane

Używany kiedy pełna treść instrukcji SQL jest nieznana przed uruchomieniem programu.

T-SQL dla każdego / Alison Balter. Gliwice, cop Spis treści. O autorce 11. Dedykacja 12. Podziękowania 12. Wstęp 15

Procedury składowane. Funkcje vs. procedury Funkcja. Procedura. zazwyczaj ma parametry tylko typu IN; można wywoływać z poziomu

P o d s t a w y j ę z y k a S Q L

Obowiązuje od wersji

1 Przetwarzanie transakcyjne Cechy transakcji Rozpoczęcie i zakończenie Punkty bezpieczeństwa... 3

Bazy danych. Wykład IV SQL - wprowadzenie. Copyrights by Arkadiusz Rzucidło 1

przykłady problemów; realizacja dostaw części od producenta do klienta:

ORACLE (Wykład 1) aragorn.pb.bialystok.pl/~aonisko. Typy rozproszonych baz danych. Systemy klient-serwer. Klient-serwer: Przykład

Wstęp 5 Rozdział 1. Podstawy relacyjnych baz danych 9

SQL Server i T-SQL w mgnieniu oka : opanuj język zapytań w 10 minut dziennie / Ben Forta. Gliwice, Spis treści

Ćwiczenia laboratoryjne nr 11 Bazy danych i SQL.

PRZESTRZENNE BAZY DANYCH WYKŁAD 2

Przykłady najlepiej wykonywać od razu na bazie i eksperymentować z nimi.

Bazy danych. Dr inż. Paweł Kasprowski

Przydatne sztuczki - sql. Na przykładzie postgres a.

BAZY DANYCH Cz III. Transakcje, Triggery

strukturalny język zapytań używany do tworzenia i modyfikowania baz danych oraz do umieszczania i pobierania danych z baz danych

1 DML - zapytania, część II Grupowanie Operatory zbiorowe DML - modyfikacja 7. 3 DCL - sterowanie danymi 9.

Oracle PL/SQL. Paweł Rajba.

Tabele wykorzystywane w przykładach

Literatura: SQL Ćwiczenia praktyczne Autor: Marcin Lis Wydawnictwo: Helion. Autor: Joanna Karwowska

Podstawy języka SQL. SQL Structured Query Languagestrukturalny

Struktura drzewa w MySQL. Michał Tyszczenko

Laboratorium nr 4. Temat: SQL część II. Polecenia DML

Pakiety są logicznymi zbiorami obiektów takich jak podprogramy, typy, zmienne, kursory, wyjątki.

Konstruowanie Baz Danych SQL UNION, INTERSECT, EXCEPT

Kursory i wyjątki. (c) Instytut Informatyki Politechniki Poznańskiej 1

Oracle PL/SQL. Paweł Rajba.

Język DML. Instrukcje DML w różnych implementacjach SQL są bardzo podobne. Podstawowymi instrukcjami DML są: SELECT INSERT UPDATE DELETE

Odnawialne Źródła Energii I rok. Tutorial PostgreSQL

050 SQL ELEMENTY ZAAWANSOWANE. Prof. dr hab. Marek Wisła

Paweł Rajba

Cele. Definiowanie wyzwalaczy

Sprawdzenie poziomu izolacji transakcji (w aktualnym połączeniu):

Wyzwalacze. Anna Fiedorowicz Bazy danych 2

Politechnika Gdańska, międzywydziałowy kierunek INŻYNIERIA BIOMEDYCZNA. Instrukcja do laboratorium z przedmiotu: Bazy danych. Laboratorium nr 4.

CREATE DATABASE ksiegarnia_internetowa DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Programowanie w SQL. definicja bloku instrukcji BEGIN...END, warunkowe wykonanie instrukcji IF...ELSE, wyrażenie CASE,

1 Wprowadzenie do bloków nazwanych 1. 2 Parametry 2. 3 Procedury i funkcje 3. 4 Pakiety 6. 5 Podsumowanie Źródła 10

Deklarowanie kursora

Transkrypt:

Bazy danych Zaawansowane przetwarzanie danych Marcin Szpyrka Katedra Informatyki Stosowanej AGH w Krakowie 2015/16 Literatura 1. Jeffrey D. Ullman, Jennifer Widom: Podstawowy kurs systemów baz danych, Helion, Gliwice, 2011 2. Thomas Connolly, Carolyn Begg: Systemy baz danych, tom 1 i 2, Wydawnictwo RM, Warszawa, 2004 3. Hector Garcia-Molina, Jeffrey D. Ullman, Jennifer Widom: Systemy baz danych. Pełny wykład, WNT, Warszawa, 2006 4. Chris J. Date: Relacyjne bazy danych dla praktyków, Wydawnictwo Helion, Gliwice, 2006 5. Joe Celko: SQL zaawansowane techniki programowania, Wydawnictwo Naukowe PWN, Warszawa, 2008 6. Sharon Allen: Modelowanie danych, Wydawnictwo Helion, Gliwice, 2006 7. http://www.postgresql.org dokumentacja systemu PostgreSQL. 8. Antoni Ligęza: Materiały do wykładów z baz danych, http://home.agh.edu.pl/ligeza/wiki Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 2/75

Podzapytania Zapytanie, które jest częścią innego zapytania nazywamy podzapytaniem. Podzapytania mogą zawierać inne podzapytania i mogą być zagnieżdżane do dowolnego poziomu. Rodzaje podzapytań Podzapytania skalarne zwracają pojedynczą wartość mogą być użyte wszędzie tam, gdzie wymagana jest pojedyncza wartość. Podzapytania krotkowe zwracają pojedynczą krotkę używane są w miejscach gdzie wymagany jest konstruktor wartości krotkowych. Podzapytania relacyjne zwracają wartość relacyjną (zbiór krotek) mogą być użyte wszędzie tam, gdzie wymagana jest relacja. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 3/75 Zasady używania podzapytań Podzapytanie zawsze umieszczamy w nawiasie okrągłym. Podzapytanie może odwoływać się do atrybutów z otaczającego je zapytania, które są traktowane jak stałe przy każdej ewaluacji podzapytania. Podzapytanie odwołujące się do atrybutów z zapytania nadrzędnego nazywamy skorelowanym. Domyślnie nazwy atrybutów w podzapytaniu odnoszą się do nazw atrybutów z relacji wymienionych w klauzuli from tego podzapytania. W podzapytaniach nie wolno używać klauzuli order by. Jeżeli podzapytanie jest jednym z dwóch argumentów porównania, to musi występować po prawej stronie porównania. atrybuty z zewnętrznego zapytania select nazwisko, imie, (select max(punkty) from punktujace where punktujace.numer = siatkarki.numer and punktujace.iddruzyny = siatkarki.iddruzyny) as maksimum from siatkarki order by 3 desc; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 4/75

Podzapytania w klauzuli where przykłady select nazwisko, imie, punkty from siatkarki natural join punktujace where punkty = (select max(punkty) from punktujace); select nazwisko, imie, punkty from siatkarki natural join punktujace where punkty > ((select max(punkty) from punktujace) - 5) order by punkty desc; select nazwa, miasto from druzyny where iddruzyny in (select iddruzyny from punktujace where punkty > 25); select nazwa, miasto from druzyny where iddruzyny in (select iddruzyny from punktujace where punkty > 2 * (select avg(punkty) from punktujace)); Znak = może być użyty, jeśli mamy pewność, że podzapytanie zwróci dokładnie jedną wartość. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 5/75 Operator exists Operator exists służy do sprawdzenia, czy dane zapytanie zwróciło co najmniej jedną wartość tj. czy relacja będąca wynikiem podzapytania nie jest pusta. select * from punktujace natural join siatkarki where punkty > 8 and pozycja = rozgrywająca ; select nazwa, miasto from druzyny where exists (select * from punktujace natural join siatkarki where punktujace.iddruzyny = druzyny.iddruzyny and punkty > 8 and pozycja = rozgrywająca ); Ponieważ wartości zwracanych krotek nie mają żadnego znaczenia, często zwraca się po prostu jakąś stałą wartość. select nazwa, miasto from druzyny where not exists (select 1 from punktujace natural join siatkarki where punktujace.iddruzyny = druzyny.iddruzyny and punkty > 25); Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 6/75

Podzapytania w klauzuli where operatory (1) <exp> in (<list>) wyrażenie <exp> należy do listy zwracanej przez podzapytanie; <exp> not in (<list>) wyrażenie <exp> nie należy do listy zwracanej przez podzapytanie; <exp> <rel> any (<list>) wyrażenie <exp> spełnia relację <rel> w odniesieniu do co najmniej jednego z elementów zwracanej przez podzapytanie (zamiast any można użyć some, zamiast = any można użyć in); <exp> <rel> all (<list>) wyrażenie <exp> spełnia relację <rel> w odniesieniu do wszystkich elementów zwracanej przez podzapytanie; exists podzapytanie zwraca jakąś wartość; not exists podzapytanie nie zwraca żadnej wartości; <rel> zwykle operator porównania: =, >, <, >=, <=, <>. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 7/75 Podzapytania w klauzuli where operatory (2) <exp> <> any (<list>) oznacza: <exp> not in (<list>) oznacza: <exp> l 1 <exp> l 2... <exp> l k <exp> l 1 <exp> l 2... <exp> l k Predykaty: x >= all (select...) i x >= (select max(x)...) nie są równoważne, ze względu na fakt, że funkcja max ignoruje wartości null. create table a (x integer); create table b (x integer); insert into a values (1), (2), (4), (5); insert into b values (1), (2), (3), (NULL); select x from a where x >= all (select x from b); -- (0 rows) select x from a where x >= (select max(x) from b); -- 4 -- 5 -- (2 rows) Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 8/75

Wartość null i predykat in (1) W przypadku zastosowania operatora not in, należy zwrócić uwagę na fakt, czy na liście wartości zwracanej przez podzapytanie może pojawić się null. Jeżeli tak się stanie, to wynikiem całego zapytania będzie pusta relacja. create table a (x integer); create table b (x integer); insert into a values (1), (2), (3), (4); insert into b values (1), (NULL), (2); select * from a where x not in (select x from b); --- (0 rows) Przekształcenia: where x not in (select x from b) where x not in (1, NULL, 2) where not (x in (1, NULL, 2)) where not ((x = 1) or (x = NULL) or (x = 2)) where ((x <> 1) and (x <> NULL) and (x <> 2)) where ((x <> 1) and UNKNOWN and (x <> 2)) where UNKNOWN Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 9/75 Wartość null i predykat in (2) Wartość null z tabeli a nie spełnia warunku, więc nie znajdzie się w wyniku. create table a (x integer); create table b (x integer); insert into a values (1), (2), (NULL), (4); insert into b values (1), (2), (3); select * from a where x not in (select x from b); --- 4 (1 row) Przekształcenia: where x not in (select x from b) where x not in (1, 2, 3) where not (x in (1, 2, 3)) where not ((x = 1) or (x = 2) or (x = 3)) where ((x <> 1) and (x <> 2) and (x <> 3)) Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 10/75

Predykat exists i złączenia Bardzo często podzapytanie z predykatem exists (not exists) może zostać spłaszczone do użycia join. create table a (x integer); create table b (x integer); insert into a values (1), (2), (4), (5); insert into b values (1), (2), (3); select * from a where exists (select * from b where a.x = b.x); -- --- -- 1 -- 2 select a.x from a join b on a.x = b.x; -- --- -- 1 -- 2 select * from a where not exists (select * from b where a.x = b.x); -- --- -- 4 -- 5 select a.x from a left outer join b on a.x = b.x where b.x is null; -- --- -- 4 -- 5 Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 11/75 Podzapytania w klauzuli from Podzapytania użyte w klauzuli from muszą mieć przypisane aliasy. select avg(pkt)::numeric(5,2) from (select sum(punkty) pkt from punktujace group by idmeczu) p; select avg(pkt)::numeric(5,2) from (select idmeczu, iddruzyny, sum(punkty) pkt from punktujace group by idmeczu, iddruzyny) p; select nazwa, pkt from druzyny natural join (select idmeczu, iddruzyny, sum(punkty) pkt from punktujace group by idmeczu, iddruzyny) p; select nazwa, avg(pkt)::numeric(5,2) from druzyny natural join (select idmeczu, iddruzyny, sum(punkty) pkt from punktujace group by idmeczu, iddruzyny) p group by nazwa order by 2 desc; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 12/75

Podzapytania w klauzuli having select idmeczu, termin, sum(punkty) from punktujace natural join mecze group by idmeczu, termin having sum(punkty) > (select avg(pkt)::numeric(5,2) from (select sum(punkty) pkt from punktujace group by idmeczu) p) order by 3; select nazwisko, imie, sum(punkty) from siatkarki natural join punktujace group by nazwisko, imie having sum(punkty) > (select sum(punkty) from siatkarki natural join punktujace where nazwisko = Kosek and imie = Karolina ) order by 3 desc; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 13/75 Klauzula with (1) Klauzula with pozwala na definiowania pomocniczych wyrażeń, które są następnie wykorzystywane w wyrażeniu głównym. W najprostszej postaci, stanowi ona alternatywną wersję zapisywania zapytań z podzapytaniami w klauzuli from. with p as ( select sum(punkty) pkt from punktujace group by idmeczu ) select avg(p.pkt)::numeric(5,2) from p; with p as (select idmeczu, iddruzyny, sum(punkty) pkt from punktujace group by idmeczu, iddruzyny) select nazwa, avg(pkt)::numeric(5,2) from druzyny natural join p group by nazwa order by 2 desc; with suma_zamowienia as ( select idklienta, sum(cena) as suma_zam from zamowienia group by idklienta), suma_historia as (select idklienta, sum(cena) as suma_his from historia group by idklienta) select idklienta, nazwa, coalesce(suma_zamowienia.suma_zam,0) + coalesce(suma_historia.suma_his,0) from klienci left join suma_zamowienia using(idklienta) left join suma_historia using(idklienta) order by 3 desc; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 14/75

Klauzula with (2) Klauzula with może być również użyta z instrukcjami insert, update, delete. Klauzula returning jest wówczas stosowana do zwrócenia rekordów przetwarzanych przez wyrażenie pomocnicze. with archiwizacja as ( delete from zamowienia where termin = 2007-04-29 returning * ) insert into historia select idzamowienia, idklienta, idkompozycji, cena, termin from archiwizacja; with p as ( update kompozycje set cena = cena * 1.1 returning * ) select idkompozycji, nazwa, cena from p; with p as ( update kompozycje set cena = cena * 1.1 returning * ) select idkompozycji, nazwa, cena from kompozycje; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 15/75 Dzielenie relacji Niech H 1 = {A 1, A 2,..., A n, B 1, B 2,..., B k } będzie nagłówkiem relacji R i niech H 2 = {B 1, B 2,..., B k } będzie nagłówkiem relacji S, przy czym zakładamy że S. Iloraz R S jest relacją o schemacie H = {A 1, A 2,..., A n }, która zawiera wszystkie krotki t o schemacie H takie, że dla dowolnej krotki s S, krotka {t, s} R. Dostawca Budex Budex Budex Budex Matbud Matbud Matbud Matbud Probud Probud Probud Probud Element cegła pustak cement piasek pustak cement gips piasek cegła cement piasek żwir Element cegła cement piasek = Dostawcy Budex Probud Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 16/75

Dzielenie implementacja (1) create table kandydaci ( id integer primary key, imie varchar(30) not null, nazwisko varchar(30) not null ); insert into kandydaci values(1, Adam, Nowak ); insert into kandydaci values(2, Piotr, Nowak ); insert into kandydaci values(3, Karol, Nowakowski );... create table jezyki ( id integer not null, jezyk varchar(10) not null, primary key(id,jezyk) ); insert into jezyki values(1, angielski ); insert into jezyki values(1, niemiecki ); insert into jezyki values(1, rosyjski );... create table wymagane_jezyki ( jezyk varchar(10) primary key); insert into wymagane_jezyki values( angielski ); insert into wymagane_jezyki values( rosyjski ); Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 17/75 Dzielenie implementacja (2) -- dzielenie definicyjne select id, imie, nazwisko from kandydaci natural join jezyki except -- ponizsze zapytanie zwraca dane kandydatow, -- ktorzy nie znaja co najmniej jednego z wymaganych jezykow select id, imie, nazwisko from ( -- wszystkie mozliwe wpisy kandydat + wymagany jezyk select id, imie, nazwisko, j.jezyk from kandydaci, wymagane_jezyki j except -- istniejące wpisy kandydat + jezyk select * from kandydaci natural join jezyki ) p; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 18/75

Dzielenie implementacja (3) -- dzielenie wg Celko select distinct id, imie, nazwisko from (kandydaci natural join jezyki) kj1 where not exists ( select * from wymagane_jezyki j where not exists ( select * from (kandydaci natural join jezyki) kj2 where kj2.id = kj1.id and kj2.jezyk = j.jezyk ) ); -- dzielenie wg Celko z except select distinct id, imie, nazwisko from (kandydaci natural join jezyki) kj1 where not exists ( select jezyk from wymagane_jezyki except select jezyk from (kandydaci natural join jezyki) kj2 where kj2.id = kj1.id ); -- dla których nie -- istnieje taki język w j -- że ta osoba nie zna -- tego jezyka Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 19/75 Porównywanie wzorców POSIX Regular Expressions Operator Znaczenie ~ dopasowanie do wzorca, czuły na wielkość znaków ~* dopasowanie do wzorca, nieczuły na wielkość znaków!~ brak dopasowania do wzorca, czuły na wielkość znaków!~* brak dopasowania do wzorca, nieczuły na wielkość znaków W przeciwieństwie do wzorców używanych w like, w przypadku wyrażeń regularnych standardu POSIX, wyrażenie regularne nie musi pasować do całego napisu, ale może pasować tylko do jego części. Można wymusić by był to np. początek lub koniec napisu. POSIX (ang. Portable Operating System Interface for Unix) dosłownie przenośny interfejs systemu operacyjnego. POSIX standaryzuje: interfejs programistyczny (API); interfejs użytkownika, np. polecenia systemowe; właściwości powłoki systemu. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 20/75

Wyrażenia regularne - POSIX Wyrażenie regularne jest definiowane jako jako jedna lub więcej gałęzi oddzielonych znakiem. Pasuje ono do dowolnego napisu, który pasuje do co najmniej jednej z gałęzi. Gałąź składa się z połączonych zero lub więcej atomów z określoną krotnością lub ograniczeń. Pusta gałąź pasuje do pustego napisu. Atom z określoną krotnością jest atomem z opcjonalnym określeniem jego krotności. Brak określenia krotności oznacza jego pojedyncze wystąpienie. Ograniczenie pasuje do pustego napisu, ale tylko wtedy, gdy spełnione są zadane warunki (np. dla kotwicy $ jest to koniec napisu). Może być używane w dowolnym miejscu, tak jak atom, ale nie może mieć określenia krotności. Określenia krotności nie mogą występować po sobie, nie mogą zaczynać wyrażeń i podwyrażeń, ani występować bezpośrednio po znakach ^ i. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 21/75 Symbole - POSIX Atom Znaczenie (re) dopasowanie do re, gdzie re jest wyrażeniem regularnym. (kropka) pojedynczy znak [znaki] dopasowanie do jednego z wymienionych znaków \k dopasowanie do symbolu k traktowanego jako zwykły znak (k nie jest symbolem alfanumerycznym), np. \\ oznacza ukośnik wsteczny { jeżeli po { nie występuje cyfra, to jest to dopasowanie do znaku { x dopasowanie do znaku x (x jest zwykłym znakiem bez specjalnego znaczenia) Wyrażenie [^znaki] oznacza dopasowanie do dowolnego znaku nie znajdującego się na liście. Wyrażenie [znak1-znak2] oznacza zakres znaków, np [a-d] Nazwa klasy znaków umieszczona wewnątrz ograniczników [[: :]] oznacza listę wszystkich znaków należących do tej klasy. Dostępne nazwy klas to: alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit. Wyrażenia [[:<:]] i [[:>:]] są specjalnymi ograniczeniami oznaczającymi dopasowanie odpowiednio do początku i końca słowa. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 22/75

Symbole - POSIX (cd) Krotność Znaczenie * 0 lub więcej wystąpień atomu + 1 lub więcej wystąpień atomu? 0 lub 1 wystąpień atomu {n} n wystąpień atomu {m,} co najmniej m wystąpień atomu {m,n} od m do n włącznie wystąpień atomu (m n) UWAGA: Parametry m i n mogą przyjmować wyłącznie wartości całkowite z zakresu od 0 do 255. Ograniczenie Znaczenie ^ dopasowanie do początku łańcucha znaków $ dopasowanie do końca łańcucha znaków Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 23/75 Porównywanie wzorców POSIX przykłady select nazwa from druzyny where nazwa ~* stal ; select iddruzyny, nazwa from druzyny where iddruzyny ~ b{2} ; select nazwa from druzyny where nazwa ~ BKS AZS MKS ; select nazwa from druzyny where nazwa ~ ^B ; select nazwa from druzyny where nazwa ~ S$ ; select nazwa from druzyny where nazwa ~ [[:<:]]B ; select nazwa from druzyny where nazwa ~ S[[:>:]] ; select nazwa from druzyny where nazwa ~ ^[^B].*[[:<:]]B ; select nazwa from druzyny where nazwa ~.{10} ; select miasto from druzyny where miasto ~ [c-e] ; select miasto from druzyny where miasto ~ [ce-] ; select miasto from druzyny where miasto ~ i[ae].*k ; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 24/75

Porównywanie wzorców POSIX przykłady select * from napisy where napis ~ [01]+ ; select * from napisy where napis ~ ^[01]+ ; select * from napisy where napis ~ ^[01]+$ ; select * from napisy where napis ~ ^(01)+$ ; select * from napisy where napis ~ ^(01)+.$ ; select * from napisy where napis ~ ^(01)+.*$ ; select * from napisy where napis ~ (10)+(01)+ ; select * from napisy where napis ~ (10)+.(01)+ ; select * from napisy where napis ~ la ; select * from napisy where napis ~.la ; select * from napisy where napis ~ ^.la ; select * from napisy where napis ~ ^..+la ; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 25/75 Rozszerzenie SQL języki proceduralne PostgreSQL umożliwia korzystanie z języków proceduralnych. Przed wykorzystaniem danego języka, należy wprowadzić w PostgreSQL ustawienia, włączające obsługę tego języka. Dla języka PL/pgSQL program obsługi jest dołączony w dystrybucji jako współdzielona biblioteka. Aby zainstalować język PL/pgSQL dla bazy danych, można skorzystać z polecenia create language w psql i załadować współdzieloną bibliotekę lub wykorzystać skrypt pomocniczy wywołany z konta użytkownika postgres. createlang plpgsql nazwa_bazy Informacje o załadowanych językach przechowywane są w tabeli pg_language. select * from pg_language; drop language nazwa_jezyka ; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 26/75

Funkcje create function nazwa ([typ_funkcji [,...]]) returns typ_wyniku as definicja language nazwa_języka Definicję funkcji podaje się jako pojedynczy ciąg znaków, który może obejmować kilka wierszy. Można go zapisać w dowolnym języku programowania obsługiwanym przez PostgreSQL jako ładowalny język proceduralny. Po utworzeniu funkcji, jej definicja jest zapisywana w bazie danych. Kiedy funkcja jest wywoływana po raz pierwszy, definicja funkcji jest kompilowana przez program obsługi do postaci wykonywalnej, a następnie wykonywana. Dopiero użycie funkcji pozwala na wykrycie jej ewentualnych błędów. PostgreSQL uznaje funkcje za różne, jeżeli mają one różne nazwy lub różną liczbę parametrów, albo parametry są innego typu. select prosrc from pg_proc where proname= nazwa_funkcji ; drop function nazwa_funkcji; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 27/75 PL/pgSQL cechy języka Może być używany do definiowania funkcji użytkownika i procedur wyzwalanych. Rozszerza język SQL o struktury sterujące (instrukcje wyboru, pętle). Pozwala wykonywać złożone obliczenia. Pozwala na zgrupowanie ciągu instrukcji SQL w ramach pojedynczej funkcji przechowywanej po stronie serwera (ograniczenie danych przesyłanych między serwerem i klientem nie są przesyłane dane pośrednie). Funkcje pisane w PL/pgSQL mogą przyjmować jako argumenty i zwracać jako wyniki wartości typów skalarnych i tablicowych akceptowanych przez serwer. Możliwa jest również obsługa typów złożonych (rekordów), polimorficznych, zbiorów rekordów, a nawet tabel. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 28/75

PL/pgSQL PL/pgSQL to język blokowo-strukturalny, podobny do języka Pascal lub C, z deklaracjami zmiennych i zakresami bloków. Każdy blok ma opcjonalną etykietę, może posiadać kilka deklaracji zmiennych i zamyka instrukcje tworzące blok pomiędzy słowami kluczowymi oraz end. [<<etykieta>>] declare deklaracje instrukcje end; W języku PL/pgSQL wielkość liter nie ma znaczenia. Funkcje PL/pgSQL mogą nie mieć argumentów lub mogą mieć ich kilka (możliwe jest definiowanie funkcji ze zmienną liczbą argumentów). Typ parametrów podaje się w nawiasach, po nazwie funkcji. Można stosować wbudowane typy PostgreSQL, takie jak int4 lub float8. Jeżeli nie podamy nazw parametrów, to odwołania do parametrów wewnątrz treści funkcji mają postać $1, $2 itd., w kolejności ich definiowania. Typ zwracanego wyniku określa się w klauzuli returns definicji funkcji. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 29/75 Funkcje przykład create function zysk(cena numeric(7,2)) returns numeric(7,2) as if cena < 75.00 then return 0.05 * cena; elseif cena >= 75.00 and cena <= 110.00 then return 0.07 * cena; else return 0.08 * cena; end if; end; language plpgsql; drop function zysk(numeric(7,2)); create or replace function zysk(cena numeric(7,2)) returns numeric(7,2) as... Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 30/75

Zgłaszanie komunikatów i wyjątków create function zysk2(cena numeric(7,2)) returns numeric(7,2) as if cena <= 0.00 then raise exception Niepoprawna cena: %., $1; else raise notice Obliczenia dla wartości: %., $1; end if; if cena < 75.00 then return 0.05 * cena; elsif cena >= 75.00 and cena <= 110.00 then return 0.07 * cena; else return 0.08 * cena; end if; end; language plpgsql; select zysk2(-23.00); -- ERROR: Niepoprawna cena: -23.00. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 31/75 Instrukcje warunkowe if wyrazenie_logiczne then instrukcje [ elsif wyrazenie_logiczne then instrukcje... ] [ else instrukcje ] end if; case wyrazenie when wyrazenie [, wyrazenie [...]] then instrukcje [ when wyrazenie [, wyrazenie [...]] then instrukcje... ] [ else instrukcje ] end case; case when wyrazenie_logiczne then instrukcje [ when wyrazenie_logiczne then instrukcje... ] [ else instrukcje ] end case; case x when 1, 2 then y := 0; when 3, 4, 5 then y := 1; else y := 2; end case; case when x between 0 and 1 then y := 0; when x between 2 and 5 then y := 1; else y := 2; end case; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 32/75

Deklarowanie zmiennych Wszystkie zmienne muszą zostać zadeklarowane w bloku deklaracji przed ich użyciem. Wyjątkiem są iteratory pętli for (całkowite i kursory). n integer; w numeric(7,2); pudelko pudelka%rowtype; id pudelka.nazwa%type; element record; name [constant] type [not null] [{ default := } expression]; Jeżeli nie użyto default, to zmienne początkowo mają przypisane null. Zmienne, którym dodano ograniczenie not null, muszą mieć ustawioną wartość domyślną. Wartość domyślna jest ustawiana zawsze przy wejściu do danego bloku. Jeżeli definiując funkcję nie podano nazw parametrów, to w bloku deklaracji można zdefiniować dla nich aliasy. id alias for $1 Jako nazw zmiennych (parametrów) nie należy używać nazw tabel i kolumn tych tabel. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 33/75 Przypisanie Operator przypisania: zmienna := wartość Operacje przypisania są wykonywane przez serwer PostgreSQL jako instrukcje select nawet, gdy używany jest operator :=. Poprzez dołączenie klauzuli from można wykorzystać select do przypisywania zmiennym wartości z bazy danych. Należy zapewnić, że instrukcja select zwróci tylko jeden wiersz, ponieważ dodatkowe wiersze zostaną pominięte bez wyświetlania jakichkolwiek komunikatów, zaś do zmiennej będzie przypisany tylko pierwszy zwrócony wiersz. create or replace function suma_zamowien(klient text) returns numeric(7,2) as declare w numeric(7,2); select sum(cena) into w from zamowienia where idnadawcy = klient; return w; end; language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 34/75

Rekordy Rekord jest rodzajem typu złożonego, który w czasie deklarowania zmiennej nie opiera się na konkretnej tabeli. Zawiera on pola, które są zgodne w czasie wykonania z przypisaną do niego wartością. Rekordy można wykorzystać do zapisywania wyników instrukcji select. Należy zapewnić, że instrukcja select zwróci tylko jeden wiersz, ponieważ dodatkowe wiersze zostaną pominięte bez wyświetlania jakichkolwiek komunikatów, zaś do zmiennej będzie przypisany tylko pierwszy zwrócony wiersz. Istnieje możliwość, że instrukcja select nie zwróci żadnego wiersza. W takim przypadku operacja przypisanie nie będzie wykonana. W PostgreSQL występuje zmienna logiczna found, która jest dostępna natychmiast po wykonaniu operacji przypisania z wykorzystaniem instrukcji select into. wynik record; select * into wynik from klienci where idklienta = 9; if not found then -- dzialania awaryjne end if; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 35/75 Pętle (1) Najprostszą pętlą jest pętla niekontrolowana, która wykonuje się nieskończenie, o ile nie zamieścimy wewnątrz instrukcji exit lub return. [<<etykieta>>] loop instrukcje end loop; Wszystkie konstrukcje loop mogą posiadać etykiety, które są wykorzystywane w instrukcji exit. Instrukcja ta powoduje zakończenie odpowiedniej pętli. Etykieta musi odnosić się do bieżącej pętli lub do pętli zewnętrznej. Jeżeli etykieta nie jest określona, zakończona zostaje pętla bieżąca. Jeżeli występuje klauzula when, instrukcja exit nie wykonuje się, chyba że wartością wyrażenia jest true. Podobnie funkcjonuje instrukcja continue. <<infinite>> loop n := n + 1; exit infinite when n >= 10; end loop; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 36/75

Pętle (2) while wyrazenie loop instrukcje end loop; for nazwa in [reverse] od.. do loop instrukcje end loop; for wiersz in select... loop instrukcje end loop; Dla każdego z wierszy zwracanego przez instrukcję select, zmienna wiersz przyjmuje wartość tego wiersza, po czym wykonywane są instrukcje. Zmienną wykorzystywaną do zapamiętania wiersza należy wcześniej zadeklarować jako record lub rowtype. Ostatni przetworzony wiersz będzie dostępny również po zakończeniu wykonywania pętli lub przerwaniu jej działania za pomocą instrukcji exit. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 37/75 Zwracanie wartości przez funkcję (1) Jeżeli funkcja zwraca pojedynczą wartość, to używana jest instrukcja return wyrażenie. Kończy ona jednocześnie wykonywanie funkcji. Funkcje mogą być deklarowane z argumentami wyjściowymi. Pozwala to zwrócić funkcji więcej niż jeden wynik. W takim przypadku użycie return (bez wartości) kończy wykonanie funkcji podobnie, jeśli funkcja zwraca wartość typu void. Ponadto w przypadku tych funkcji użycie return nie jest konieczne. create or replace function podsumowanie(nr int, druzyna varchar, out mecze int, out srednia numeric) as select count(idmeczu), avg(punkty) into mecze, srednia from siatkarki natural join punktujace where numer = nr and iddruzyny = druzyna group by numer, iddruzyny; end language plpgsql; select podsumowanie(1, musz ); -- (15,4.1333333333333333) Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 38/75

Pętle przykład create or replace function wynik(f_idmeczu smallint, out f_gospodarze smallint, out f_goscie smallint) as declare t_gospodarze smallint[]; t_goscie smallint[]; i smallint; f_gospodarze := 0; f_goscie := 0; select gospodarze into t_gospodarze from statystyki where idmeczu = f_idmeczu; select goscie into t_goscie from statystyki where idmeczu = f_idmeczu; i := 1; while t_gospodarze[i] is not null loop if t_gospodarze[i] > t_goscie[i] then f_gospodarze := f_gospodarze + 1; else f_goscie := f_goscie + 1; end if; i := i + 1; end loop; end language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 39/75 Zwracanie wartości przez funkcję (2) Funkcja jako wynik może zwracać tabelę. Jest to równoważne zdefiniowaniu kilku argumentów wyjściowych i określenia wyniku funkcji jako setof typ. UWAGA: Nazwy kolumn zwracanej tabeli nie mogą pokrywać się z nazwami kolumn tabeli, na której oparto zapytanie. create or replace function wyniki_sezonu() returns table (f_numer smallint, f_iddruzyny varchar(5), f_imie varchar(12), f_nazwisko varchar(30), f_idmeczu smallint, f_punkty smallint) as return query select numer, iddruzyny, imie, nazwisko, idmeczu, punkty from siatkarki natural join punktujace; end language plpgsql; select wyniki_sezonu(); Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 40/75

Typy polimorficzne PostgreSQL dostarcza typy polimorficzne: anyelement (dowolny typ), anyarray (dowolny typ tablicowy), anynonarray (dowolny typ nietablicowy), i anyenum (dowolny typ wyliczeniowy). Dowolna funkcja stosująca te typy określana jest jako polimorficzna. Funkcja taka może pracować na równych typach danych, a aktualne typy są wnioskowane na podstawie argumentów. Funkcja może mieć określone jako argumenty kilka wartości np. typu anyelement, ale przy konkretnym jej wywołaniu wszystkie one muszą mieć jeden wspólny typ danych. Jeżeli w definicji funkcji pojawiają się argumenty anyelement i anyarray, to przy konkretnym jej wywołaniu typy tablicowe muszą być tablicami typu skojarzonego z anyelement itd. Jeżeli funkcja zwraca jako wynik typ polimorficzny, to jeden z jej argumentów musi być typu polimorficznego. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 41/75 Zwracanie wartości przez funkcję (3) Jeżeli funkcja ma określony typ wyniku jako polimorficzny, to jest on reprezentowany przez specjalny parametr $0. Jest on inicjowany wartością null. create function add_three_values(v1 anyelement, v2 anyelement, v3 anyelement) returns anyelement as declare result alias for $0; result := v1 + v2 + v3; return result; end; language plpgsql; create function add_three_values(v1 anyelement, v2 anyelement, v3 anyelement, out result anyelement) as result := v1 + v2 + v3; end; language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 42/75

Zwracanie wartości przez funkcję (4) Funkcja jako wynik może zwrócić zbiór rekordów. create temporary table wyniki (mecz smallint, punkty smallint); create or replace function punkty_w_meczach(f_numer int, f_iddruzyny varchar) returns setof wyniki as return query select idmeczu, punkty from punktujace where numer = f_numer and iddruzyny = f_iddruzyny; end language plpgsql; create or replace function punkty_w_meczach_2(f_numer int, f_iddruzyny varchar, out f_idmeczu smallint, out f_punkty smallint) returns setof record as return query select idmeczu, punkty from punktujace where numer = f_numer and iddruzyny = f_iddruzyny; end language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 43/75 Zwracanie wartości przez funkcję (5) Użycie return query (podobnie return next) nie powoduje wyjścia z funkcji, ale dodaje tylko kolejny wiersze (lub wiersz) do wyniku. Obie konstrukcje mogą wystąpić w ramach jednej funkcji w dowolnej kolejności. Jeżeli funkcja używa parametrów wyjściowych, to użycie return next (bez argumentu) powoduje dodanie do zbioru wynikowego rekordu z aktualnymi wartościami parametrów wyjściowych. create or replace function lista_meczow(f_iddruzyny varchar) returns setof smallint as return query select idmeczu from mecze where gospodarze = f_iddruzyny; return query select idmeczu from mecze where goscie = f_iddruzyny; return next 100; end language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 44/75

Zastosowanie funkcji przykłady select idmeczu, d1.nazwa gospodarze, d2.nazwa goscie, wynik(idmeczu) from druzyny d1 join mecze m on d1.iddruzyny = m.gospodarze join druzyny d2 on d2.iddruzyny = m.goscie order by idmeczu; select idmeczu, d1.nazwa gospodarze, d2.nazwa goscie, (wynik(idmeczu)).f_gospodarze from druzyny d1 join mecze m on d1.iddruzyny = m.gospodarze join druzyny d2 on d2.iddruzyny = m.goscie order by idmeczu; select idmeczu, d1.nazwa gospodarze, d2.nazwa goscie, (s.w).f_gospodarze gosp, (s.w).f_goscie gosc from druzyny d1 join mecze m on d1.iddruzyny = m.gospodarze join druzyny d2 on d2.iddruzyny = m.goscie join (select idmeczu, wynik(idmeczu) w from statystyki) as s using(idmeczu) order by idmeczu; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 45/75 Funkcje przykład (1) create or replace function suma_zamowien(nazwa varchar(10), dni integer) returns numeric(7,2) as declare w1 numeric(7,2); w2 numeric(7,2); select into w1 sum(cena) from zamowienia where idklienta = nazwa; select into w2 sum(cena) from historia where idklienta = nazwa and termin >= Now()::date - dni; if w1 is null then w1 := 0.00; end if; if w2 is null then w2 := 0.00; end if; w1 := w1 + w2; return w1; end; language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 46/75

Funkcje przykład (2) create or replace function rabat(nazwa varchar(10)) returns numeric(7,2) as declare w1 numeric(7,2); w2 numeric(7,2); w1 := suma_zamowien(nazwa,7); w2 := case when w1 <= 100.00 then 0.05 when w1 > 100.00 and w1 <= 400.00 then 0.10 when w1 > 400.00 and w1 <= 700.00 then 0.15 else 0.20 end; return w2; end; language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 47/75 Funkcje przykład (3) create function podwyzka() returns void as declare wiazanka kompozycje%rowtype; for wiazanka in select * from kompozycje loop if wiazanka.cena < 50 then update kompozycje set cena = wiazanka.cena + 5 where idkompozycji = wiazanka.idkompozycji; elseif wiazanka.cena >= 50 and wiazanka.cena <= 100 then update kompozycje set cena = wiazanka.cena + 10 where idkompozycji = wiazanka.idkompozycji; else update kompozycje set cena = wiazanka.cena + 20 where idkompozycji = wiazanka.idkompozycji; end if; end loop; end; language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 48/75

Funkcje przykład (4) create function punkty_zdobyte(druzyna varchar(5), mecz smallint) returns smallint as declare id varchar(5); pkt smallint := 0; select gospodarze into id from mecze where idmeczu = mecz; if id = druzyna then select gospodarze[1] + gospodarze[2] + gospodarze[3] + coalesce(gospodarze[4], 0) + coalesce(gospodarze[5], 0) into pkt from statystyki where idmeczu = mecz; else select goscie into id from mecze where idmeczu = mecz; if id = druzyna then select goscie[1] + goscie[2] + goscie[3] + coalesce(goscie[4], 0) + coalesce(goscie[5], 0) into pkt from statystyki where idmeczu = mecz; end if; end if; return pkt; end; language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 49/75 Funkcje przykład (5) -- 3 pkt. - zwycięstwo -- 2 pkt. - zwycięstwo 3:2 w setach -- 1 pkt. - porażka 2:3 w setach -- 0 pkt. - porażka create function punkty_za_mecz(druzyna varchar(5), mecz smallint) returns smallint as declare id varchar(5); sety_druzyna smallint; sety_przeciwnik smallint; select gospodarze into id from mecze where idmeczu = mecz; if id = druzyna then select (wynik(mecz)).f_gospodarze, (wynik(mecz)).f_goscie into sety_druzyna, sety_przeciwnik; else select goscie into id from mecze where idmeczu = mecz; if id = druzyna then select (wynik(mecz)).f_gospodarze, (wynik(mecz)).f_goscie into sety_przeciwnik, sety_druzyna; end if; end if; if sety_druzyna is not null then if sety_druzyna < 2 then return 0; elseif sety_druzyna = 2 then return 1; elseif sety_przeciwnik = 2 then return 2; else return 3; end if; else return 0; end if; end; language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 50/75

Funkcje przykład zastosowania select nazwa as druzyna, count(idmeczu) as mecze, sum(punkty_za_mecz(iddruzyny,idmeczu)) as punkty, sum(punkty_zdobyte(iddruzyny,idmeczu)) - sum(punkty_stracone(iddruzyny,idmeczu)) as "male punkty" from druzyny join mecze on (iddruzyny = gospodarze or iddruzyny = goscie) where idmeczu <= 20 group by nazwa order by 3 desc; druzyna mecze punkty male punkty ----------------------------+-------+--------+------------- Bank BPS Muszynianka Fakro 4 12 374-311 ENION Energia MKS 4 10 351-294 BKS Aluprof 4 9 342-287 GCB Centrostal 4 9 315-258 IMPEL Gwardia 4 8 353-340 PTPS Piła 4 6 310-302 Pronar Zeto Astwa AZS 4 3 296-350 Organika Budowlani 4 3 318-348 KPSK Stal 4 0 283-345 Gedania 4 0 193-300 (10 wierszy) Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 51/75 Wyzwalacze (1) Wykorzystanie procedury wyzwalanej (ang. trigger) pozwala na automatyczne uruchamianie procedury zapisanej w bazie danych, jeżeli dla określonej tabeli będą podjęte takie działania, jak: insert, update oraz delete. Aby wykorzystać procedurę wyzwalaną, najpierw należy zdefiniować procedurę, a następnie utworzyć sam wyzwalacz, który określa, kiedy procedura wyzwalana będzie wykonywana. create trigger nazwa {before after} {zdarzenie [or...]} on table for each {row statement} execute procedure funkcja(argumenty) Wyzwalacz w istocie informuje: Uruchom tę procedurę przechowywana w bazie danych za każdym razem, kiedy dla tej tabeli zachodzi w bazie danych określone zdarzenie. Wyzwalacz może mieć nazwę, którą można wykorzystać do jego usunięcia, kiedy nie będzie już potrzebny, poprzez wykonanie polecenia: drop trigger nazwa on tabela; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 52/75

Wyzwalacze (2) Wyzwalacz zadziała, kiedy zajdzie określone zdarzenie. Można zażądać, by zadziałał on po zajściu zdarzenia, kiedy to wywoływana procedura będzie miała dostęp do danych pierwotnych (dla aktualizacji i usunięcia) oraz nowych danych (dla wstawiania i aktualizacji). Można także zażądać, by zadziałał przed zajściem zdarzenia. Jeśli aktualizacja wielu wierszy spowoduje działanie wyzwalacza, można wybrać, czy wyzwalacz ma działać dla każdego aktualizowanego wiersza (row), czy też raz dla całej operacji aktualizacji (statement). Wyzwalacz działa w momencie, kiedy są spełnione określone warunki i wykonuje tzw. procedurę wyzwalaną. Procedurę wyzwalaną tworzy się jako funkcję bez parametrów (jeśli w definicji wyzwalacza jest inaczej, to argumenty przekazuje się przez TG_ARGV) oraz o specjalnym typie wyniku trigger. Procedura musi zwracać wartość null lub wiersz odpowiadający strukturze tabeli, dla której ją uruchomiono. Dla wyzwalaczy typu after, które wykonuje się po operacji update, zaleca się, aby procedura wyzwalana zwracała wartość null. Dla wyzwalaczy typu before, zwracany wynik wykorzystuje się do sterowania aktualizacją, która ma być wykonana. Jeżeli procedura wyzwalana zwraca null, operacja update nie jest wykonywana, jeżeli zwracany jest wiersz danych, jest on wykorzystywany jako źródło aktualizacji, dając okazję procedurze wyzwalanej do zmiany danych przed zatwierdzeniem ich w bazie danych. W przypadku wyzwalaczy typu statement funkcja powinna zwracać null. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 53/75 Zmienne dostępne w procedurach wyzwalanych NEW Rekord zawierający nowy wiersz bazy danych. OLD Rekord zawierający stary wiersz bazy danych. TG_NAME Zmienna tekstowa, zawierająca nazwę wyzwalacza, który zadziałał i spowodował wykonanie procedury wyzwalanej. TG_WHEN Zmienna tekstowa zawierająca tekst BEFORE lub AFTER, w zależności od typu wyzwalacza. TG_LEVEL Zmienna tekstowa zawierająca tekst ROW lub STATEMENT, w zależności od definicji wyzwalacza. TG_OP Zmienna tekstowa zawierająca INSERT, DELETE lub UPDATE, w zależności od zdarzenia, które wywołało wyzwalacz. TG_RELID Identyfikator obiektu reprezentujący tabelę, dla której uaktywniono wyzwalacz. TG_RELNAME Nazwa tabeli, dla której uaktywniono wyzwalacz. TG_NARGS Zmienna całkowita, zawierająca liczbę argumentów określonych w definicji wyzwalacza. TG_ARGV Tablica ciągów znaków, zawierająca parametry procedury, rozpoczynająca się od indeksu 0. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 54/75

Wyzwalacze przykład (1) create function fn_zapotrzebowanie() returns trigger as declare s integer; update kompozycje set stan = stan - 1 where idkompozycji = new.idkompozycji; select into s stan from kompozycje where idkompozycji = new.idkompozycji; if s = 1 then insert into zapotrzebowanie values(new.idkompozycji, current_date, null); end if; return null; end; language plpgsql; create trigger tr_zapotrzebowanie after insert on Zamowienia for each row execute procedure fn_zapotrzebowanie(); Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 55/75 Wyzwalacze przykład (2) drop function fn_dostawa(); drop trigger tr_dostawa on kompozycje; create function fn_dostawa() returns trigger as if new.stan > 1 then delete from zapotrzebowanie where idkompozycji = new.idkompozycji; end if; return new; end; language plpgsql; create trigger tr_dostawa after update on kompozycje for each row execute procedure fn_dostawa(); Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 56/75

Tworzenie funkcji agregujących tylko PostgreSQL create aggregate nazwa ( typ_danych_wejsciowych [,... ] ) ( sfunc = funkcja_zmiany_stanu, stype = typ_stanu [, finalfunc = funkcja_finalna ] [, initcond = warunek_poczatkowy ] [, sortop = operator_sortowania ] -- dla agregatów typu ) -- min, max Funkcja agregująca jest identyfikowana na podstawie swojej nazwy i typów argumentów (możliwe jest przeładowanie nazwy). Jej nazwa i typy argumentów nie mogą się również pokrywać z nazwą i typami argumentów innych (nieagregujących) funkcji. Zmienna lokalna typu stype przechowuje wynik cząstkowy. Dla każdej nowej wartości w grupie, stan wewnętrzny jest aktualizowany w oparciu o funkcję zmiany stanu. Dodatkowo na końcu obliczeń jednorazowo stosowana jest funkcja finalna (jeżeli ją określono). Warunek początkowy definiuje stan wyjściowy (w przypadku jego braku używane jest null)). sfunc: (internal_state, next_data_values) next_internal_state ffunc: internal_state aggregate_value Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 57/75 Funkcji agregujące iloczyn elementów create table liczby ( id integer primary key, kategoria char, w1 integer, w2 numeric(6,2), w3 float ); create function product_state(anyelement, anyelement) returns anyelement as return $1 * $2; end; language plpgsql; create aggregate product(anyelement) ( sfunc = product_state, stype = anyelement, initcond = 1 ); select kategoria, product(w1), product(w2), product(w3) from liczby group by kategoria; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 58/75

Funkcji agregujące średnia geometryczna (1) n n x i i=1 create aggregate geometric_mean(double precision) ( sfunc = geometric_mean_state, stype = double precision[], finalfunc = geometric_mean_final, initcond = {1,0} ); select kategoria, geometric_mean(w1) from liczby group by kategoria order by kategoria; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 59/75 Funkcji agregujące średnia geometryczna (2) n n x i create function geometric_mean_state(double precision[], double precision) returns double precision[] as return array[ $1[1] * $2, $1[2] + 1]; end; language plpgsql; i=1 create or replace function geometric_mean_final(double precision[]) returns double precision as if $1[2] = 0 then return null; else return $1[1] ^ (1 / $1[2]); end if; end; language plpgsql; Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 60/75

Funkcji agregujące średnia harmoniczna (1) create aggregate harmonic_mean(double precision) ( sfunc = harmonic_mean_state, stype = double precision[], finalfunc = harmonic_mean_final, initcond = {0,0} ); n n i=1 select harmonic_mean_state( {2,3},2); select harmonic_mean_final( {4,3} ); select kategoria, harmonic_mean(w1) from liczby group by kategoria order by kategoria; 1 x i Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 61/75 Funkcji agregujące średnia harmoniczna (2) create function harmonic_mean_state(double precision[], double precision) returns double precision[] as return array[ $1[1] + (1/$2), $1[2] + 1]; end; language plpgsql; n n i=1 create or replace function harmonic_mean_final(double precision[]) returns double precision as if $1[2] = 0 then return null; else return $1[2] / $1[1]; end if; end; language plpgsql; 1 x i Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 62/75

Transakcje Transakcja jest kolekcją złożoną z jednej lub kilku operacji w bazie danych, które należy wykonać wszystkie lub nie wykonywać żadnej z nich. SQL rozpoczyna transakcję; commit pomyślne zakończenie transakcji wszystkie zmiany w bazie danych przeprowadzone w ramach transakcji zostają zatwierdzone (wcześniej były tymczasowe). rollback porzucenie wszystkie zmiany w bazie danych przeprowadzone w ramach transakcji zostają wycofane. Uwaga: W PostgreSQL nie wolno zagnieżdżać transakcji. Jeżeli spróbujemy wykonać instrukcję podczas trwania transakcji, PostgreSQL wyświetli komunikat informujący, że transakcja jest w toku. Transakcje powinny być niewielkie. Należy także unikać sytuacji, w których transakcja trwa wówczas, gdy jest potrzebny dialog z użytkownikiem. Zaleca się, aby najpierw zebrać od użytkownika wszystkie potrzebne informacje, a następnie przetworzyć je w transakcji, niezależnie od odpowiedzi użytkownika, których nie da się przewidzieć. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 63/75 ACID własności transakcji Niepodzielna (Atomic) Transakcja, mimo że jest zbiorem działań, musi być wykonywana jako pojedyncza jednostka. Transakcja musi odbywać się dokładnie w jednym momencie i nie może dzielić się na podzbiory. Spójna (Consistent) Po zakończeniu wykonywania transakcji system musi być spójny, (ograniczenie powinno być sprawdzone na końcu transakcji). Odizolowana (Isolated) Oznacza to, że każda transakcja, bez względu na to, ile transakcji w danym momencie wykonuje się w bazie danych, musi być niezależna od wszystkich innych transakcji. Trwała (Durable) Po wykonaniu transakcji musi ona zostać utrwalona. W PostgreSQL wykonuje się to za pomocą pliku dziennika transakcji. W czasie wykonywania transakcji zmiany są zapisywane nie tylko do bazy danych, ale także do pliku dziennika. Po zakończeniu transakcji zapisywany jest znacznik, który informuje, że transakcja została zakończona i dane z dziennika transakcji zostały zatwierdzone do zapisu na stałe do bazy danych. Gwarantuje to bezpieczeństwo tych danych, nawet w przypadku awarii bazy danych. Jeżeli z pewnych powodów serwer bazy danych przestanie działać w trakcie transakcji, po ponownym jego uruchomieniu istnieje możliwość automatycznego sprawdzenia, czy zakończone transakcje zostały właściwie odzwierciedlone w bazie danych. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 64/75

Brudne dane W bazie danych możemy zablokować zmodyfikowane w ramach transakcji zmiany do czasu wykonania instrukcji commit lub rollback. Mechanizm ten zapobiega widoczności tymczasowych zmian w innych transakcjach. Istnieje możliwość, że zmodyfikowane dane będą widoczne dla innych transakcji, pomimo że mogą później zostać usunięte z bazy danych po wykonaniu instrukcji rollback. Autor transakcji decyduje, czy widoczność tymczasowych zmian dla innych transakcji jest bezpieczna, czy nie. Brudne dane to dane zapisane w transakcji, ale jeszcze nie zatwierdzone. Brudny odczyt to odczyt brudnych danych zapisanych przez inną transakcję. SQL ustawienie poziomu izolacji set transaction read write; set transaction isolation level read uncommitted; Uwaga: W PostgreSQL odczyt brudnych danych nie jest możliwy, nawet jeżeli ustawimy poziom izolacji na read uncommitted (odczyt niezatwierdzony). Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 65/75 Poziomy izolacji read committed (odczyt zatwierdzony) Poziom ten nie zezwala na odczyt brudnych danych, ale pozwala widzieć zmiany zatwierdzone między czasie przez inne transakcje, tj. w ramach transakcji wykonanie tego samego zapytania wielokrotnie może dawać różne wyniki. repeatable read (odczyt powtarzalny) Poziom ten gwarantuje, że po pobraniu krotki po raz pierwszy, w przypadku ponowienia zapytania otrzymamy identyczną krotkę. Samo powtarzane zapytanie nie musi zwracać za każdym razem tego samego zbioru krotek. Możliwe jest, że w kolejnych powtórzeniach zapytania dostaniemy krotki widma (phantom tuples), tj. krotki wstawione do bazy w trakcie działania transakcji. serializable (odczyt uszeregowany) Poziom ten wyklucza możliwość wystąpienia wszystkich omawianych zjawisk niepożądanych tj.: brudnych odczytów, odczytów nie dających się powtórzyć i odczytów widmo. Transakcja jest wykonywana tak, jakby wszystkie inne równolegle wykonywane transakcje były realizowane przed lub po rozważanej transakcji. Domyślnym trybem izolacji w PostgreSQL jest read committed. System może równolegle wykonywać wiele transakcji, dla których określono różne poziomy izolacji. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 66/75

Zakleszczenia Jeżeli PostgreSQL wykryje zakleszczenie, tzn. dwie czekające jedna na drugą, zablokowane sesje, z których żadna nie może kontynuować działania, to jedna sesja zostanie przerwana, a druga będzie kontynuować działanie. Nie ma sposobu, aby z góry przewidzieć, którą sesję przerwie PostgreSQL. System spróbuje wybrać tę sesję, która wykonuje mniej istotne zmiany. Transakcja 1 Transakcja 2 Komentarz update wiersz 64 update wiersz 83 niezależne update wiersz 83 czeka na zwolnienie 83 update wiersz 64 czeka na zwolnienie 64 auto-rollback automatyczne przerwanie commit Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 67/75 Użytkownicy baz danych PostgreSQL zarządza dostępem do baz danych korzystając z koncepcji roli, która może być zarówno pojedynczym użytkownikiem, jak również grupą użytkowników. Koncepcja roli zastępuje koncepcje użytkownika i grupy użytkowników. Każde połączenie z bazą danych jest realizowane z użyciem nazwy jakiejś roli, zaś uprawnienia przypisane do tej roli decydują jakie operacje na bazie danych będzie można wykonać. SQL create role nazwa; create role nazwa login; drop role nazwa; -- create user nazwa; select rolname from pg_roles; Uwaga: Nazwy użytkowników (role) w systemie PostgreSQL są całkowicie niezależne od nazw użytkowników w systemie operacyjnym. Superużytkownik systemu PostgreSQL (rola tworzona na etapie instalacji) ma nazwę postgres. Tylko rola zdefiniowana z atrybutem login może zostać użyta do połączenia z bazą danych. Marcin Szpyrka Bazy danych Zaawansowane przetwarzanie danych 68/75