Sunteți pe pagina 1din 26

Tipuri de date n PL/SQL

Fiecare variabil sau constant utilizat ntr-un bloc PL/SQL este de un


anumit tip prin care se specific:
formatul su de stocare,
constrngerile care trebuie s le verifice
domeniul valorilor sale.
Variabilele folosite n Oracle9i pot fi:

specifice PL/SQL;

nespecifice PL/SQL.
Variabile specifice PL/SQL se clasific n variabile:

de tip scalar,
compuse,
referin,

LOB (large objects),

tipuri obiect.
Variabile nespecifice PL/SQL pot fi:
variabile de legtur (bind variables),
variabile gazd (host variables),
variabile indicator.

Variabile specifice PL/SQL


Tipurile de date scalare
Nu au componente interne (conin valori atomice). Se mpart n 5 clase.
Tipurile de date ce stocheaz valori numerice cuprind tipul NUMBER
cu subtipurile DEC, DECIMAL, DOUBLE PRECISION, FLOAT,
INTEGER,
INT,
NUMERIC,
REAL,
SMALLINT;
tipul
BINARY_INTEGER cu subtipurile NATURAL, NATURALN,
POSITIVE, POSITIVEN, SIGNTYPE; tipul PLS_INTEGER.
Tipurile de date ce stocheaz caractere cuprind tipul VARCHAR2 cu
subtipurile STRING, VARCHAR; tipul de date CHAR cu subtipul
CHARACTER; tipurile LONG, RAW, LONG RAW, ROWID.
Tipurile de date ce stocheaz data calendaristic i ora cuprind
tipurile DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE,
TIMESTAMP WITH LOCAL TIME ZONE, INTERVAL YEAR TO
MONTH, INTERVAL DAY TO SECOND.
Tipurile de date globalizare ce stocheaz date unicode includ tipurile
NCHAR i NVARCHAR2.
Tipul de date BOOLEAN stocheaz valori logice (true, false sau null).

Tipurile de date compuse


Au componente interne care pot fi manipulate individual. Oracle ofer
programatorului dou tipuri de date compuse:
nregistrare (RECORD);
colecie (INDEX-BY TABLE, NESTED TABLE, VARRAY).

Tipurile de date referin


REF CURSOR si REF obiect sunt tipuri de date ale cror valori, numite
pointeri, fac referin ctre obiecte din program. Pointerii conin locaia de
memorie (adresa) unui element i nu elementul n sine. Tipul REF CURSOR este
folosit pentru a face referin la un cursor explicit. Tipul REF obiect face
referin la adresa unui obiect.

Tipurile de date LOB


Large object sunt acele tipuri de date ale cror valori, numite locatori
(locators) specific localizarea unor obiecte de dimensiuni mari, adic blocuri

de date nestructurate, cum ar fi texte, imagini grafice, clipuri video i sunete.


Tipurile LOB sunt manipulate cu ajutorul pachetului DBMS_LOB.
Aceste tipuri sunt:

CLOB (character large object),

BLOB (binary large object),

BFILE (binary file),

NCLOB (national language character large object).

Tipurile obiect
Sunt tipuri compuse, definite de utilizator, care ncapsuleaz structuri de
date (atribute) mpreun cu subprograme pentru manipularea datelor (metode).
Dintre tipurile scalare PL/SQL, urmtoarele sunt i tipuri SQL (adic pot fi
folosite pentru coloanele tabelelor Oracle): NUMBER, VARCHAR2, CHAR,
LONG, RAW, LONG RAW, ROWID, NCHAR, NVARCHAR2, DATE. n unele
cazuri, tipurile de date PL/SQL difer de corespondentele lor SQL prin
dimensiunea maxim permis.
Tipul NUMBER memoreaz numerele n virgul fix i virgul mobil. El
are forma general NUMBER (m, n), unde m reprezint numrul total de cifre,
iar n numrul de zecimale. Valoarea unei variabile de tip NUMBER este cuprins
ntre 1.0E-129 i 9.99E125. Numrul de zecimale determin poziia n care
apare rotunjirea. Valoarea sa este cuprins ntre -84 i 127, iar implicit este 0.
Tipul NUMBER are urmtoarele subtipuri, care au aceleai intervale de
valori: NUMERIC, REAL, DEC, DECIMAL i DOUBLE PRECISION (pentru
memorarea datelor numerice n virgul fix), FLOAT (pentru memorarea datelor
numerice n virgul mobil), SMALLINT, INTEGER i INT (pentru memorarea
numerelor ntregi). Aceste subtipuri se pot utiliza pentru compatibilitate
ANSI/ISO, IBM SQL/DS sau IBM DB2.
Tipul BINARY_INTEGER memoreaz numere ntregi cu semn avnd
valori cuprinse ntre -231 - 1 i 231 - 1. Acest tip de date este utilizat frecvent
pentru indecii tabelelor, nu necesit conversii i admite mai multe subtipuri. De
exemplu, pentru a restriciona domeniul variabilelor la valori ntregi nenegative
se utilizeaz tipurile NATURAL (0 .. 231 1) i POSITIVE (1 .. 231 1).
Tipul PLS_INTEGER este utilizat pentru stocarea numerelor ntregi cu
semn i are acelai interval de definire ca i tipul BINARY_INTEGER. Operaiile
cu acest tip sunt efectuate mai rapid (folosesc aritmetica mainii), dect cele cu
tipurile NUMBER sau BINARY_INTEGER (folosesc librrii aritmetice). Prin
urmare, pentru o mai bun performan, este preferabil s se utilizeze tipul
PLS_INTEGER.

Variabilele alfanumerice pot fi de tip CHAR, VARCHAR2, LONG, RAW i


