Sunteți pe pagina 1din 10

Facultatea de Cibernetică, Statistică şi Informatică Economică

SGBD Oracle – seminarul 2

VARIABILE

1. Declarare şi iniţializare

 declararea variabilelor se realizează în zona declarativă (delimitată prin DECLARE) a


blocului (sau sub-blocului);
 iniţializarea se poate face la declarare sau în zona de execuţie (între BEGIN şi END);
 variabilele vor fi vizibile în restul blocului, respectiv şi în blocurile incluse în el, mai puţin în
sub-blocurile în care numele lor este redefinit (ca în majoritatea limbajelor de programare
structurate, semnificaţia unui nume definit de utilizator într-un bloc/sub-bloc este dată de cea
mai apropiată declaraţie anterioară locului folosirii);
 toate variabilele PL/SQL au un tip de dată, restricţii şi un şir valid de valori;
 declararea şi iniţializarea se realizează astfel:

nume_variabila [CONSTANT] TIP_DATA [NOT NULL] [:= | DEFAULT expresie]

 constantele trebuie obligatoriu iniţializate, iar ulterior nu îşi vor putea schimba valoarea;
 variabilele NOT NULL trebuie obligatoriu iniţializate, iar ulterior nu vor putea primi
valoarea NULL;
 se foloseşte următoarea convenţie de notare:
c_nume Constanta
v_nume Variabila
g_nume VarGlobala (variabilă globală definită în zona de specificaţii a pachetului de
programe şi valabilă pentru toate subprogramele pachetului).

2. Tipuri de variabile

Variabile PL/SQL
 Scalare
 Compozite
 Referinţă
 LOB (Large Objects): NCLOB, CLOB, BLOB, BFILE
 Obiect
Variabile non-PL/SQL: variabile de mediu (BIND VARIABLES), variabile gazdă
(HOST VARIABLES), variabile indicator (INDICATOR VARIABLES)

a) Variabile Scalare:
Tipurile scalare conţin valori simple (o variabila scalară poate conţine la un moment dat o
singură valoare simplă). Cele mai folosite tipuri sunt:

 CHAR (lung_max) - lungime fixă de max 32.767 bytes


 VARCHAR2 (lung_max) – lungime variabilă de max 32.767 bytes
 LONG [şir de caractere de lungime variabilă 2GB]
 NUMBER (precizie,scală) – virgulă fixă, precizie maximă 38 cifre
zecimale

1
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

 BOOLEAN (poate lua valorile TRUE, FALSE sau NULL) – nu are un


tip SQL echivalent
 DATE
 BINARY_integer şi PLS_INTEGER (numere întregi între -
2147483647 şi 2147483647) – sunt specifice PL/SQL, folosesc
aritmetica mașinii astfel încât operațiile sunt mai rapide comparativ
cu tipul NUMBER
 BINARY_FLOAT şi BINARY_DOUBLE (pentru numere reale,
precizie simplă, respectiv dublă)
 TIMESTAMP (f) – dată calendaristică și timp cu precizia f pentru
milisecunde. Există și varianta TIMESTAMP WITH TIME ZONE
precum și TIMESTAMP WITH LOCAL TIME ZONE

Exemple de definire variabile și constante:


set serveroutput on; -- pentru a putea asisa pe ecran

declare
v_functie varchar2(9);
v_numar binary_integer:=0;
v_totalsal number(9,2):=0;
v_datainceput date:=sysdate+7;
c_taxa constant number(3,2):=8.25;
v_valid boolean not null:=true;
begin
dbms_output.put_line('test');
end;
/

Tipurile de date pot avea subtipuri, definite de Oracle sau de către utilizator. Subtipurile pot
introduce restricții tipului de bază, conținând o submulțime a acestuia. Există și subtipuri care nu
introduc nicio restricție tipului de bază, acestea pot avea rol în asigurarea compatibilității cu alte
baze de date și limbaje de programare. Spre exemplu, NUMBER are printre subtipuri,
DECIMAL pentru virgulă fixă cu o precizie maximă de 38 cifre zecimale și FLOAT pentru
virgulă mobilă cu o precizie de aproximativ 38 cifre zecimale (nu introduce practic vreo
restricție tipului de bază). Tipul PLS_INTEGER are printre subtipuri NATURAL pentru valori
nenegative și SIGNTYPE care poate lua doar valorile -1, 0 sau 1. VARCHAR și STRING sunt
subtipuri cu același domeniu de valori ca și VARCHAR2.

