PL/SQL v příkladech / Package
V minulých dílech byla většina příkladů demonstrována na úrovni jednoho anonymního PL/SQL bloku. V praxi je ale vhodnější funkcionalitu sjednocovat do logických celků, takzvaných balíků. Výhodou je nejen seskupení souvisejících objektů a tudíž přehlednější a čitelnější kód, ale také vyšší výkon (package je držena v paměti po celou dobu trvání relace), jednodušší administrace přístupových práv a možnost odstínění interní logiky před ostatními objekty v databázi.
Package se skládá ze dvou částí. Povinnou je specifikace (někdy též „hlavička“) obsahující pouze výčet a předpis objektů, nepovinnou tělo, které objekty a jejich funkci dále popisuje. Platí pravidlo, že co je deklarováno v hlavičce, je veřejně viditelné, naopak co je deklarované pouze v těle balíku, je privátní.
CREATE OR REPLACE PACKAGE MujBalik AS -- veřejná deklarativní část g_Verejna NUMBER:=10; END; /
CREATE OR REPLACE PACKAGE BODY MujBalik AS -- privátní deklarativní část g_Privatni NUMBER:=20; G_KONSTANTA CONSTANT NUMBER:=30; END; /
BEGIN dbms_output.put_line(MujBalik.g_Verejna); -- 10 MujBalik.g_Verejna:=30; dbms_output.put_line(MujBalik.g_Verejna); -- 30 -- NELZE MujBalik.g_Privatni:=40; -- NELZE dbms_output.put_line(MujBalik.g_Privatni); END;
Do package je možné zabalit nejen proměnné a konstanty, ale také typy, procedury, funkce, kurzory a uživatelské výjimky.
CREATE OR REPLACE PACKAGE MujBalik
AS
-- veřejný typ
TYPE Varchar_TT IS TABLE OF VARCHAR2(4000) INDEX BY PLS_INTEGER;
-- specifikace veřejné funkce
FUNCTION mf_PoleNaRetezec(
pt_Pole MujBalik.Varchar_TT
, p_Oddelovac CHAR:=', '
) RETURN VARCHAR2;
END;
/
CREATE OR REPLACE PACKAGE BODY MujBalik
AS
-- tělo veřejné funkce
FUNCTION mf_PoleNaRetezec(
pt_Pole MujBalik.Varchar_TT
, p_Oddelovac CHAR:=', '
) RETURN VARCHAR2
IS
l_Vysledek VARCHAR2(4000);
BEGIN
FOR i IN 1..pt_Pole.COUNT LOOP
l_Vysledek:=l_Vysledek||p_Oddelovac||pt_Pole(i);
END LOOP;
RETURN LTRIM(l_Vysledek, p_Oddelovac);
END;
END;
/
DECLARE lt_Pole MujBalik.Varchar_TT; BEGIN lt_Pole(1):='jedna'; lt_Pole(2):='dva'; dbms_output.put_line(MujBalik.mf_PoleNaRetezec(lt_Pole)); -- jedna, dva END;
Pokud se vevnitř balíku odkazujeme na interní metodu, je důležité, aby její zápis stál fyzicky nad zápisem metody, ze které voláme. Rozdíl ve specifikaci a použití veřejné versus interní metody je znázorněn v následujícím příkladu.
CREATE OR REPLACE PACKAGE MujBalik
AS
-- specifikace veřejné bezparametrické funkce
FUNCTION mf_VratPrivatni
RETURN NUMBER;
-- specifikace veřejné bezparametrické procedury
PROCEDURE mp_NastavPrivatniNaSto;
END;
/
CREATE OR REPLACE PACKAGE BODY MujBalik
AS
-- privátní proměnná
g_Privatni NUMBER;
-- privátní procedura
PROCEDURE mpi_NastavPrivatni(
p_Parametr NUMBER
)
IS
BEGIN
g_Privatni:=p_Parametr;
END;
-- tělo veřejné bezparametrické funkce
FUNCTION mf_VratPrivatni
RETURN NUMBER
IS
BEGIN
RETURN g_Privatni;
END;
-- tělo veřejné bezparametrické procedury
PROCEDURE mp_NastavPrivatniNaSto
IS
BEGIN
-- volání privátní procedury
mpi_NastavPrivatni(100);
END;
END;
/
BEGIN -- NELZE MujBalik.mpi_NastavPrivatni(100); MujBalik.mp_NastavPrivatniNaSto; dbms_output.put_line(MujBalik.mf_VratPrivatni); -- 100 END;
Stejně jako uložené funkce z předchozí kapitoly, tak i funkce v packagi je možné využívat v SQL dotazech.
SELECT MujBalik.mf_VratPrivatni FROM dual ; -- 100
Pekny clanek, co bude dalsi ?
Výjimky a záchytné body.