Procedury składowane w PostgreSQL/Język PLpgSQL/Instrukcje

Z Wikibooks, biblioteki wolnych podręczników.

Instrukcja pusta[edytuj]

Instrukcja pusta, NULL, służy do wskazania, że nic nie robimy. Może być użyteczne np. przy ignorowaniu pewnych wyjątków.

PostgreSQL dopuszcza aby w niektórych miejscach, gdzie wymagane są instrukcje, nic nie wprowadzać. Lepiej jednak używać instrukcji pustej, żeby jasno wyrazić intencję nic-nie-robienia.

Przypisanie[edytuj]

Instrukcja przypisania ma składnię:

zmienna := wyrażenie;

Zmienna musi być wcześniej zadeklarowana, wyrażenie może być dowolnego typu, dającego się skonwertować na typ zmiennej.

Wczytywanie danych[edytuj]

Do wczytywania pojedynczego wiersza z tabeli służy rozszerzona instrukcja SELECT o składni:

SELECT lista kolumn INTO [ STRICT ] lista zmiennych FROM ...

W najprostszym przypadku w listach kolumn oraz zmiennych musi zgadzać się liczba elementów oraz typy. Np.:

DECLARE
    imie    varchar(100);
    wiek    integer;
BEGIN
    SELECT osoba_imie, osoba_wiek INTO imie, wiek
      FROM osoby WHERE osoba_id = id;
END;

Jeśli jest tylko jedna kolumna można używać instrukcji przypisania:

    wiek := osoba_wiek FROM osoby WHERE osoba_id = id;

Przy wczytywaniu rekordu lub wiersza używana jest składnia SELECT * INTO zmienna FROM ..., np.:

DECLARE
    osoba osoby%ROWTYPE;
BEGIN
    SELECT * INTO osoba 
      FROM osoby WHERE osoba_id = id;
END;

Jeśli zapytanie zwróci więcej niż jeden wiersz, zgłaszany jest wyjątek TOO_MANY_ROWS, jeśli natomiast nie zwróci wyników, zmienne są ustawiane na NULL.

Dodanie słowa kluczowego STRICT powoduje, że także w przypadku pustego wyniku zostanie zgłoszony wyjątek NO_DATA_FOUND. Innymi słowy STRICT wymusza zwrócenie dokładnie jednego wiersza.

Wczytywanie danych z kursorów[edytuj]

Z otwartego kursora można wczytać aktualny wiersz instrukcją:

FETCH [ przemieszczenie ] { FROM  | IN } nazwa_kursora INTO lista zmiennych

Np.

DECLARE
    kursor  REFCURSOR;
    ocena1  numeric;
    ocena2  numeric;

    napis1  text;
    napis2  text;
BEGIN
    OPEN kursor FOR SELECT ocena FROM studenci ORDER BY nazwisko, imie;
    -- wczytanie z pierwszego i ostatniego wiersza pojedynczej kolumny
    FETCH FIRST FROM kursor INTO ocena1;
    FETCH LAST FROM kursor INTO ocena2;

    CLOSE kursor;

    OPEN kursor FOR SELECT imie, nazwisko FROM studenci ORDER BY nazwisko;
    -- wczytanie aktualnego wiersza
    MOVE NEXT FROM kursor;
    FETCH FROM kursor INTO napis1, napis2;

    CLOSE kursor;
END;

Wczytywanie danych po zmianie wiersza[edytuj]

Od wersji 8.4 rozszerzono składnię SQL-owych instrukcji UPDATE, INSERT oraz DELETE o klauzulę

RETURNING lista kolumn INTO [ STRICT ] lista zmiennych

która wykonuje na aktualizowanym/wstawianym/kasowanym wierszu SELECT ... INTO. Np.:

DECLARE
	wiek	integer;
BEGIN
	INSERT INTO osoby (
		osoba_id,
		osoba_imie,
		osoba_nazwisko,
		osoba_wiek
	) VALUES (
		1,
		'Jan',
		'Kowalski',
		45
	)
	RETURNING osoba_wiek
	     INTO wiek;
END;

Co odpowiada mniej więcej:

DECLARE
	wiek	integer;
BEGIN
	INSERT INTO osoby (
		osoba_id,
		osoba_imie,
		osoba_nazwisko,
		osoba_wiek
	) VALUES (
		1,
		'Jan',
		'Kowalski',
		45
	);

	SELECT osoba_wiek INTO wiek
	  FROM osoby WHERE osoba_id = 1;
END;

Instrukcje warunkowe - IF[edytuj]

Instrukcja warunkowa może być używana w kilku wariantach:

-- 1
IF warunek THEN
    instrukcje
END IF;


-- 2
IF warunek THEN
    instrukcje
ELSE
    instrukcje
END IF;


-- 3
IF warunek THEN
    instrukcje
ELSIF warunek2 THEN
    instrukcje
ELSE
    instrukcje
END IF;

Instrukcja wyboru - CASE[edytuj]

Instrukcja CASE występuje w dwóch wariantach. W pierwszym, wyboru, działa w sposób znany z innych języków - dla podanego wyrażenia wykonuje część etykietowaną wartością wyrażenia.

W drugim działa w uproszczeniu jak ciąg instrukcji IF ... ELSIF ... ELSE, tzn. oblicza wartości kolejnych warunków logicznych i jeśli któryś okaże się prawdziwy, wykonuje powiązane z nim instrukcje.

W obu wariantach, jeśli nie uda się niczego dopasować, wykonywane są instrukcje po opcjonalnej części ELSE. Jeśli ELSE nie występuje, podnoszony jest wyjątek CASE_NOT_FOUND.

Wariant 1[edytuj]

Informacja
Wartości etykiet nie muszą być stałe, mogą to być dowolne wyrażenia, w tym zmienne i argumenty funkcji.

Składnia:

CASE wartość
    WHEN etykieta1 [, etykieta2 [, ...] ] THEN
        instrukcje
    
    WHEN etykieta1 [, etykieta2 [, ...] ] THEN
        instrukcje
    ...    

    ELSE
        instrukcje
    ...
END CASE;

Przykład:

CASE liczba
    WHEN 1, 3, 5, 7, 9 THEN
        komunikat := 'liczba nieparzysta';
    WHEN 2, 4, 6, 8 THEN
        komunikat := 'liczba parzysta';
    ELSE
        komunikat := 'liczba spoza zakresu 1..9';
END CASE;

Wariant 2[edytuj]

Składnia:

CASE 
    WHEN wyrażenie THEN
        instrukcje
    
    WHEN wyrażenie THEN
        instrukcje
    ...

    ELSE
        instrukcje
    ...
END CASE;

Przykład:

CASE 
    WHEN liczba % 3 = 0 THEN
        komunikat := 'liczba podzielna przez 3';
    WHEN liczba % 2 = 1 THEN
        komunikat := 'liczba nieparzysta';
    ELSE
        komunikat := 'liczba parzysta';
END CASE;