Jazyk PL/SQL
Dokumentace PL/SQL Oracle
PL/SQL prirucka

1) Jazyk PL/SQL

PL/SQL je proceduralni jazyk (cykly, podminky, funkce, procedury).
Zakladem je blok (nepojmenovany - anonymni, funkce, procedura).
Bloky mohou byt vnorene. Struktura bloku:


[DECLARE 
-- declarations
...
] 
BEGIN 
-- statements 
...
[EXCEPTION
 -- handlers
 ...]
END;

Cast deklarace promennych a osetreni vyjimek je nepovinna.

2) Cast deklarace
Promenne a konstanty musi byt deklarovany drive, nez jsou pouzity.
Promenne a konstanty mohou mit libovolny SQL nebo PL/SQL datovy typ.

Napr. 
jmeno VARCHAR2(20); ucitel BOOLEAN;

Konstanty maji uvedeno klicove slovo CONSTANT a okamzite prirazenu
hodnotu:
pi CONSTANT real := 3.1415;

Vsechny deklarovane promenne jsou automaticky inicializovany hodnotou NULL, pokud neni uvedena jina hodnota.

Promenna muze byt naplnena 3 zpusoby:
a) prirazovaci prikaz

cena := pocet_hodin * sazba; ucitel := TRUE;

b) klausule INTO prikazu select

SELECT 1+1 INTO cena FROM dual; 
SELECT uco INTO cislo_osoby FROM lide WHERE rc=8254074667;

c) vystupnim parametrem (OUT nebo IN OUT) procedury

zvys_plat(plat,100);


Atributy (pro zadavani datovych typu)

Mame tabulku kniha a ta ma atribut nazev. Aniz bychom znali (nebo
chteli presne specifikovat) datovy typ tohoto atributu, muzeme
vytvorit promennou
se stejnym datovym typem pomoci %TYPE.

nazev_knihy kniha.nazev%TYPE

Obdobne muzeme vytvorit promennou typu zaznam se vsemi atributy
urcite tabulky
(budeme do mi moci vlozit prave jeden radek tabulky). Slouzi k tomu %ROWTYPE.
(funguje to i na kursory, ale o tom az priste).

Napr.: Mejme tabulku lide s atributy jmeno, uco, rc:

clovek lide%ROWTYPE

Jednotlive polozky pak zpristupnime pomoci "."

INSERT INTO seznam VALUES (clovek.uco);

3) Cast prikazu
a) podminky IF-THEN-ELSE

IF kredit >= 80 THEN
 insert into log values('Pripojeni GPRS povoleno',SYSDATE);
 povolit := TRUE;
ELSE
 insert into log values('Prilis nizky kredit pro pripojeni GPRS',SYSDATE);
 povolit := FALSE;
END IF;

b) vicenasobne vetveni

  CASE
    WHEN jobid = 'PU_CLERK' THEN
        IF sal < 3000 THEN
		  sal_raise := .12;
        ELSE
		  sal_raise := .09;
        END IF;
    WHEN jobid = 'SH_CLERK' THEN
        IF sal < 4000 THEN
		  sal_raise := .11;
        ELSE
		  sal_raise := .08;
        END IF;
    WHEN jobid = 'ST_CLERK' THEN
        IF sal < 3500 THEN
		  sal_raise := .10;
        ELSE
		  sal_raise := .07;
        END IF;
    ELSE
     BEGIN
       DBMS_OUTPUT.PUT_LINE('No raise for this job: ' || jobid);
     END;
  END CASE;

Vystup pomoci DBMS_OUTPUT muze byt potlaceny. Pro zapnuti provedte prikaz:
SQL> SET SERVEROUTPUT ON

c) Nekonecny cyklus LOOP

i := 100; 
LOOP
  i:=i+2; 
  select salary into plat from employees where id=i; 
  celkem := celkem + plat; 
  EXIT WHEN j>1000; 
END LOOP;