Exemplu:
declare
m decimal; -- echivalent m NUMBER(38,0)
n float; -- echivalent n NUMBER
begin
m:=100.20;
dbms_output.put_line('m='||m);
n:=100.20;
dbms_output.put_line('n='||n);
2
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

end;
/

Execuția blocului va afișa:


m=100
n=100.2

Exemplu:
declare
z signtype;
begin
z:=2;
dbms_output.put_line('z='||z);
end;
/

Execuția blocului va genera o excepție deoarece variabila z nu poate lua decât valorile -1, 0 sau
1.

Afişarea variabilelor PL/SQL se realizează prin intermediul funcţiei PUT_LINE din pachetului
DBMS_OUTPUT. Se poate utiliza operatorul de concatenare ( || ) pentru a afişa mai multe
mesaje sau variabile pe aceeaşi linie.

DBMS_OUTPUT.PUT_LINE ('VALOAREA VARIABILEI ESTE:' ||variabila);

Popularea variabilelor cu valori din tabelele bazei de date


 Se utilizează comanda SELECT cu clauza INTO pentru popularea variabilelor PL/SQL cu
valori ale atributelor din tabele;
 cererile SELECT din cadrul blocurilor PL/SQL trebuie să furnizeze o singură linie rezultat
(în caz contrar se semnalează eroare).

Exemplu:
--se afiseaza numele angajatului cu codul 100
SET SERVEROUTPUT ON – daca este setat deja nu mai este necesar
DECLARE
v_nume VARCHAR2(20);
BEGIN
SELECT nume
INTO v_nume
FROM angajati
WHERE id_angajat = 100;
DBMS_OUTPUT.PUT_LINE('NUMELE ANGAJATULUI ESTE:' || v_nume);
END;
/

3
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

3. Atributul %TYPE

Atribuie unei variabile tipul altei variabile sau tipul de date specific unei coloane din tabelă.
Contribuie la asigurarea independenței programelor față de baza de date.

Declararea unei variabile cu %TYPE:

variabila tabelă.nume_coloană%TYPE;
sau
variabila1 tip_dată;
variabila2 variabila1%TYPE;

Exemplu:
--afiseaza numele si prenumele angajatului cu codul 100.

Observaţie: Restricţia NOT NULL a unei coloane nu se aplică şi variabilei declarate prin
folosirea atributului %TYPE.

4. Variabile de mediu sau variabile de legătură ale aplicaţiilor gazdă (BIND VARIABLES)

 sunt variabile de legătură cu aplicaţia în care rulează motorul PL/SQL;


 trebuie declarate în aplicaţie (în mediul gazdă) şi pot fi accesate şi modificate în cadrul
blocurilor PL/SQL;
 după terminarea execuţiei blocului PL/SQL, variabila rămâne în mediul gazdă cu valoarea
primită în urma rulării blocului (şi poate fi pasată altui bloc, realizând astfel transmiterea de
valori între blocurile PL/SQL);
 nu pot fi utilizate în cadrul procedurilor, funcţiilor sau pachetelor;
 se declară în afara blocului PL/SQL cu ajutorul cuvântului cheie VARIABLE:
VARIABLE g_numevariabilă TIP
 pentru declararea unei variabile host de tip NUMBER nu se specifică precizia şi scala;
 pentru utilizarea lor în cadrul unui bloc PL/SQL sau într-o frază SQL din afara blocului se
prefixează cu “:”

:host_variabila:=v_variabila;

 se afişează în afara blocului cu ajutorul comenzii PRINT (la afişare variabila nu se va prefixa
cu “:”)
PRINT g_numevariabilă

Exemple:

SET SERVEROUTPUT ON
VARIABLE n number

BEGIN

4
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

select count(*) into :n


from comenzi
where modalitate = 'online';
END;
/
PRINT n
-- afiseaza 32
begin
:n:=:n+5;
dbms_output.put_line('n='||:n);
-- afiseaza n=37
:n:=:n+5;
dbms_output.put_line('n='||:n);
-- afiseaza n=42
end;
/
PRINT n
-- afiseaza 42

Observaţie: Se poate auto-afişa variabila prin setarea AUTOPRINT ON (nu mai este necesară
folosirea comenzii PRINT după execuția blocului).

Exemplu:

--se selecteaza produsele si pretul acestora pentru acele produse care au pretul <
pretul mediu al produsului cu codul 3133 fara a utiliza un select imbricat

SET SERVEROUTPUT ON
SET AUTOPRINT ON
VARIABLE g_pret number

BEGIN
select avg(pret) into :g_pret
from rand_comenzi
where id_produs = 3133;
END;
/
select * from rand_comenzi where pret< :g_pret;

