PL/SQL v příkladech / Skalární datové typy

Datové typy v PL/SQL dělíme na tři základní kategorie, a to na skalární, kompozitní a referenční. Do skalárních můžeme uložit typicky jen jednu hodnotu, kompozitní pojmou pole hodnot, případně jde o složitější struktury jako rekord nebo objekt. Referenční datový typ slouží jako ukazatel.

Boolean a číslo

Předchozí díl kromě struktury a řízení kódu zjednodušeně představil dva základní datové typy – číslo a logický datový typ. Následující příklad ukazuje dvě, resp. tři metody přiřazení hodnoty do proměnné. Výchozí inicializaci v deklarativní části, přiřazení ve výkonové části a přiřazení pomocí SQL dotazu za použití klíčového slova INTO.

DECLARE
  l_Bool BOOLEAN; -- logický datový typ, nelze použít v SQL
  l_Cislo NUMBER:=100; -- typ číslo
BEGIN
  l_Cislo:=200;
  SELECT 300
    INTO l_Cislo
    FROM dual -- pomocná systémová tabulka
  ;
  IF (l_Bool IS NULL) THEN -- výchozí hodnota proměnné je vždy NULL
    dbms_output.put_line(l_Cislo); -- 300
  END IF;
END;

Datový typ NUMBER dokáže uchovat jak celočíselné hodnoty, tak i hodnoty s pohyblivou desetinnou čárkou. Přesnost (celkový počet cifer) a měřítko (počet cifer za desetinnou čárkou) můžeme specifikovat ručně. Pokud tak neučiníme, použije se maximální přesnost a měřítko. V PL/SQL můžeme pracovat také s různými číselnými pseudotypy, jako například INT, který se interně mapuje na NUMBER(38,0). Kvůli co největšímu zjednodušení budu dále používat jen NUMBER, více informací o číselných datových typech najdete v dokumentaci.

Znak a řetězec

Pro práci s řetězci předem stanovené délky slouží typ CHAR, pro řetězce proměnné délky VARCHAR2. Maximální velikost závisí na nastavení a zvolené znakové sadě a opět lze dohledat v dokumentaci. Obecně ale platí, že pro velmi dlouhý text je vhodnější použití datového typu CLOB („Character Large OBject“). Skládání řetězců a základní funkce pro práci s nimi popisuje následující příklad.

DECLARE
  l_Znak CHAR(1):='A'; -- pevně daná velikost
  l_Retezec VARCHAR2(4000):='slovo'; -- maximální velikost
BEGIN
  -- skládání řetězců pomocí dvou pajp
  dbms_output.put_line(l_Retezec||' '||l_Znak); -- slovo A
  -- vyříznutí
  dbms_output.put_line(SUBSTR(l_Retezec, 1, 3)); -- slo
  -- pozice v řetězci
  dbms_output.put_line(INSTR(l_Retezec, 'ov')); -- 3
  -- nahrazení
  dbms_output.put_line(REPLACE(l_Retezec, 'o', 'O')); -- slOvO
END;

Datum

Pro uchování data používá Oracle typ DATE, který obsahuje rok, měsíc, den, hodinu, minutu a vteřinu. Přiřazení probíhá pomocí funkce TO_DATE(), konverze do lidsky čitelného řetězce funkcí TO_CHAR(). Obě funkce přijímají jako druhý parametr formát.

DECLARE
  l_Datum DATE;
  l_Retezec VARCHAR2(20);