d) Cyklus FOR-LOOP

FOR i IN 1..100 LOOP 
  INSERT INTO mocniny VALUES (i,i*i);
END LOOP;

e) Cyklus WHILE-LOOP

WHILE salary <= 2500 LOOP
  SELECT sal, mgr, ename INTO salary, mgr_num, last_name
         FROM emp WHERE empno = mgr_num;
END LOOP;

f) Nepodmineny skok GOTO label

IF vykonnost > 90 THEN
  GOTO zvys_plat; 
END IF;
-- Vytvoreni label pomoci:
<<zvys_plat>>
IF prac_napln = 'Prodejce' THEN 
  plat := plat * 1.2;
ELSE 
  plat := plat * 1.1;
END IF;


4) Funkce a procedury

[CREATE [OR REPLACE]] PROCEDURE jmeno_procedury (parametry) IS|AS
blok ... 

[CREATE [OR REPLACE]] FUNCTION jmeno_funkce (parametry) RETURN datovy_typ IS|AS
blok ...


kde parametry jsou tvaru: 
jmeno_parametru [IN|OUT [NOCOPY]|IN OUT [NOCOPY]] datovy_typ [ {:=|DEFAULT} vyraz]

IN - vstupni parametr (default) 
OUT - vystupni parametr 
IN OUT - vstupne/vystupni parametr

Defaultne se IN parametr predava referenci a OUT a IN OUT hodnotou.
Modifikator NOCOPY umozni parametry OUT a IN OUT predavat referenci.

DROP [PROCEDURE/FUNCTION] jmeno;


Pro zjisteni seznamu drive vytvorenych funkci/procedur lze pouzit:

SELECT object_name FROM user_procedures;

Kod jiz existujici procedury nebo funkce muzete vypsat z user_source:

SELECT text FROM user_source WHERE lower(name)='zvys_vyplatu' ORDER BY line;

Detaily o jednotlivych parametrech funkci lze zjistit z user_arguments.

Pro ziskani chyb po vytvoreni procedury/funkce s chybami pouzijte
prikaz show errors.

Priklady procedur a funkci najdete na http://www.psoug.org/reference/functions.html.


5) Vyjimky

Pri vyvolani vyjimky je preruseno provadeni programu a je spusteno osetreni
vyjimky. Existuje cela rada standardnich vyjimek (jako deleni nulou, chybejici
data, timeout), krome toho je mozne vytvaret a osetrovat uzivatelsky definovane
vyjimky.

EXCEPTION
WHEN vyjimka THEN 
...
WHEN VALUE_ERROR or ZERO_DIVIDE THEN
...
WHEN OTHERS THEN
...

Ne vsechny interni vyjimky jsou pojmenovane, proto
je muzeme osetrovat v casti OTHERS nebo pojmenovat a osetrit std. zpusobem:

PRAGMA EXCEPTION_INIT(exception_name, - Oracle_error_number);

Napr:

DECLARE
deadlock_detected EXCEPTION;
PRAGMA EXCEPTION_INIT(deadlock_detected, -60);
BEGIN
...
EXCEPTION
WHEN deadlock_detected THEN
 ...
END;


Pro manualni vyvolani vyjimky je prikaz RAISE vyjimka;

Pro znovu vyvolani aktualne zachycene vyjimky behem jejiho osetreni (v casti EXCEPTION WHEN ...) slouzi prikaz: RAISE;

Manualni spusteni vyjimky a predani chybove zpravy aplikaci:
raise_application_error(error_number, message[, {TRUE | FALSE}]);
Z dokumentace Oracle lze zjistit:
error_number - cislo mezi -20000 a -20999
message      - chybove hlaseni (az 2048 znaku dlouhe)
treti parametr - vyvolavana chyba je ulozena na zasobnik chyb (TRUE) nebo 
                 vyvolavana chyba nahradi obsah zasobniku (FALSE). Default hodnota je FALSE.