PL/SQL v příkladech / Package
Stručný seriál, který krok po kroku představí konstrukce jazyka PL/SQL společnosti Oracle na jednoduchých příkladech. Předpokládá znalost základních principů procedurálního programování.

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

Ondřej Kubáč
Květen 3rd, 2016 at 12:18 pm

Pekny clanek, co bude dalsi ?

Květen 3rd, 2016 at 3:11 pm

Výjimky a záchytné body.

ZANECHTE KOMENTÁŘ


Velké díky pro teslathemes