LONGRAW. Reprezentarea intern depinde de setul de caractere ales (ASCII sau
EBCDIC).
Tipurile CHAR, VARCHAR2 i RAW pot avea un parametru pentru a
preciza lungimea maxim. Dac aceasta nu este precizat atunci, implicit, se
consider 1. Lungimea este exprimat n octei (nu n caractere). Subtipurile
acestor tipuri se pot utiliza pentru compatibilitate ANSI/ISO, IBM SQL/DS sau
IBM DB2.
n Oracle9i a fost extins sintaxa pentru CHAR i VARCHAR2, permind
ca variabila ce precizeaz lungimea maxim s fie de tip CHAR sau BYTE.
Variabilele de tip LONG pot memora texte, tabele de caractere sau
documente, prin urmare iruri de caractere de lungime variabil de pn la
32760 octei. Este similar tipului VARCHAR2.
Tipul RAW permite memorarea datelor binare (bii) sau a irurilor de
octei. De exemplu, o variabil RAW poate memora o secven de caractere
grafice sau o imagine digitizat. Tipul RAW este similar tipului alfanumeric, cu
excepia faptului c PL/SQL nu interpreteaz datele de tip RAW. Oracle nu face
conversia datelor de acest tip, atunci cnd se transmit de la un sistem la altul.
Chiar dac lungimea maxim a unei variabile RAW poate fi 32767 octei, ntr-o
coloan RAW a bazei de date nu se pot introduce dect 2000 octei. Pentru a
insera valori mai mari se folosete o coloan de tip LONG RAW, care are
lungimea maxim 231 octei. LONG RAW este similar tipului LONG, dar datele
nu mai sunt interpretate de PL/SQL.
Tipurile TIMESTAMP, TIMESTAMP WITH TIME ZONE, TIMESTAMP
WITH LOCAL TIME ZONE, INTERVAL YEAR TO MONTH, INTERVAL DAY
TO SECOND au fost introduse n Oracle9i i permit rafinri ale tipului DATE.
De exemplu, TIMESTAMP poate lua n considerare i fraciuni de secund.
PL/SQL suport dou seturi de caractere: una specific bazei de date care
este utilizat pentru definirea identificatorilor i a codului surs (database
character set - DCS) i o mulime de caractere naionale care este folosit pentru
reprezentarea informaiei cu caracter naional (national character set - NCS).
Tipurile de date NCHAR i NVARCHAR2 sunt utilizate pentru stocarea n
baza de date a irurilor de caractere ce folosesc NCS. Ele ofer suport pentru
globalizarea datelor, astfel nct utilizatorii din toat lumea pot interaciona cu
Oracle n limba lor naional. Aceste tipuri de date suport numai date Unicode.
Unicode este o mulime de caractere globale care permite stocarea de
informaie n orice limb, folosind o mulime unic de caractere.

Prin urmare, unicode furnizeaz o valoare cod unic pentru fiecare


caracter, indiferent de platform, program sau limb.

Variabile nespecifice PL/SQL


Variabila de legtur (bind) se declar ntr-un mediu gazd i este folosit
pentru transferul (la execuie) valorilor numerice sau de tip caracter n/din unul
sau mai multe programe PL/SQL. Variabilele declarate n mediul gazd sau n
cel apelant pot fi referite n instruciuni PL/SQL, dac acestea nu sunt n cadrul
unei proceduri, funcii sau pachet.
n SQL*Plus, variabilele de legtur se declar folosind comanda
VARIABLE, iar pentru afiarea valorilor acestora se utilizeaz comanda PRINT.
Ele sunt referite prin prefixarea cu simbolul :, pentru a putea fi deosebite de
variabilele declarate n PL/SQL.
Deoarece instruciunile SQL pot fi integrate n programe C, este necesar
un mecanism pentru a transfera valori ntre mediul de programare C i
instruciunile SQL care comunic cu server-ul bazei de date Oracle. n acest
scop, n programul ncapsulat sunt definite variabilele gazd (host). Acestea sunt
declarate ntre directivele BEGIN DECLARE SECTION i END DECLARE
SECTION ale preprocesorului.
O valoare null n baza de date nu are o valoare corespunztoare n mediul
limbajului gazd (de exemplu, limbajul C). Pentru a rezolva problema
comunicrii valorilor null ntre programul scris n limbaj gazd i sistemul
Oracle, au fost definite variabilele indicator. Acestea sunt variabile speciale de
tip ntreg, folosite pentru a indica dac o valoare null este recuperat (extras)
din baza de date sau stocat n aceasta. Ele au urmtoarea form:
:nume_extern [: indicator]
De exemplu, dac atribuirea este fcut de limbajul gazd, valoarea 1 a
indicatorului specific faptul c PL/SQL trebuie s nlocuiasc valoarea
variabilei prin null, iar o valoare a indicatorului mai mare ca zero precizeaz c
PL/SQL trebuie s considere chiar valoarea variabilei.

Declararea variabilelor
Identificatorii PL/SQL trebuie declarai nainte de a fi referii n blocul
PL/SQL. Dac n declaraia unei variabile apar referiri la alte variabile, acestea
trebuie s fi fost declarate anterior. Orice variabil declarat ntr-un bloc este
accesibil blocurilor coninute sintactic n acesta.
Tipurile scalare sunt predefinite n pachetul STANDARD. Pentru a folosi
un astfel de tip ntr-un program este suficient s fie declarat o variabil de tipul
respectiv.
Tipurile compuse sunt definite de utilizator. Prin urmare, n acest caz
trebuie definit efectiv tipul i apoi declarat variabila de tipul respectiv.

n declararea variabilelor pot fi utilizate atributele %TYPE i


%ROWTYPE, care reprezint tipuri de date implicite. Aceste tipuri permit
declararea unei variabile n concordan cu declaraii de variabile fcute anterior.
Atributul %TYPE permite definirea unei variabile avnd tipul unei
variabile declarate anterior sau tipul unei coloane dintr-un tabel.
Atributul %ROWTYPE permite definirea unei variabile avnd tipul unei
nregistrri dintr-un tabel. Avantajul utilizrii acestui atribut const n faptul c
nu este necesar s se cunoasc numrul i tipurile coloanelor tabelului.
Elementele individuale ale acestei structuri de tip nregistrare sunt referite n
maniera clasic, prefixnd numele coloanei cu numele variabilei declarate.
Calitatea atributelor %TYPE i %ROWTYPE const n faptul c simplific
ntreinerea codului PL/SQL. De exemplu, poate fi modificat dimensiunea unei
coloane, fr s fie necesar modificarea declaraiei variabilelor al cror tip s-a
definit fcnd referin la tipul coloanei respective.
Sintaxa declarrii unei variabile este urmtoarea:
identificator [CONSTANT] {tip_de_date | identificator%TYPE |
identificator%ROWTYPE} [NOT NULL]
[ {:= | DEFAULT} expresie_PL/SQL];
Se pot defini constante (valoarea stocat nu poate fi modificat) prin
specificarea la declarare a cuvntului cheie CONSTANT.
Exemplu:
v_valoare
v_data_achizitie
v_material
c_valoare
v_stare
v_clasificare
v_cod_opera
v_opera
int_an_luna

NUMBER(15) NOT NULL := 0;


DATE DEFAULT SYSDATE;
VARCHAR2(15) := 'Matase';
CONSTANT NUMBER := 100000;
VARCHAR2(20) DEFAULT 'Buna';
BOOLEAN DEFAULT FALSE;
opera.cod_operaTYPE;
operaROWTYPE;
INTERVAL YEAR TO MONTH :=
INTERVAL '3-2' YEAR TO MONTH;

Observaii:
1. Pentru a denumi o variabil este utilizat frecvent (pentru uurina referirii)
prefixarea cu litera v (v_identificator), iar pentru o constant este folosit
prefixarea cu litera c (c_identificator).
2. Variabilele pot fi iniializate, iar dac o variabil nu este iniializat, valoarea
implicit a acesteia este null. Dac o variabil este declarat NOT NULL,
atunci ea va fi obligatoriu iniializat.
3. Pentru a iniializa o variabil sau o constant poate fi utilizat o expresie
PL/SQL compatibil ca tip cu variabila sau constanta respectiv.

4. Constantele trebuie iniializate cnd sunt declarate, altfel apare o eroare la