BEGIN
  l_Datum:=TO_DATE('1.1.2016', 'DD.MM.YYYY'); -- přiřazení
  -- implicitní konverze dle nastavení databáze
  l_Retezec:=l_Datum;
  dbms_output.put_line(l_Retezec); -- 01.01.16
  -- explicitní konverze pomocí formátu
  l_Retezec:=TO_CHAR(l_Datum, 'DD.MM.YYYY');
  dbms_output.put_line(l_Retezec); -- 01.01.2016
  -- načtení a konverze aktuálního data
  l_Retezec:=TO_CHAR(SYSDATE, 'HH24:MI:SS DD.MON.YY');
  dbms_output.put_line(l_Retezec); -- 17:30:12 21.BŘE.16
  -- načtení a konverze na název dne v týdnu
  l_Retezec:=TO_CHAR(SYSDATE, 'DAY');
  dbms_output.put_line(l_Retezec); -- PONDĚLÍ
  -- přepsání jazykového nastaveni databáze
  l_Retezec:=TO_CHAR(SYSDATE, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH');
  dbms_output.put_line(l_Retezec); -- MON
END;

Základní práci s datem jako přičtení hodiny, dne nebo měsíce shrnuje následující příklad.

DECLARE
  l_Datum DATE:=TO_DATE('01.01.2016', 'DD.MM.YYYY');
BEGIN
  -- přičtení dne
  dbms_output.put_line(l_Datum+1); -- 02.01.16
  -- přičtení hodiny
  dbms_output.put_line(TO_CHAR(l_Datum+1/24, 'HH24:MI')); -- 01:00
  -- přičtení měcíce
  dbms_output.put_line(ADD_MONTHS(l_Datum, 1)); -- 01.02.16
  -- odečtení roku
  dbms_output.put_line(ADD_MONTHS(l_Datum, -12)); -- 01.01.15
  -- poslední den v měsíci
  dbms_output.put_line(LAST_DAY(l_Datum)); -- 31.01.16
  -- zaokrouhlený rozdíl měsíců
  dbms_output.put_line(ROUND(MONTHS_BETWEEN(l_Datum+80, l_Datum))); -- 3
END;

%TYPE

V případě, že si nejsme datovým typem jisti nebo se bude v průběhu času měnit, můžeme zvolit deklaraci podle jiné proměnné nebo sloupce v tabulce.

DECLARE
  l_Cislo NUMBER;
  l_Employee_ID l_Cislo%TYPE; -- NUMBER
  l_FirstName employees.first_name%TYPE; -- VARCHAR2(20)
BEGIN
  l_Employee_ID:=100;
  l_FirstName:='Steven';
  dbms_output.put_line(l_Employee_ID||' '||l_FirstName); -- 100 Steven
END;

Konstanta a klauzule NOT NULL

Jazyk PL/SQL podporuje také konstanty, které není možné v těle bloku přepsat jinou hodnotou. Velmi užitečná je také NOT NULL klauzule kontrolující, zda-li je daná proměnná incializovaná.

DECLARE
  L_CISLO CONSTANT NUMBER:=100; -- konstanta
  l_Bool BOOLEAN NOT NULL:=FALSE; -- neNULLový typ
BEGIN
  -- NELZE L_CISLO:=200;
  -- NELZE l_Bool:=NULL;
  IF (NOT l_Bool) THEN
    dbms_output.put_line(L_CISLO); -- 100
  END IF;
END;

Maximální velikost základních datových typů

Datový typ Velikost v SQL Velikost v PL/SQL
NUMBER ± 999…(38 „devítek“) ± 999…(38 „devítek“)
CHAR 2000 bajtů * 32767 bajtů *
VARCHAR2 4000 bajtů * 32767 bajtů *
CLOB 8 TB až 128 TB ** 128 TB

* pozor na to, že různé znaky mají v UTF-8 různou velikost

** závisí na nastavení velikosti databázového bloku

Jeden komentář

  1. Zdravím Matěji, ráda bych poděkovala za super stránky, krásně mi pomáhají zorientovat se v PL/SQL kódu a myslím, že jistě nebudu jediná, které pomůžou.

    Pak bych jen upozornila na malinkou nepřesnost

    -- pozice v řetězci
    dbms_output.put_line(INSTR(l_Retezec, 'ov')); -- 2
    

    Výsledek je, pokud se nemýlím, 3 a ne 2. Trochu mě to zmátlo, protože 2 by byl výsledek, pokud by se počítalo od nuly, ale jak je zřejmé z předchozí ukázky, tak první znak = 1.

    Pokud se pletu, tak se omlouvám.

    Přeji hezký den

    Bára

Zanechte komentář

Vaše emailová adresa nebude zobrazena. Povinná pole jsou označena *