PL/SQL v příkladech / Záchytné body
Záchytné body jsou mechanismem uvnitř PL/SQL bloku, který umožňuje rozdělit prováděnou transakci na dílčí celky, neboli milníky. K těmto milníkům se poté lze jednoduše vrátit, aniž bychom přišli o celou transakci.
Nejdříve si zadefinujme pomocnou metodu, která vrátí plat konkrétního zaměstnance.
CREATE OR REPLACE FUNCTION sf_VratPlat(
p_Zamestnanec_ID NUMBER
) RETURN NUMBER
IS
l_Plat NUMBER;
BEGIN
SELECT salary
INTO l_Plat
FROM employees
WHERE employee_id=p_Zamestnanec_ID
;
RETURN l_Plat;
END;
/
A ještě jednu, která plat aktualizuje.
CREATE OR REPLACE PROCEDURE sp_NastavPlat(
p_Zamestnanec_ID NUMBER
, p_Plat NUMBER
)
IS
BEGIN
UPDATE employees
SET salary=p_Plat
WHERE (employee_id=p_Zamestnanec_ID)
;
END;
/
V prvním kroku nastavíme počáteční plat na 24000, čímž započne transakce. O tuto hodnotu nechceme přijít, ať už se dále v kódu děje cokoliv. Vytvoříme tedy bod obnovy a pojmenujeme ho vnejsi_savepoint
Druhý krok opět nastaví plat, tentokrát na 25500.
Pro ilustraci následuje anonymní blok, který si před prováděním změn vytvoří „svůj vlastní“ milník s názvem vnitrni_savepoint, nastaví plat na 26000 a vyvolá výjimku. Ta je odchycena a zároveň se provede částečné vrácení změň do stavu před začátkem anonymního bloku.
V poslední fázi se opět vyvolá výjimka a vrácení k záchytnému bodu, což anuluje i aktualizaci platu z druhého kroku.
DECLARE
L_ZAMESTNANEC_ID CONSTANT NUMBER:=100; -- testovací zaměstnanec
VYJIMKA EXCEPTION;
BEGIN
sp_NastavPlat(L_ZAMESTNANEC_ID, 24000);
dbms_output.put_line(sf_VratPlat(L_ZAMESTNANEC_ID)); -- 24000
SAVEPOINT vnejsi_savepoint;
sp_NastavPlat(L_ZAMESTNANEC_ID, 25500);
dbms_output.put_line(sf_VratPlat(L_ZAMESTNANEC_ID)); -- 25500
/* ZAČÁTEK VNITŘNÍHO BLOKU */
BEGIN
SAVEPOINT vnitrni_savepoint;
sp_NastavPlat(L_ZAMESTNANEC_ID, 26000);
dbms_output.put_line(sf_VratPlat(L_ZAMESTNANEC_ID)); -- 26000
RAISE VYJIMKA;
EXCEPTION
WHEN VYJIMKA THEN
ROLLBACK TO SAVEPOINT vnitrni_savepoint;
END;
/* KONEC VNITŘNÍHO BLOKU */
dbms_output.put_line(sf_VratPlat(L_ZAMESTNANEC_ID)); -- 25500
RAISE VYJIMKA;
EXCEPTION
WHEN VYJIMKA THEN
ROLLBACK TO SAVEPOINT vnejsi_savepoint;
dbms_output.put_line(sf_VratPlat(L_ZAMESTNANEC_ID)); -- 24000
END;