5. Variabile de substituţie

 de regulă, variabilele de substituţie sunt folosite pentru a transmite valori dinspre mediul
SQL*Plus spre comenzile SQL sau blocurile PL/SQL, în timp ce variabilele de legătură
(bind variables) sunt folosite pentru a transmite valori în sens invers sau pentru a transfera
valori între blocuri PL/SQL lansate succesiv (primul bloc setează variabila, următorul o
consultă);
 prin variabile de substituţie se pot transmite valori comenzilor SQL sau blocurilor PL/SQL
lansate (folosind "&" sau "&&");

5
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

 se pot invoca din comenzile SQL sau din blocurile PL/SQL prin "&nume_variabila" sau
"&&nume_variabila";
 sunt locale sesiunii SQL în care au fost declarate;
 în mediul SQL variabilele de substituţie pot fi uşor citite prin introducerea de valori de la
tastatură (utilizând ACCEPT), se pot defini (cu DEFINE) sau afişa pe ecran (cu PROMPT);

Exemple:

--se afiseaza numarul de comenzi ale angajatului al carui cod este introdus de
utilizator prin intermediul variabilei de substitutie &id_angajat
DECLARE
v_nr_comenzi number(2);
BEGIN
select count(id_comanda) into v_nr_comenzi from comenzi
where id_angajat=&id_angajat; --ex. id_angajat = 160
dbms_output.put_line('Angajatul are: '|| v_nr_comenzi||' comenzi');
END;
/

Observaţie: Într-un bloc PL/SQL se pot utiliza toate tipurile de variabile, respectând însă
caracteristicile şi regulile de utilizare ale acestora. În exemplul următor se utilizează
atât variabila de substituţie s_nume definită şi iniţializată prin comanda DEFINE,
cât şi variabila de legătură g_salariul, dar şi variabila locală v_prenume de acelaşi
tip cu coloana nume din tabela Angajati. Variabila de substituție care conține un șir
de caractere va fi folosită cu apostrof drept în atribuiri sau comparații, spre exemplu
nume:='&v_nume'.

-- se afiseaza salariul si prenumele angajatului cu numele Abel


SET SERVEROUTPUT ON
VARIABLE g_salariul number
DEFINE s_nume=Abel

DECLARE
v_prenume angajati.prenume%type;
BEGIN
select prenume,salariul into v_prenume, :g_salariul
from angajati where nume='&s_nume';
DBMS_OUTPUT.PUT_LINE ('Prenumele angajatului este: '||v_prenume);
END;
/

print g_salariul

6
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

INTERACŢIUNEA CU SERVERUL ORACLE PRIN COMENZI SQL

Interacţiunea se realizează prin intermediul comenzilor LDD (Limbajul de Descriere a Datelor),


LCD (Limbajul de Control al Datelor), LMD (Limbajul de Manipulare a Datelor), LPT
(Limbajul pentru Procesarea Tranzacțiilor) astfel:

 PL/SQL nu suportă comenzi LDD sau LCD în cadrul unui bloc. Pentru executarea acestor
comenzi se utilizează comanda EXECUTE IMMEDIATE:
Comenzi DDL/DCL Executie
CREATE, ALTER, DROP EXECUTE IMMEDIATE 'CREATE
GRANT, REVOKE TABLE.... '

Se poate folosi și pachetul DBMS_SQL pentru comenzi LDD și LCD. Acest pachet, precum și
EXECUTE IMMEDIATE pot fi folosite și pentru alte instrucțiuni SQL care conțin instrucțiuni
ce se pot modifica în timpul execuției. Spre exemplu, putem construi o procedură care folosește
o interogare a cărei clauze nu sunt cunoscute decât în momentul execuției (spre exemplu, pentru
căutare dinamică în funcție de criteriile selectate de utilizator).

 PL/SQL suportă toate comenzile din limbajul de manipulare a datelor (LMD) şi din cel de
control al tranzacţiilor (LPT). Un bloc PL/SQL nu e o tranzacţie. Comenzile Commit/
Rollback/ Savepoint sunt independente de bloc dar pot să apară în interiorul său.

Comenzi DML/TPL Executie


SELECT, INSERT, UPDATE, Se executa normal in cadrul blocului
DELETE, MERGE

COMMIT, ROLLBACK, SAVEPOINT Pot apare în bloc dar au efect asupra


tuturor tranzacţiilor din interiorul şi din
afara acestuia.

Exemple:
Se creează tabela PROD în cadrul unui bloc PL/SQL:

