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ěsí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
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
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