compilare.
5. n seciunea declarativ, pe fiecare linie, exist o singur declaraie de
variabil.
6. Dou obiecte (variabile) pot avea acelai nume cu condiia s fie definite n
blocuri diferite. Dac ele coexist, poate fi folosit doar obiectul declarat n
blocul curent.
7. Atributul %ROWTYPE nu poate include clauze de iniializare.

Definirea subtipurilor
Subtipurile deriv dintr-un tip de baz, la care se adaug anumite restricii.
De exemplu, NATURAL este un subtip predefinit PL/SQL, derivat din tipul de
baz BINARY_INTEGER, cu restricia c permite prelucrarea valorilor ntregi
nenegative.
Prin urmare, un subtip nu reprezint un nou tip de date, ci un tip existent
asupra cruia se aplic anumite constrngeri. Subtipurile presupun acelai set de
operaii ca i tipul de baz, dar aplicate unui subset de valori al acestui tip.
Sistemul Oracle permite ca utilizatorul s-i defineasc propriile sale
tipuri i subtipuri de date n partea declarativ a unui bloc PL/SQL, subprogram
sau pachet utiliznd sintaxa:
SUBTYPE nume_subtip IS tip_de_baza [NOT NULL];
n dicionarul datelor exist vizualizri care furnizeaz informaii despre
tipurile de date create de utilizator (USER_TYPES, USER_TYPE_ATTRS).

Conversii ntre tipuri de date


Exist dou tipuri de conversii:
implicite;
explicite.
PL/SQL face automat conversii implicite ntre caractere i numere sau
ntre caractere i date calendaristice. Chiar dac sistemul realizeaz automat
aceste conversii, n practic se utilizeaz frecvent funcii de conversie explicit.
Funciile de conversie explicit din SQL sunt utilizabile i n PL/SQL.
Acestea sunt: TO_NUMBER, TO_CHAR, TO_DATE, TO_MULTI_BYTE,
TO_SINGLE_BYTE, CHARTOROWID, ROWIDTOCHAR, RAWTOHEX,
HEXTORAW, TO_CLOB, TO_LOB.
n Oracle9i se pot folosi urmtoarele funcii de conversie: ASCIISTR,
BIN_TO_NUM, NUMTODSINTERVAL, TO_TIMESTAMP, TO_YMINTERVAL,
TO_NCHAR, TO_NCLOB, TO_TIMESTAMP_TZ, NUMTOYMINTERVAL,
TO_DSINTERVAL, REFTOHEX, RAWTOHEX, RAWTONHEX, FROM_TZ,
ROWIDTONCHAR, COMPOSE, DECOMPOSE.

Denumirile acestor funcii reflect posibilitile pe care le ofer. De


exemplu, TO_YMINTERVAL convertete argumentele sale la tipul INTERVAL
YEAR TO MONTH conform unui format specificat. Funcia COMPOSE
convertete un ir de caractere la un ir unicode (asociaz o valoare cod unic
pentru fiecare simbol din ir).