SET SERVEROUTPUT ON
--comenzi LDD
begin
--execute immediate 'DROP table prod';
execute immediate 'CREATE table prod AS SELECT * FROM produse where 1=2';
end;
/
Se adaugă în tabela PROD înregistrări din tabela produse:

--comenzi LMD
--comenzi LMD
declare
v_codp produse.id_produs%type;
7
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

v_denp produse.denumire_produs%type;
v_cat produse.categorie%type;
v_des produse.descriere%type;
begin
SELECT id_produs, denumire_produs, categorie, descriere INTO v_codp, v_denp,
v_cat, v_des
FROM produse where id_produs=3133;
INSERT INTO prod (id_produs, denumire_produs, categorie, descriere) VALUES
(v_codp, v_denp, v_cat, v_des);
DBMS_OUTPUT.PUT_LINE ('S-a adaugat in tabela prod produsul: '||v_codp||' '||
v_denp||' '||v_cat);
end;
/
select * from prod;

Pentru o mai mare flexibilitate se poate declara o variabilă de tip şir de caractere care să
primească comanda LDD care va fi executată prin Execute Immediate:

Exemple:
Se creează tabela EMP_SAL prin intermediul unei variabile de tip VARCHAR2. La creare, în
tabela EMP_SAL se va adăuga o nouă înregistrare.

SET SERVEROUTPUT ON
VARIABLE G_EID NUMBER
DECLARE
V_SIR VARCHAR2(200);
BEGIN
:G_EID:=110;
V_SIR:='CREATE table emp_sal AS SELECT id_angajat, nume, prenume, salariul
FROM angajati where id_angajat='||:G_EID;
DBMS_OUTPUT.PUT_LINE (V_SIR);
EXECUTE IMMEDIATE V_SIR;
END;
/
select * from emp_sal;

Se adaugă o nouă coloană STOC în tabela PROD:


DECLARE
V_SIR VARCHAR2(200);
BEGIN
V_SIR:='ALTER TABLE PROD ADD (STOC NUMBER (7))';
DBMS_OUTPUT.PUT_LINE (V_SIR);
EXECUTE IMMEDIATE V_SIR;
END;
/
select * from PROD;

8
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

Manipularea datelor in PL/SQL se face prin instrucţiunile LMD (INSERT, UPDATE, DELETE)
care pot fi lansate fără restricţii în PL/SQL.

Exemple:

 Comanda INSERT
Se adaugă o nouă înregistrare în tabela EMP_SAL:

BEGIN
INSERT INTO emp_sal (id_angajat, nume, prenume, salariul)
VALUES (200, 'Pop', 'Marian', 7500);
END;
/
select * from emp_sal;

Se adaugă o nouă înregistrare în tabela produse prin introducerea valorilor cu ajutorul


variabilelor de substituţie:

BEGIN
INSERT INTO prod (id_produs, denumire_produs, categorie, stoc)
VALUES (&id, '&denumire', '&categorie', &stoc);
END;
/
select * from prod;

 Comanda UPDATE

Se mărește cu x procente salariul angajaților din tabela EMP_SAL care au în prezent salariul
mai mic decât o anumită valoare:
DECLARE
v_procent number:=0.1;
v_prag angajati.salariul%type:=10000;
BEGIN
UPDATE emp_sal
SET salariul=salariul*(1+v_procent)
WHERE salariul<v_prag;
END;
/
select * from emp_sal;

Se realizează o aprovizionare în cadrul depozitului prin care se măresc stocurile tuturor


produselor cu 100 bucăți (coloana STOC a fost anterior adăugată):
BEGIN
UPDATE prod
SET stoc=nvl(stoc,0)+100;
END;
/
select * from prod;

9
Facultatea de Cibernetică, Statistică şi Informatică Economică
SGBD Oracle – seminarul 2

În urma comenzilor realizate de clienţi, monitoarele de tipul LCD sunt vândute, se deci scade
din stocul existent un număr de monitoare introdus de la tastatură:

BEGIN
UPDATE prod
SET stoc=stoc-&nr_buc_vandute
WHERE lower(denumire_produs) like 'monitor lcd%';
COMMIT;
END;
/
select * from produse;

Atenţie! În acest caz utilizarea comenzii COMMIT va finaliza atât tranzacţia curentă cât şi
tranzacţiile executate anterior.

 Comanda DELETE

Se şterge angajatul cu numele Pop din tabela emp_sal:


DECLARE
BEGIN
DELETE FROM emp_sal WHERE initcap(nume) like 'Pop%';
ROLLBACK;
END;
/
select * from emp_sal;

10

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