Příkazy cyklu

Z PostgreSQL
Přejít na: navigace, hledání

Příkaz LOOP

Cyklus LOOP ... END LOOP je nejjednodušší příkazem cyklu. Sám o sobě představuje nekonečný cyklus a k jeho opuštění je nutné použít příkaz LEAVE. Příkaz LEAVE si vynucuje návěstí, tudíž pokud nepředpokládáme, že cyklus opustíme příkazy RETURN nebo SIGNAL musí mít příkaz LOOP vždy návěstí.

Syntaxe

  [navesti ':' ]
  LOOP
    (seznam sql/psm prikazu)
  END LOOP [navesti]

Příkaz WHILE

Cyklus WHILE..END WHILE zajistí opakované provádění bloku SQL příkazů v případě, že zadaný výraz je pravdivý. V případě, že výraz je neplatný již při zahájení příkazu, tělo cyklu se neprovede ani jednou. Ukázka obsahuje výpočet funkce faktoriál.

CREATE OR REPLACE FUNCTION factorial(n int)
RETURNS int8 AS
$$
  BEGIN
    DECLARE f int8 DEFAULT 1;
    DECLARE counter integer = n;
    factorial_loop:
    WHILE counter > 1 DO
      SET f = f * counter;
      SET counter = counter - 1;
    END WHILE;
    RETURN f;
  END;
$$

Syntaxe

  [navesti ':']
  WHILE podminka DO
    (seznam SQL/PSM prikazu)
  END WHILE [navesti]

Příkaz REPEAT

Příkaz REPEAT UNTIL END REPEAT zajistí minimálně jednou vyhodnocení těla cyklu. Cyklus se opouští tehdy, pokud je podmínka splněna. Uvnitř těla cyklu lze použít příkazy LEAVE a ITERATE. Při nevhodném použití příkazu ITERATE hrozí nekonečný cyklus, neboť se obchází testování podmínky. Následující příkaz vypíše obsah tabulky.

CREATE OR REPLACE FUNCTION rt()
RETURNS void AS
$$
  BEGIN
    DECLARE a, b integer;
    DECLARE sqlstate char(5);
    DECLARE c CURSOR FOR SELECT * FROM Foo;
    OPEN c;
    REPEAT
      FETCH c INTO a, b;
      IF sqlstate = '00000' THEN
        PRINT a, b;
      END IF;
    UNTIL sqlstate <> '00000' END REPEAT;
  END;
$$ LANGUAGE plpgsql;

Syntaxe

  [navesti ':']
  REPEAT
    (seznam SQL/PSM prikazu)
  UNTIL logicky vyraz END REPEAT [navesti]

Příkaz FOR

Jednou z předchozích ukázek byla iterace napříč výsledkem dotazu pomocí explicitně deklarovaného kurzoru. Nejedná se o nijak komplikovaný vzor. Musíme být pouze opatrní při vnořené iteraci několika kurzory. Tuto činnost lze ještě zjednodušit použitím příkazu FOR. Tento příkaz zajistí vytvoření kurzoru, jeho otevření, deklaraci potřebných lokálních proměnných (s viditelností omezenou příkazem FOR) odpovídajících sloupcům kurzoru i opakované plnění těchto proměnných příkazem FETCH.

Syntaxe

  [navesti ':' ]
  FOR [ jmennny prostor AS ]
      [ nazev kurzoru  CURSOR FOR ]  SQL dotaz
  DO  
    (seznam sql/psm prikazu)
  END FOR [ navesti ]

Příkaz FOR detekuje názvy a typy atributu v SQL dotazu a vytvoří odpovídající proměnné (se stejným názvem a typem) v zadaném jmenném prostoru. Tyto proměnné jsou v každé iteraci příkazu naplněny aktuální hodnotou kurzoru. Pokud neuvedeme název kurzoru, použije se nepojmenovaný kurzor. Pokud je název zadaný, vytvoří se pojmenovaný kurzor s zadaným názvem. Pojmenovat kurzor má smysl pouze v tom případě, že v těle příkazu FOR použijeme příkaz DELETE WHERE CURRENT OF název kurzoru nebo UPDATE WHERE CURRENT OF název kurzoru. To ale předpokládá, PostgreSQL zatím nepodporované, aktualizovatelné kurzory. Stejně jako ve všech ostatních příkazech opakování (cyklů) lze provádění příkazu přerušit překazem LEAVE nebo přejít na další řádek kurzoru příkazem ITERATE. K tomu ale musí mít příkaz FOR určeno návěstí.

V příkladu je příkaz FOR použitý k zobrazení vzestupné řady sudých čísel v intervalu 0..20:

CREATE OR REPLACE FUNCTION foo()
RETURNS void AS
$$ 
  FOR ns AS 
      SELECT g.i FROM generate_series(0, 10) g(i)
  DO
    PRINT ns.i * 2;
  END FOR;
$$ LANGUAGE plpgpsm;

Příkazy LEAVE a ITERATE

Všechny podporované příkazy cyklu můžeme přerušit příkazem LEAVE. Příkazem ITERATE zahájíme novou iteraci cyklu. Tyto dva příkazy mají povinné návěstí, tudíž cykly na které se váží, musí mít přiřazeno návěstí také. Tím je naprosto jednoznačně určeno, který cyklus skončí nebo kde se zahájí další iterace.

Syntaxe

LEAVE navesti
ITERATE navesti