nregistrri
Tipul RECORD ofer un mecanism pentru prelucrarea nregistrrilor.
nregistrrile au mai multe cmpuri ce pot fi de tipuri diferite, dar care sunt
legate din punct de vedere logic.
Inregistrrile trebuie definite n doi pai:
se definete tipul RECORD;
se declar nregistrrile de acest tip.
Declararea tipului RECORD se face conform urmtoarei sintaxe:
TYPE nume_tip IS RECORD
(nume_cmp1 {tip_cmp | variabil%TYPE |
nume_tabel.coloan%TYPE | nume_tabel%ROWTYPE}
[ [NOT NULL] {:= | DEFAULT} expresie1],
(nume_cmp2 {tip_cmp | variabil%TYPE |
nume_tabel.coloan%TYPE | nume_tabel%ROWTYPE}
[ [NOT NULL] {:= | DEFAULT} expresie2],);
Identificatorul nume_tip reprezint numele tipului RECORD care se va
specifica n declararea nregistrrilor, nume_cmp este numele unui cmp al
nregistrrii, iar tip_cmp este tipul de date al cmpului.
Observaii:

Dac un cmp nu este iniializat atunci implicit se consider c are


valoarea NULL. Dac s-a specificat constrngerea NOT NULL, atunci
obligatoriu cmpul trebuie iniializat cu o valoare diferit de NULL.
Pentru referirea cmpurilor individuale din nregistrare se prefixeaz
numele cmpului cu numele nregistrrii.
Pot fi asignate valori unei nregistrri utiliznd comenzile SELECT,
FETCH sau instruciunea clasic de atribuire. De asemenea, o nregistrare
poate fi asignat altei nregistrari de acelai tip.
Componentele unei nregistrri pot fi de tip scalar, RECORD, TABLE,
obiect, colecie (dar, nu tipul REF CURSOR).
PL/SQL permite declararea i referirea nregistrrilor imbricate.
Numrul de cmpuri ale unei nregistrri nu este limitat.
nregistrrile nu pot fi comparate (egalitate, inegalitate sau null).

nregistrrile pot fi parametri n subprograme i pot s apar n clauza


RETURN a unei funcii.
Diferena dintre atributul %ROWTYPE i tipul de date compus RECORD:
tipul RECORD permite specificarea tipului de date pentru cmpuri i
permite declararea cmpurilor sale;
atributul %ROWTYPE nu cere cunoaterea numrului i tipurilor
coloanelor tabloului.
Oracle9i introduce cteva faciliti legate de acest tip de date.
Se poate insera (INSERT) o linie ntr-un tabel utiliznd o nregistrare.
Nu mai este necesar listarea cmpurilor individuale, ci este suficient
utilizarea numelui nregistrrii.
Se poate reactualiza (UPDATE) o linie a unui tabel utiliznd o
nregistrare. Sintaxa SET ROW permite s se reactualizeze ntreaga
linie folosind coninutul unei nregistrri.
ntr-o nregistrare se poate regsi i returna sau terge informaia din
clauza RETURNING a comenzilor UPDATE sau DELETE.
Dac n comenzile UPDATE sau DELETE se modific mai multe linii,
atunci pot fi utilizate n sintaxa BULK COLLECT INTO, colecii de
nregistrri.
Exemplu:
Exemplul urmtor arat modul n care poate s fie utilizat o nregistrare
n clauza RETURNING asociat comenzii DELETE.
DECLARE
TYPE val_opera IS RECORD (
cheie NUMBER,
val
NUMBER);
v_info_valoare val_opera;
BEGIN
DELETE FROM opera
WHERE cod_opera = 753
RETURNING cod_opera, valoare
INTO v_info_valoare;

END;

Colecii
Uneori este preferabil s fie prelucrate simultan mai multe variabile de
acelai tip. Tipurile de date care permit acest lucru sunt coleciile. Fiecare
element are un indice unic, care determin poziia sa n colecie.
Oracle7 a furnizat tipul index-by table, iniial numit PL/SQL table datorit
asemnrii sale cu structura tabelelor relaionale.

10

Oracle8 a introdus dou tipuri colecie, nested table i varray. Oracle9i


permite crearea de colecii pe mai multe niveluri, adic colecii de colecii.
n PL/SQL exist trei tipuri de colecii:
tablouri indexate (index-by tables);
tablouri imbricate (nested tables);
vectori (varrays sau varying arrays).
Tipul index-by table poate fi utilizat numai n declaraii PL/SQL. Tipurile
varray i nested table pot fi utilizate att n declaraii PL/SQL, ct i n declaraii
la nivelul schemei (de exemplu, pentru definirea tipului unei coloane a unui
tabel relaional).
Exemplu:
n exemplul care urmeaz sunt ilustrate cele trei tipuri de colecii.
DECLARE
TYPE tab_index IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
TYPE tab_imbri IS TABLE OF NUMBER;
TYPE vector IS VARRAY(15) OF NUMBER;
v_tab_index tab_index;
v_tab_imbri tab_imbri;
v_vector
vector;
BEGIN
v_tab_index(1) := 72;
v_tab_index(2) := 23;
v_tab_imbri := tab_imbri(5, 3, 2, 8, 7);
v_vector := vector(1, 2);
END;

Observaii:
Deoarece coleciile nu pot fi comparate (egalitate sau inegalitate), ele
nu pot s apar n clauzele DISTINCT, GROUP BY, ORDER BY.
Tipul colecie poate fi definit ntr-un pachet.
Tipul colecie poate s apar n clauza RETURN a unei funcii.
Coleciile pot fi parametri formali ntr-un subprogram.
Accesul la elementele individuale ale unei colecii se face prin
utilizarea unui indice.

Tablouri indexate
Tipul de date index-by table ofer un mecanism pentru prelucrarea
tablourilor. Tabloul indexat PL/SQL are dou componente: o coloan ce
cuprinde cheia primar pentru acces la liniile tabloului i o coloan care include
valoarea efectiv a elementelor tabloului.

11

Oracle7 asigur definirea tablourilor de nregistrri care pot fi declarate i


utilizate numai n programe PL/SQL, Oracle8 realizeaz definirea tablourilor de
tipuri obiect, iar Oracle9i permite definirea tablourilor de colecii.
n Oracle9i tipul index-by table este redenumit associative array pentru
compatibilitate (de limbaj) cu termenul folosit n alte limbaje de programare (C+
+, JavaScript, Perl) pentru a defini aceast structur de date.
Tablourile indexate PL/SQL trebuie definite n doi pai: se definete tipul
TABLE; se declar tabloul indexat PL/SQL de acest tip.
Declararea tipului TABLE se face respectnd urmtoarea sintax:
TYPE nume_tip IS TABLE OF
{tip_coloan | variabil%TYPE |
nume_tabel.coloan%TYPE [NOT NULL] |
nume_tabel%ROWTYPE}
INDEX BY tip_indexare;
Identificatorul nume_tip este numele noului tip definit care va fi specificat
n declararea tabloului PL/SQL, iar tip_coloan este un tip scalar simplu (de
exemplu, VARCHAR2, CHAR, DATE sau NUMBER).
Pn la versiunea Oracle9i unicul tip de indexare acceptat era INDEX BY
BINARY_INTEGER. Oracle9i permite urmtoarele opiuni pentru tip_indexare:
PLS_INTEGER, NATURAL, POSITIVE, VARCHAR2(n) sau chiar indexarea
dup un tip declarat cu %TYPE. Nu sunt permise indexrile INDEX BY
NUMBER, INDEX BY INTEGER, INDEX BY DATE, INDEX BY VARCHAR2,
INDEX BY CHAR(n) sau indexarea dup un tip declarat cu %TYPE n care
intervine unul dintre tipurile enumerate anterior.
Observaii:
Elementele unui tablou indexat nu sunt ntr-o ordine particular i pot
fi inserate cu chei arbitrare.
Deoarece nu exist constrngeri de dimensiune, dimensiunea tabloului
se modific dinamic.
Tabloul indexat PL/SQL nu poate fi iniializat n declararea sa.
Un tablou indexat neiniializat este vid (nu conine nici valori, nici
chei).
Un element al tabloului este nedefinit atta timp ct nu are atribuit o
valoare efectiv.
Iniial, un tablou indexat este nedens. Dup declararea unui tablou se
poate face referire la liniile lui prin precizarea valorii cheii primare.

12

Dac se face referire la o linie care nu exist, atunci se produce


excepia NO_DATA_FOUND.
Dac se dorete contorizarea numrului de linii, trebuie declarat o
variabil n acest scop sau poate fi utilizat o metod asociat
tabloului.
Deoarece numrul de linii nu este limitat, operaia de adugare de linii
este restricionat doar de dimensiunea memoriei alocate.
Tablourile pot s apar ca argumente ntr-o procedur.
Pentru inserarea unor valori din tablourile PL/SQL ntr-o coloan a unui
tabel de date se utilizeaz instruciunea INSERT n cadrul unei secvene
repetitive LOOP.
Asemntor, pentru regsirea unor valori dintr-o coloan a unei baze de
date ntr-un tablou PL/SQL se utilizeaz instruciunea FETCH (cursoare) sau
instruciunea de atribuire n cadrul unei secvene repetitive LOOP.
Pentru a terge liniile unui tablou fie se asigneaz elementelor tabloului
valoarea null, fie se declar un alt tablou PL/SQL (de acelai tip) care nu este
iniializat i acest tablou vid se asigneaz tabloului PL/SQL care trebuie ters. n
PL/SQL 2.3 tergerea liniilor unui tabel se poate face utiliznd metoda DELETE.
Exemplu:
S se defineasc un tablou indexat PL/SQL avnd elemente de tipul
NUMBER. S se introduc 20 de elemente n acest tablou. S se tearg tabloul.
DECLARE
TYPE tablou_numar IS TABLE OF NUMBER
INDEX BY PLS_INTEGER;
v_tablou tablou_numar;
BEGIN
FOR i IN 1..20 LOOP
v_tablou(i) := i*i;
DBMS_OUTPUT.PUT_LINE(v_tablou(i));
END LOOP;
--v_tablou := NULL;
--aceasta atribuire da eroarea PLS-00382
FOR i IN v_tablou.FIRST..v_tablou.LAST LOOP
v_tablou(i) := NULL;
END LOOP;
DBMS_OUTPUT.PUT_LINE('tabloul are ' || v_tablou.COUNT ||
' elemente');
END;

n PL/SQL este folosit frecvent tipul tablou de nregistrri. Referirea la un


element al tabloului se face prin forma clasic: tabel(index).cmp.
Exemplu:

13

S se defineasc un tablou de nregistrri avnd tipul celor din tabelul


organizator. S se iniializeze un element al tabloului i s se introduc n
tabelul organizator. S se tearg elementele tabloului.
DECLARE
TYPE org_table_type IS TABLE OF organizator%ROWTYPE
INDEX BY BINARY INTEGER;
org_table org_table_type;
i
NUMBER;
BEGIN
IF org_table.COUNT <>0 THEN
i := org_table.LAST+1;
ELSE i:=1;
END IF;
org_table(i).cod_org := 752;
org_table(i).nume := 'Grigore Ion';
org_table(i).adresa := 'Calea Plevnei 18 Sibiu';
org_table(i).tip := 'persoana fizica';
INSERT INTO organizator
VALUES (org_table(i).cod_org, org_table(i).nume,
org_table(i).adresa, org_table(i).tip);
-- sau folosind noua facilitate Oracle9i
-- INSERT INTO organizator
-- VALUES (org_table(i));
org_table.DELETE; -- sterge toate elementele
DBMS_OUTPUT.PUT_LINE('Dupa aplicarea metodei DELETE
sunt '||TO_CHAR(org_table.COUNT)||' elemente');
END;

Vectori
Vectorii (varray) sunt structuri asemntoare vectorilor din limbajele C
sau Java. Spre deosebire de tablourile indexate, vectorii au o dimensiune
maxim (constant) stabilit la declarare. n special, se utilizeaz pentru
modelarea relaiilor one-to-many, atunci cnd numrul maxim de elemente din
partea many este cunoscut i ordinea elementelor este important.
Vectorii reprezint structuri dense. Fiecare element are un index care d
poziia sa n vector i care este folosit pentru accesarea elementelor particulare.
Limita inferioar a indicelui este 1. Vectorul poate conine un numr variabil de
elemente, de la 0 (vid) la numrul maxim specificat obligatoriu n definiia sa.
Tipul de date vector este declarat utiliznd sintaxa:
TYPE nume_tip IS
{VARRAY | VARYING ARRAY} (lungime_maxim)
OF tip_elemente [NOT NULL];

14

Identificatorul nume_tip este numele tipului de date vector, iar


lungime_maxim reprezint numrul maxim de elemente din vector.
Tip_elemente este un tip scalar PL/SQL, tip nregistrare sau tip obiect. De
asemenea, acest tip poate fi definit utiliznd atributele %TYPE sau
%ROWTYPE.
n Oracle9i sunt permise (pentru tip_elemente) tipurile TABLE sau alt tip
VARRAY. Exist restricii referitoare la tipul elementelor, n sensul c acesta nu
poate s fie BOOLEAN, NCHAR, NCLOB, NVARCHAR2, REF CURSOR,
PLS_INTEGER, LONG, LONG RAW, NATURAL, NATURALN, POSITIVE,
POSITIVEN, BINARY_INTEGER, SIGNTYPE, STRING, tip obiect cu atribute
TABLE sau VARRAY, BLOB, CLOB, tip obiect cu atribute BLOB sau CLOB.
Exemplu:
DECLARE
TYPE secventa IS VARRAY(5) OF VARCHAR2(10);
v_sec secventa := secventa ('alb', 'negru', 'rosu',
'verde');
BEGIN
v_sec (3) := 'rosu';
v_sec.EXTEND; -- adauga un element null
v_sec(5) := 'albastru';
-- extinderea la 6 elemente va genera eroarea ORA-06532
v_sec.EXTEND;
END;

Tablouri imbricate
Tablourile imbricate (nested table) sunt tablouri indexate a cror
dimensiune nu este stabilit. Numrul maxim de linii ale unui tablou imbricat
este dat de capacitatea maxim 2 GB.
Un tablou imbricat este o mulime neordonat de elemente de acelai tip.
Valorile de acest tip:
-- pot fi stocate n baza de date,
-- pot fi prelucrate direct n instruciuni SQL
-- au excepii predefinite proprii.
Sistemul Oracle nu stocheaz liniile unui tablou imbricat ntr-o ordine
particular. Dar, cnd se regsete tabloul n variabile PL/SQL, liniile vor avea
indici consecutivi ncepnd cu valoarea 1. Iniial, aceste tablouri sunt structuri
dense, dar se poate ca n urma prelucrrii s nu mai aib indici consecutivi.
Comanda de declarare a tipului de date tablou imbricat are sintaxa:
TYPE nume_tip IS TABLE OF tip_ elemente [NOT NULL];
Identificatorul nume_tip reprezint numele noului tip de date tablou
imbricat, iar tip_elemente este tipul fiecrui element din tabloul imbricat, care
poate fi un tip definit de utilizator sau o expresie cu %TYPE, respectiv
%ROWTYPE.

15

n Oracle9i sunt permise (pentru tip_elemente) tipurile TABLE sau alt tip
VARRAY. Exist restricii referitoare la tipul elementelor, n sensul c acesta nu
poate s fie BOOLEAN, STRING, NCHAR, NCLOB, NVARCHAR2, REF
CURSOR, BINARY_INTEGER, PLS_INTEGER, LONG, LONG RAW,
NATURAL, NATURALN, POSITIVE, POSITIVEN, SIGNTYPE, tip obiect cu
atributele TABLE sau VARRAY.
Tabloul imbricat are o singur coloan, iar dac aceasta este de tip obiect,
tabloul poate fi vizualizat ca un tabel multicoloan, avnd cte o coloan pentru
fiecare atribut al tipului obiect.
Exemplu:
DECLARE
TYPE numartab IS TABLE OF NUMBER;
-- se creeaza un tablou cu un singur element
v_tab_1 numartab := numartab(-7);
-- se creeaza un tablou cu 4 elemente
v_tab_2 numartab := numartab(7,9,4,5);
-- se creeaza un tablou fara nici un element
v_tab_3 numartab := numartab();
BEGIN
v_tab_1(1) := 57;
FOR j IN 1..4 LOOP
DBMS_OUTPUT.PUT_LINE (v_tab_2(j) || ' ');
END LOOP;
END;

Se observ c singura diferen sintactic ntre tablourile indexate i cele


imbricate este absena clauzei INDEX BY BINARY_INTEGER. Mai exact, dac
aceast clauz lipsete, tipul este tablou imbricat.
Observaii:
Spre deosebire de tablourile indexate, vectorii i tablourile imbricate
pot s apar n definirea tabelelor bazei de date.
Tablourile indexate pot avea indice negativ, domeniul permis pentru
index fiind 2147483647..2147483647, iar pentru tabele imbricate
domeniul indexului este 1..2147483647.
Tablourile imbricate, spre deosebire de tablourile indexate, pot fi
prelucrate prin comenzi SQL.
Tablourile imbricate trebuie iniializate i/sau extinse pentru a li se
aduga elemente.
Cnd este creat un tablou indexat care nu are nc elemente, el este vid.
Dac un tablou imbricat (sau un vector) este declarat, dar nu are nc nici un

16

element (nu este iniializat), el este automat iniializat (atomic) null. Adic,
colecia este null, nu elementele sale. Prin urmare, pentru tablouri imbricate
poate fi utilizat operatorul IS NULL. Dac se ncearc s se adauge un element
la un tablou imbricat null, se va genera eroarea ORA - 06531: reference to
uninitialized
collection
care
corespunde
excepiei
predefinite
COLLECTION_IS_NULL.
Prin urmare, cum poate fi iniializat un tablou imbricat? Ca i obiectele,
vectorii i tablourile imbricate sunt iniializate cu ajutorul constructorului.
Acesta are acelai nume ca i tipul coleciei referite. PL/SQL apeleaz un
constructor numai n mod explicit. Tabelele indexate nu au constructori.
Constructorul primete ca argumente o list de valori de tip tip_elemente.
Elementele sunt numerotate n ordine, de la 1 la numrul de valori date ca
parametrii constructorului. Dimensiunea iniial a coleciei este egal cu
numrul de argumente date n constructor, cnd aceasta este iniializat. Pentru
vectori nu poate fi depit dimensiunea maxim precizat la declarare. Atunci
cnd constructorul este fr argumente, va crea o colectie fr nici un element
(vida), dar care are valoarea not null. Exemplul urmtor este concludent n acest
sens.
Exemplu:
DECLARE
TYPE alfa IS TABLE OF VARCHAR2(50);
-- creeaza un tablou (atomic) null
tab1 alfa ;
/* creeaza un tablou cu un element care este null, dar
tabloul nu este null, el este initializat, poate
primi elemente */
tab2 alfa := alfa() ;
BEGIN
IF tab1 IS NULL THEN
DBMS_OUTPUT.PUT_LINE('tab1
ELSE
DBMS_OUTPUT.PUT_LINE('tab1
END IF;
IF tab2 IS NULL THEN
DBMS_OUTPUT.PUT_LINE('tab2
ELSE
DBMS_OUTPUT.PUT_LINE('tab2
END IF;
END;

este NULL');
este NOT NULL');
este NULL');
este NOT NULL');

17

n urma execuiei acestui bloc se obine urmtorul rezultat:


tab1 este NULL
tab2 este NOT NULL
Excepiile semnificative care apar n cazul utilizrii incorecte a coleciilor:
Exemplu:
DECLARE
TYPE numar IS TABLE OF INTEGER;
alfa numar;
BEGIN
alfa(1) := 77;
-- declanseaza exceptia COLLECTION_IS_NULL
alfa := numar(15, 26, 37);
alfa(1) := ASCII('X');
alfa(2) := 10*alfa(1);
alfa('P') := 77;
/* declanseaza exceptia VALUE_ERROR deoarece indicele
nu este convertibil la intreg */
alfa(4) := 47;
/* declanseaza exceptia SUBSCRIPT_BEYOND_COUNT deoarece
indicele se refera la un element neinitializat */
alfa(null) := 7; -- declanseaza exceptia VALUE_ERROR
alfa(0) := 7; -- exceptia SUBSCRIPT_OUTSIDE_LIMIT
alfa.DELETE(1);
IF alfa(1) = 1 THEN -- exceptia NO_DATA_FOUND

END;
Tablourile imbricate i vectorii pot fi utilizai drept cmpuri n tabelele
bazei. Aceasta presupune c fiecare nregistrare din tabelul respectiv conine un
obiect de tip colecie. nainte de utilizare, tipul trebuie stocat n dicionarul
datelor, deci trebuie declarat prin comanda:
CREATE TYPE nume_tip AS {TABLE | VARRAY} OF tip_elemente;
Dup crearea tabelului (prin comanda CREATE TABLE), pentru fiecare
cmp de tip tablou imbricat din tabel este necesar clauza de stocare:
NESTED TABLE nume_cmp STORE AS nume_tabel;

Colecii pe mai multe niveluri


n Oracle9i se pot construi colecii pe mai multe niveluri (multilevel
collections), prin urmare colecii ale cror elemente sunt, n mod direct sau
indirect, colecii. n felul acesta pot fi definite structuri complexe: vectori de

18

vectori, vectori de tablouri imbricate, tablou imbricat de vectori, tablou imbricat


de tablouri imbricate, tablou imbricat sau vector de un tip definit de utilizator
care are un atribut de tip tablou imbricat sau vector.
Aceste structuri complexe pot fi utilizate ca tipuri de date pentru definirea:
coloanelor unui tabel relaional,
atributelor unui obiect ntr-un tabel obiect,
variabilelor PL/SQL.
Observaii:
Numrul nivelurilor de imbricare este limitat doar de capacitatea de
stocare a sistemului.
Pentru a accesa un element al coleciei incluse sunt utilizate dou
seturi de paranteze.
Obiectele de tipul colecie pe mai multe niveluri nu pot fi comparate.
Exemplu:
n exemplele care urmeaz sunt definite trei structuri complexe i sunt
prezentate cteva modaliti de utilizare ale acestora. Exemplele se refer la
vectori pe mai multe niveluri, tablouri imbricate pe mai multe niveluri i tablouri
indexate pe mai multe niveluri.
DECLARE
TYPE alfa IS VARRAY(10) OF INTEGER;
TYPE beta IS VARRAY(10) OF alfa;
valf alfa := alfa(12,31,5); --initializare
vbet beta := beta(valf,alfa(55,6,77),alfa(2,4),valf);
i
integer;
var1 alfa;
BEGIN
i := vbet(2)(3); -- i va lua valoarea 77
vbet.EXTEND; -- se adauga un element de tip vector la vbet

vbet(5) := alfa(56,33);
vbet(4) := alfa(44,66,77,4321);
vbet(4)(4) := 7; -- 4321 este inlocuit cu 7
vbet(4).EXTEND; -- se adauga un element la al 4-lea element
vbet(4)(5) := 777; -- acest nou element adaugat va fi 777
END;

/
DECLARE
TYPE gama IS TABLE OF VARCHAR2(20);
TYPE delta IS TABLE OF gama;
TYPE teta IS VARRAY(10) OF INTEGER;

19

TYPE epsi IS TABLE OF teta;


var1 gama := gama('alb','negru');
var2 delta := delta(var1);
var3 epsi := epsi(teta(31,15),teta(1,3,5));
BEGIN
var2.EXTEND;
var2(2) := var2(1);
var2.DELETE(1); -- sterge primul element din var2
/* sterge primul sir de caractere din al doilea
tablou al tabloului imbricat */
var2(2).DELETE(1);
END;
/
DECLARE
TYPE alfa IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;
TYPE beta IS TABLE OF alfa INDEX BY BINARY_INTEGER;
TYPE gama IS VARRAY(10) OF VARCHAR2(30);
TYPE delt IS TABLE OF gama INDEX BY BINARY_INTEGER;
var1 gama := gama('alb','negru');
var2 beta;
var3 delt;
var4 alfa;
var5 alfa; -- tablou vid
BEGIN
var4(1) := 324;
var4(2) := 222;
var4(42) := 333;
var2(27) := var4;
var3(39) := gama(77,76,89,908);
-- var2(40)(3) := 55; eroare nu exista element 40 in var2
var2(40) := var5; -- asignez un tablou null
var2(40)(3) := 55; -- corect
END;
/

Prelucrarea coleciilor
O colecie poate fi exploatat fie n ntregime (atomic) utiliznd comenzi
LMD, fie pot fi prelucrate elemente individuale dintr-o colecie (piecewise
updates) utiliznd operatori SQL sau anumite faciliti oferite de PL/SQL.
Comanda INSERT permite inserarea unei colecii ntr-o linie a unui
tabel. Colecia trebuie s fie creat i iniializat anterior.
Comanda UPDATE este folosit pentru modificarea unei colecii
stocate.

20

Comanda DELETE poate terge o linie ce conine o colecie.


Coleciile din baza de date pot fi regsite n variabile PL/SQL,
utiliznd comanda SELECT.
Exemplu:
CREATE OR REPLACE TYPE operalist AS VARRAY(10) OF
NUMBER(4);
CREATE TABLE gal_ope (
cod_galerie
NUMBER(10),
nume_galerie VARCHAR2(20),
info
operalist);
DECLARE
v_opera
operalist := operalist (777, 888, 999);
v_info_op operalist := operalist (7007);
v_info
gal_ope.info%TYPE;
v_cod
gal_ope.cod_galerie%TYPE := 2345;
BEGIN
INSERT INTO gal_ope
VALUES (4567, 'Impresionisti', operalist(4567,4987));
INSERT INTO gal_ope
VALUES (2345, 'Cubism', v_opera);
INSERT INTO gal_ope
VALUES (123, 'Alfa', v_info_op);
SELECT info
INTO
v_info
FROM
gal_ope
WHERE cod_galerie = v_cod;

END;
Un vector stocat ntr-un tabel este prelucrat ca un ntreg (nu pot fi
modificate elemente individuale). Prin urmare, elementele individuale ale unui
vector nu pot fi referite n comenzile INSERT, UPDATE sau DELETE. Pentru
referirea acestora trebuie utilizate comenzi procedurale PL/SQL. Pentru a
modifica un vector, el trebuie selectat ntr-o variabil PL/SQL a crei valoare
poate fi modificat i apoi reinserat n tabel.
Tablourile imbricate depuse n baza de date sunt mai flexibile, deoarece
pot fi prelucrate fie n ntregime, fie ca elemente individuale. n fiecare caz pot fi
utilizate numai comenzi SQL.
Se pot face reactualizri sau inserri asupra tablourilor imbricate care dau
o valoare nou pentru ntreaga colecie sau se pot face inserri, tergeri,
reactualizri de elemente particulare din colecie.

21

O colecie poate fi asignat altei colecii prin comenzile INSERT,


UPDATE, FETCH, SELECT, instruciunea de atribuire sau prin apelul unui
subprogram, dar coleciile trebuie s fie de acelai tip. Dac unei colecii i se
asigneaz o colecie atomic null, aceasta devine atomic null i trebuie
reiniializat.
n Oracle8i a fost introdus operatorul TABLE, ce permite prelucrarea
elementelor unui tablou imbricat care este stocat ntr-un tabel. Operatorul
permite interogarea unei colecii n clauza FROM (la fel ca un tabel).
Operandul lui TABLE este:
fie numele unei colecii i atunci rezultatul operatorului este tot o
colecie,
fie este o subinterogare referitoare la o colecie, iar n acest caz,
operatorul TABLE returneaz o singur valoare (coloan) care este un
tablou imbricat sau un vector. Prin urmare, lista din clauza SELECT a
subcererii trebuie s aib un singur articol.
Exemplu:
Se presupune c tabelul opera are o coloan info de tip tablou imbricat.
Acest tablou are dou componente n care pentru fiecare oper de art sunt
depuse numele articolului referitor la opera respectiv i revista n care a aprut.
S se insereze o linie n tabelul imbricat.
INSERT INTO TABLE (SELECT info
FROM
opera
WHERE titlu = 'Primavara')
VALUES ('Pictura moderna', 'Orizonturi');
Listarea codului fiecrei opere de art i a coleciei articolelor referitoare
la aceste opere de art se face prin comanda:
SELECT a.cod_opera, b.*
FROM
opera a, TABLE (a.info) b;
Pentru tablouri imbricate pe mai multe niveluri, operaiile LMD pot fi
fcute atomic sau pe elemente individuale, iar pentru vectori pe mai multe
niveluri, operaiile pot fi fcute numai atomic.
Pentru prelucrarea unei colecii locale se poate folosi i operatorul CAST.
CAST are forma sintactic:
CAST (nume_colecie AS tip_colecie)
Operanzii lui CAST sunt o colecie declarat local (de exemplu, ntr-un
bloc PL/SQL anonim) i un tip colecie SQL. CAST convertete colecia local la

22

tipul specificat. n felul acesta, o colecie poate fi prelucrat ca i cum ar fi un


tabel SQL al bazei de date.

Metodele unei colecii


PL/SQL ofer subprograme numite metode (methods), care opereaz
asupra unei colecii. Acestea pot fi apelate numai din comenzi procedurale, i
nu din SQL.
Metodele sunt apelate prin expresia:
nume_colecie.nume_metod [ (parametri) ]
Metodele care se pot aplica coleciilor PL/SQL sunt urmtoarele:
COUNT returneaz numrul curent de elemente ale unei colecii PL/SQL;
DELETE(n) terge elementul n dintr-o colecie PL/SQL; DELETE(m, n)
terge toate elementele avnd indecii ntre m i n; DELETE terge
toate elementele unei colecii PL/SQL (nu este valid pentru tipul
varrays);
EXISTS(n) returneaz TRUE dac exist al n-lea element al unei colecii
PL/SQL (altfel, returneaz FALSE, chiar dac elementul este null);
FIRST, LAST returneaz indicele primului, respectiv ultimului element
din colecie;
NEXT(n), PRIOR(n) returneaz indicele elementului urmtor, respectiv
precedent celui de rang n din colecie, iar dac nu exist un astfel de
element returneaz valoarea null;
EXTEND adaug elemente la sfritul unei colecii: EXTEND adaug un
element null la sfritul coleciei, EXTEND(n) adaug n elemente null,
EXTEND(n, i) adaug n copii ale elementului de rang i (nu este valid
pentru tipul index-by tables); nu poate fi utilizat pentru a iniializa o
colecie atomic null;
LIMIT returneaz numrul maxim de elemente ale unei colecii (cel de la
declarare) pentru tipul vector i null pentru tablouri imbricate (nu este
valid pentru tipul index-by tables);
TRIM terge elementele de la sfritul unei colecii: TRIM terge ultimul
element, TRIM(n) terge ultimele n elemente (nu este valid pentru
tipul index-by tables). Similar metodei EXTEND, metoda TRIM
opereaz asupra dimensiunii interne a tabloului imbricat.
EXISTS este singura metod care poate fi aplicat unei colecii atomice
null. Orice alt metod declaneaz excepia COLLECTION_IS_NULL.

Bulk bind

23

n exemplul care urmeaz, comanda DELETE este trimis motorului SQL


pentru fiecare iteraie a comenzii FOR.
Exemplu:
DECLARE
TYPE nume IS VARRAY(20) OF NUMBER;
alfa nume := nume(10,20,70); -- coduri ale galeriilor
BEGIN
FOR j IN alfa.FIRST..alfa.LAST
DELETE FROM opera
WHERE cod_galerie = alfa (j);
END LOOP;
END;
Pentru a realiza mai rapid aceast operaie, ar trebui s existe posibilitatea
de a terge (prelucra) ntreaga colecie i nu elemente individuale. Tehnica care
permite acest lucru este cunoscut sub numele bulk bind.
n timpul compilrii, compilatorul PL/SQL asociaz identificatorii cu o
adres, un tip de date i o valoare. Acest proces este numit binding.
Comenzile SQL din blocurile PL/SQL sunt trimise motorului SQL pentru a
fi executate. Motorul SQL poate trimite napoi date motorului PL/SQL (de
exemplu, ca rezultat al unei interogri). De multe ori, datele care trebuie
manipulate aparin unei colecii, iar colecia este iterat printr-un ciclu FOR.
Prin urmare, transferul (n ambele sensuri) ntre SQL i PL/SQL are loc pentru
fiecare linie a coleciei.
ncepnd cu Oracle8i exist posibilitatea ca toate liniile unei colecii s
fie transferate simultan printr-o singur operaie. Procedeul este numit bulk bind
i este realizat cu ajutorul comenzii FORALL, ce poate fi folosit cu orice tip de
colecie.
Comanda FORALL are sintaxa:
FORALL index IN lim_inf..lim_sup
comanda_sql;
Motorul SQL execut comanda_sql o singur dat pentru toate valorile
indexului. Comanda_sql este una din comenzile INSERT, UPDATE, DELETE
care refer elementele uneia sau mai multor colecii. Variabila index poate fi
referit numai n comanda FORALL i numai ca indice de colecie.
n exemplul care urmeaz este optimizat problema anterioar, n sensul
c instruciunea DELETE este trimis motorului SQL o singur dat, pentru toate
liniile coleciei.
Exemplu:

24

DECLARE
TYPE nume IS VARRAY(20) OF NUMBER;
alfa nume := nume(10,20,70); -- coduri ale galeriilor
BEGIN

FORALL j IN alfa.FIRST..alfa.LAST
DELETE FROM opera
WHERE cod_galerie = alfa (j);
END;
Pentru utilizarea comenzii FORALL este necesar respectarea
urmtoarelor restricii:
comanda poate fi folosit numai n programe server-side, altfel apare
eroarea this feature is not supported in client-side programs;
comenziile INSERT, UPDATE, DELETE trebuie s refere cel puin o
colecie;
toate elementele coleciei din domeniul precizat trebuie s existe
(dac, de exemplu, un element a fost ters, atunci este semnalat o
eroare);
indicii coleciilor nu pot s fie expresii i trebuie s aib valori
continue.
Exemplu:
CREATE TABLE exemplu (x NUMBER, y NUMBER);
DECLARE
TYPE nume IS TABLE OF NUMBER;
ttt
nume:= nume(1,2,3);
BEGIN
FORALL i IN ttt.FIRST..ttt.LAST
INSERT INTO exemplu
VALUES(ttt(i), 10); -- corect
FORALL i IN 1..3
INSERT INTO exemplu
VALUES(7, 9);
-- exceptie
END;
FORALL i IN gama.FIRST..gama.LAST
DELETE FROM carte
WHERE codel = gama(i+1);
-- eroare dubla (expresie si >LAST)
DECLARE

25

TYPE alfa IS TABLE OF NUMBER;


xx
alfa := alfa(10,20,30,40);
BEGIN
xx.DELETE(3);
FORALL i IN xx.FIRST..xx.LAST
DELETE FROM carte
WHERE codel = xx(i); -- eroare
END;
Dac exist o eroare n procesarea unei linii printr-o operaie LMD de tip
bulk, numai acea linie va fi rollback.
Cursorul SQL are un atribut compus %BULK_ROWCOUNT care numr
liniile afectate de iteraiile comenzii FORALL. %BULK_ROWCOUNT(i)
reprezint numrul de linii procesate de a i-a execuie a comenzii SQL. Dac nu
este afectat nici o linie, valoarea atributului este 0. %BULK_ROWCOUNT nu
poate s fie parametru n subprograme i nu poate fi asignat altor colecii.
ncepnd cu Oracle9i este utilizabil o nou clauz n comanda FORALL.
Clauza, numit SAVE EXCEPTIONS, permite ca toate excepiile care apar n
timpul execuiei comenzii FORALL s fie salvate i astfel procesarea poate s
continue. n acest context, poate fi utilizat atributul cursor
%BULK_EXCEPTIONS pentru a vizualiza informaii despre aceste excepii.
Atributul acioneaz ca un tablou PL/SQL i are dou cmpuri:
%BULK_EXCEPTIONS(i).ERROR_INDEX, reprezentnd iteraia n
timpul creia s-a declanat excepia;
%BULK_EXCEPTIONS(i).ERROR_CODE,
reprezentnd
codul
Oracle al erorii respective.
Regsirea rezultatului unei interogri n colecii (nainte de a fi trimis
motorului PL/SQL) se poate obine cu ajutorul clauzei BULK COLLECT.
Clauza poate s apar n:
comenzile SELECT INTO (cursoare implicite),
comenzile FETCH INTO (cursoare explicite),
clauza RETURNING INTO a comenzilor INSERT, UPDATE, DELETE.
Clauza are urmtoarea sintax:
BULK COLLECT INTO nume_colecie [,nume_colecie]

DECLARE
TYPE tip1 IS TABLE OF opera.cod_opera%TYPE;

26

TYPE tip2 IS TABLE OF opera.titlu%TYPE;


alfa tip1;
beta tip2;
BEGIN

/* motorul SQL incarca in intregime coloanele


cod_opera si titlu in tabelele imbricate,
inainte de a returna
tabelele motorului PL/SQL */
SELECT cod_opera, titlu BULK COLLECT INTO alfa,beta
FROM
opera;

/* daca exista n opere de arta in stare buna,


atunci alfa va contine codurile celor n opere */
DELETE FROM opera WHERE stare = 'buna'
RETURNING cod_opera BULK COLLECT INTO alfa;

END;
Comanda FORALL se poate combina cu clauza BULK COLLECT. Totui,
trebuie subliniat c ele nu pot fi folosite simultan n comanda SELECT.
Motorul SQL incarca toate liniile unei coloane. Cum se poate limita
numarul de linii procesate? Exemplelele urmatoare dau 2 variante de rezolvare.
DECLARE
TYPE alfa IS TABLE OF carte.pret%TYPE;
xx
alfa;
BEGIN
SELECT pret BULK COLLECT INTO xx
FROM
carte WHERE ROWNUM <= 500;
END;
DECLARE

zz NATURAL := 10;
BEGIN
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO xx, yy LIMIT zz;
EXIT WHEN c1%NOTFOUND;

END;

S-ar putea să vă placă și