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.