Procedury składowane w PostgreSQL/Język PLpgSQL/Deklaracja zmiennych

Z Wikibooks, biblioteki wolnych podręczników.

Deklaracja zmiennej ma składnię:

nazwa [ CONSTANT ] typ [NOT NULL] [ { DEFAULT | := } wartość domyślna ];

Nazwa nie może zaczynać się cyfrą i musi składać się z dużych i małych liter łacińskich, cyfr i znaku podkreślenia.

Jeśli nie zostanie podana wartość domyślna, wartość zmiennej jest inicjowana na NULL.

Jeśli zmienna zostanie zadeklarowana jako NOT NULL musi mieć wartość domyślną. Jednocześnie przypisanie wartości NULL tej zmiennej w ciele procedury skutkować będzie błędem czasu wykonania.

Jeśli zostanie użyte słowo kluczowe CONSTANT, nazwa reprezentuje wartość stałą i musi zostać zainicjowana.

Przykład[edytuj]

CREATE OR REPLACE FUNCTION deklaracje(a integer) RETURNS void AS $$
	DECLARE
		x	integer DEFAULT 1;	-- wartość początkowa
		y	integer := 5;		-- wartość początkowa
		z	integer := a;		-- wartość początkowa z argumentu

		w	integer NOT NULL := a;
		k	CONSTANT integer := 9;

	BEGIN
		w := NULL;	-- błąd czasu wykonywania! 'w' nie może być NULL
		k := 8;		-- błąd kompilacji! 'k' oznaczone jako wartość stała
	END;
$$ LANGUAGE 'plpgsql';

Kopiowanie typów[edytuj]

Najprostszym sposobem podania typu zmiennej jest podanie jego pełnej nazwy:

k         integer;   -- zmienna x typu całkowitego
predkosc  real;      -- zmienna predkosc typu rzeczywistego

Czasem o wiele wygodniej użyć takiego typu, jak wcześniej zdefiniowany obiekt, szczególnie w procedurach generycznych:

  • tabela,
  • kolumna tabeli,
  • wcześniej zadeklarowana zmienna.

Służą do tego operatory %TYPE dla typów skalarnych i zmiennych oraz %ROWTYPE dla relacji. UWAGA! Nie można zadeklarować tablicy z użyciem operatora %TYPE.

CREATE TABLE pracownicy (imie text, nazwisko text, wiek integer);

CREATE OR REPLACE FUNCTION funkcja(wspolczynnik real) RETURNS void AS $$
    DECLARE
        napis pracownicy.imie%TYPE; -- typ text
        w     wspolczynnik%TYPE;    -- typ real
        r1    pracownicy;           -- typ pracownicy
        r2    pracownicy%ROWTYPE;   -- typ pracownicy
        r3    w%TYPE;               -- typ real
    BEGIN
        RAISE NOTICE 'typ zmiennej: napis=%, w=%, r1=%, r2=%, r3=%',
            pg_typeof(napis),
            pg_typeof(w),
            pg_typeof(r1),
            pg_typeof(r2),
            pg_typeof(r3)
        ;
    END;
$$ LANGUAGE 'plpgsql';

SELECT funkcja(0.5);

Zakres widoczności[edytuj]

W blokach zagnieżdżonych widoczne są zmienne z bloków nadrzędnych, natomiast w przypadku powtórzenia nazwy są przesłaniane.

Możliwy jest dostęp do zmiennych z bloków zewnętrznych przez ich etykiety, tzn. podanie pełnej nazwy etykieta.nazwa_zmiennej. W identyczny sposób można odwoływać się do zmiennych z etykietowanych pętli iterujących po liczbach.

Przykład 1[edytuj]

CREATE OR REPLACE FUNCTION zakresy() RETURNS void AS $$
    <<blok>>
    DECLARE
        tekst   text := 'tekst';
        liczba  integer := 123;
    BEGIN
        RAISE NOTICE 'tekst=%, liczba=%', tekst, liczba;
    
        <<blok_zagniezdzony>>
        DECLARE
            tekst   text := 'zagnieżdżony'; -- przesłanienie
            liczba2 integer := liczba;      -- inicjalizacja zmienną
        BEGIN
            RAISE NOTICE 'blok.tekst=%, tekst=%, liczba=%, liczba2=%',
                          blok.tekst, tekst, liczba, liczba2;
        END;

        RAISE NOTICE 'tekst=%, liczba=%', tekst, liczba;
    END
$$ LANGUAGE 'plpgsql';
$ SELECT zakresy();
NOTICE:  tekst=tekst, liczba=123
NOTICE:  blok.tekst=tekst, tekst=zagnieżdżony, liczba=123, liczba2=123
NOTICE:  tekst=tekst, liczba=123

Przykład 2 - pętla FOR[edytuj]

CREATE OR REPLACE FUNCTION forfor() RETURNS VOID AS $$
	BEGIN
        <<petla_1>>
        FOR i IN 1 .. 5 LOOP
            <<petla_2>>
            FOR i IN 6 .. 7 LOOP
                RAISE NOTICE 'i=%, i=%', petla_1.i, petla_2.i;
            END LOOP;
        END LOOP;
	END;
$$ LANGUAGE 'plpgsql';
$ SELECT forfor();
NOTICE:  i=1, i=6
NOTICE:  i=1, i=7
NOTICE:  i=2, i=6
NOTICE:  i=2, i=7
NOTICE:  i=3, i=6
NOTICE:  i=3, i=7
NOTICE:  i=4, i=6
NOTICE:  i=4, i=7
NOTICE:  i=5, i=6
NOTICE:  i=5, i=7

Aliasy[edytuj]

W bloku deklaracji można również tworzyć aliasy, alternatywne nazwy dla zadeklarowanych zmiennych i argumentów funkcji oraz innych aliasów.

Przede wszystkim może to mieć zastosowanie do nazywania nienazwanych argumentów (we wcześniejszych wersjach PostgreSQL było to konieczne, ponieważ nazwanych argumentów nie było), jak również do wprowadzania krótszych nazw.

Nie można utworzyć aliasu do wyrażeń, np. do konkretnego elementu tablicy.

Składnia:

nowa_nazwa ALIAS FOR istniejaca_nazwa;

Przykład[edytuj]

CREATE OR REPLACE FUNCTION test(text, integer) RETURNS void AS $$
    DECLARE
        napis1  text := 'zmienna';

        napis2  ALIAS FOR $1;       -- parametr
        liczba  ALIAS FOR $2;       -- parametr

        napis3  ALIAS FOR napis1;   -- zmienna
        napis4  ALIAS FOR napis2;   -- inny alias

    BEGIN
        NULL;
    END;
$$ LANGUAGE 'plpgsql';

Kursory[edytuj]

Składnia deklaracji kursora:

nazwa	REFCURSOR;
nazwa	CURSOR [ ( argumenty ) ] FOR zapytanie;

Kursory są zawsze typu REFCURSOR jednak w zależności od deklaracji, mogą nieograniczone (ang. unbounded), tj. takie, dla których zapytanie zostanie określone dopiero podczas otwieranie kursora, oraz ograniczone (ang. bounded) z zapytaniem podanym w deklaracji.

Jedynie kursorów ograniczonych można używać w pętlach FOR.

Przykłady[edytuj]

DECLARE
    kursor1 REFCURSOR;
    kursor2 CURSOR FOR SELECT kolumna FROM tabela;
    kursor3 CURSOR(id integer) FOR SELECT kolumna FROM tabela WHERE tabela.id = id;
BEGIN
    ...