Sunteți pe pagina 1din 122

Claudiu Lefter

Florin Ostafi

Baze de date
- ndrumar de laborator -

Sintaxa de baz a instruciunilor SQL.


Restricionarea i sortarea datelor
obinute n urma interogrii unei baze de date
Obiective

Cunoaterea capabilitilor instruciunilor SELECT


Executarea unor instruciuni SELECT de baz
Cunoaterea diferenelor dintre instruciunile SQL i comenzile SQL*Plus
Limitarea numrului nregistrrilor returnate de o interogare
Sortarea nregistrrilor returnate de o interogare

Introducere
SQL (Structured Query Language) este unul dintre limbajele relaionale de cereri care formeaz
nucleul multor sisteme de gestiune a bazelor de date. El a fost dezvoltat pentru sistemul de gestiune
al bazelor de date System R de cercettori din cadrul IBM Research Laboratory, San Jose-California
la sfritul anilor 70. SQL a fost standardizat i a devenit limbajul de referin pentru bazele de
date relaionale.
SQL este un limbaj de comenzi pentru comunicarea cu serverul Oracle din orice aplicaie. Cnd se
introduce o instruciune SQL, aceasta este stocat ntr-o zon de memorie numit buffer-ul SQL i
ea va rmne n buffer pn n momentul introducerii unei noi instruciuni.
SQL*Plus este un instrument Oracle care recunoate i trimite instruciuni SQL la server pentru
execuie i conine propriul limbaj de comenzi.
Instruciuni SQL
Buffer
SQL*Plus

Instruciuni SQL

SERVER

Rezultatele interogrii

Comenzi SQL*Plus
Raport
formatat

Caracteristicile limbajului SQL:

poate fi folosit de o gam larg de utilizatori, inclusiv de cei ce nu sunt programatori;


este un limbaj neprocedural;
reduce timpul necesar pentru crearea si ntreinerea sistemelor.

Caracteristicile limbajului SQL*Plus:

accept fiiere de instruciuni SQL;


furnizeaz un editor n mod linie pentru modificarea instruciunilor SQL;
controleaz setrile de mediu;
formateaz rezultatele interogrilor sub form de rapoarte;
acceseaz baze de date locale si la distan.
1

Urmtorul tabel cuprinde cteva elemente de comparaie ntre SQL i SQL*Plus.


SQL

SQL*Plus

Este un limbaj pentru comunicarea cu serverul Oracle


pentru accesarea datelor
Este bazat pe standardul ANSI SQL

Recunoate instruciuni SQL i le trimite la server


Este o interfa proprietate Oracle pentru executarea
instruciunilor SQL
Nu permite manipularea valorilor n baze de date
Este permis o comand pe linie i nu este memorat n
bufferul SQL
Folosete caracterul (-) pentru continuarea unei comenzi
dac aceasta nu ncape pe o linie
Nu are nevoie de caractere de terminare. Se execut
imediat
Pot fi abreviate
Folosete comenzi pentru formatri

Manipuleaz date i definiii de tabele n baze de date


O instruciune se stocheaz in bufferul SQL pe una sau
mai multe linii
Nu are caracter de continuare
Folosete un caracter de terminare pentru executarea
imediat a comenzii
Nu pot fi abreviate
Folosete funcii pentru anumite formatri

Mediul SQL*Plus ofer numeroase faciliti, permind:

executarea instruciunilor SQL pentru extragerea, modificarea, adugarea i tergerea datelor


din baza de date;
formatarea, efectuarea de calcule, stocarea i listarea rezultatele interogrilor sub form de
rapoarte;
crearea de fiiere de script pentru stocarea instruciunilor SQL.

Comenzile SQL*Plus se mpart n urmtoarele mari categorii:


Categorie

Scop

Mediu
Formatare
Manipulri de fiiere
Execuie
Editare
Interaciune

Afecteaz comportamentul general al instruciunilor SQL pentru sesiunea respectiv


Formateaz rezultatele interogrii
Salveaz, ncarc i ruleaz fiiere de script
Trimite instruciuni SQL din bufferul SQL la serverul Oracle
Modific instruciunea SQL aflat n buffer
Permite crearea i pasarea variabilelor ctre instruciuni SQL, afiarea variabilelor i listarea
mesajelor pe ecran
Diferite comenzi pentru conectarea la baza de date, manipularea mediului SQL*Plus i afiarea
coloanelor

Diverse

Modul de apel al SQL*Plus depinde de tipul sistemului de operare sau a mediului Windows utilizat.
Pentru conectarea n mediul Windows NT trebuie urmai urmtorii pai:
1. Start -> Programs -> Oracle-OraHome92 -> Application Development -> SQL Plus;
2. Se completeaz: username, parola i numele bazei de date.
Pentru conectarea ntr-un mediu de tip linie de comand se lanseaz urmtoarea comand:
Sqlplus [username[/password[@database]]]
unde: username = numele utilizatorului din baza de date;
password = parola de conectare la baza de date;
@database = irul de conectare la baza de date (numele bazei de date).
Not: Din motive de securitate se recomand introducerea numelui de utilizator i a numelui bazei
de date, urmnd ca apoi, la promptul Password, s se introduce parola.

Sintaxa de baz a instruciunilor SQL


Instruciunea SELECT
Pentru extragerea informaiilor din baza de date se utilizeaz instruciunea SELECT. Cu ajutorul
acestei comenzi se pot realiza urmtoarele operaii asupra datelor din baza de date:

SELECIE (SELECTION): evaluarea rezultatului interogrii va lua n calcul numai anumite


linii din tabelele de date, pe baza unor criterii de selecie.
PROIECIE (PROJECTION): rezultatul interogrii va conine numai anumite coloane din
tabele de date.
JONCIUNE (JOIN) : utilizat pentru a combina date aflate n tabele diferite prin crearea unei
legturi ntre coloanele corespunztoare.

Sintaxa de baz a comenzii SELECT este urmtoarea:


SELECT [ DISTINCT ] {*, coloana [alias] , }
FROM tabel;

n cea mai simpl form instruciunea SELECT conine:

o clauz SELECT care specific coloanele ce vor fi afiate;


o clauz FROM care specific tabelele ce conin coloanele menionate n clauza SELECT.

Din punct de vedere sintactic:


SELECT
este o list de una sau mai multe coloane;
DISTINCT
suprim duplicatele;
*
selecteaz toate coloanele;
coloana
numele coloanei;
alias
redenumete coloana selectat;
FROM tabel
specifica tabelul ce conine coloanele din clauza SELECT.
Indicaii privind scrierea instruciunilor SQL
Pentru a construi instruciuni valide, uor de citit i de editat trebuie avute n vedere urmtoarele
reguli:

n general instruciunile SQL pot fi scrise cu litere mari sau mici;


instruciunile SQL pot fi introduse pe una sau mai multe linii;
cuvintele cheie nu pot fi abreviate sau desprite n linii diferite;
de obicei clauzele sunt plasate pe linii separate pentru creterea lizibilitii textului;
este de preferat ca toate cuvintele cheie s fie introduse cu majuscule, iar toate celelalte cuvinte,
cum ar fi numele de tabele i coloane, s fie introduse cu litere mici;
n mediul SQL*Plus, o instruciune SQL este introdus la promt-ul SQL, iar urmtoarele linii
aparinnd instruciunii sunt numerotate. Acesta se numete buffer-ul SQL. Numai o singur
instruciune SQL poate exista n buffer la un moment de timp.

Not:
- un cuvnt cheie se refer la o clauz SQL, cum ar fi SELECT, FROM;
- o clauz reprezint o parte a unei instruciuni SQL (e.g. SELECT empno, ename);
- o instruciune este dat de o combinaie de una sau mai multe clauze (e.g. SELECT * FROM
emp).
3

Execuia instruciunilor SQL se poate face prin:

plasarea caracterului ; la sfritul ultimei clauze;


plasarea caracterului / la sfritul ultimei linii din buffer;
plasarea unui caracter slash / la prompt-ul SQL;
lansarea n SQL*Plus a comenzii RUN (la promt-ul SQL).

Selectarea tuturor coloanelor i liniilor


Dac se dorete afiarea tuturor coloanele cu date dintr-un tabel se folosete cuvntul cheie
SELECT mpreun cu un asterix (*) . n exemplul de mai jos, tabelul dept conine trei coloane
(DEPTNO, DNAME si LOC) i patru linii, cte o linie pentru fiecare departament.
SQL> SELECT *
2 FROM scott.dept;

DEPTNO
-----10
20
30
40

DNAME
----------ACCOUNTING
RESEARCH
SALES
OPERATIONS

LOC
-------NEW YORK
DALLAS
CHICACO
BOSTON

Acelai rezultat se poate obine i dac enumerm toate coloanele dup cuvntul cheie SELECT. De
exemplu, urmtoarea instruciune SQL afieaz toate coloanele i toate liniile din tabelul dept.
SQL> SELECT deptno, dname, loc
2 FROM scott.dept;

Selectarea unor anumite coloane


n cazul n care se dorete afiarea unor anumite coloane din tabel, se va specifica n clauza
SELECT numele acelor coloane, separate prin virgul (,). Ordinea n care coloanele selectate vor
fi afiate pe ecran este dat de ordinea n care au fost enumerate n clauza SELECT. De exemplu,
pentru a afia toate departamentele i oraele din tabelul scott.dept se va executa urmtoarea
instruciune SQL:
SQL> SELECT deptno, loc
2 FROM scott.dept;

DEPTNO
-----10
20
30
40

LOC
---------NEW YORK
DALLAS
CHICAGO
BOSTON

Afiarea rezultatului unei interogri respect urmtoarele convenii:


-

numele coloanelor de tip ir de caractere i dat calendaristic, precum i datele din tabel
asociate coloanelor respective sunt aliniate la stnga;
numele coloanelor de tip numeric i datele din coloanele respective sunt aliniate la dreapta;
numele unei coloane de tip dat calendaristic sau ir de caractere poate fi trunchiat, dar capul
de coloan de tip numeric nu poate fi trunchiat;
numele coloanelor sunt afiate implicit cu litere mari; coloanele pot fi redenumite cu ajutorul
unui alias.

Expresii aritmetice
n cazul n care se dorete modificarea modului de afiare a datelor, n sensul executrii unor
calcule sau crerii unor scenarii, se pot utiliza expresii aritmetice. Expresiile aritmetice pot conine
4

nume de coloane, constante numerice si operatori aritmetici (+, -, *, /). Aceti operatori pot fi
utilizai n orice clauz SQL, exceptnd clauza FROM.
n exemplul urmtor se dorete afiarea numelui (ename), salariului (sal) i a valorii sal+300
pentru fiecare angajat din tabelul scott.emp. Instruciunea SQL corespunztoare este:
SQL> SELECT ename, sal, sal+300
2 FROM scott.emp;

ENAME
-------KING
BLAKE
CLARK
JONES
MARTIN

SAL
-----5000
2850
2450
2975
1250

SAL+300
---------5300
3150
2750
3275
1550

Exemplul anterior utilizeaz operatorul + pentru a mri salariile cu 300 pentru toi angajaii i
afieaz o nou coloan SAL+300. De notat c SAL+300 nu este o coloan nou n tabelul
scott.emp. Implicit, denumirea noii coloane este dat de expresia aritmetic care a generat-o (n
acest caz SAL+300).
Not: SQL*Plus ignor spaiile prezente nainte i dup operatorii aritmetici.
Dac o expresie aritmetic conine mai mult de un operator, nmulirea i mprirea sunt evaluate
primele, apoi adunarea i scderea. Dac operatorii folosii ntr-o expresie sunt de aceeai prioritate,
evaluarea se va face de la stnga la dreapta. Folosirea parantezelor determin ca expresia dintre
paranteze sa fie evaluat prima.
Valoarea null
Dac o linie nu are date pentru o coloan particular, aceast valoare se numete null. Semnificaia
valori null este de dat nedisponibil, neatribuit, necunoscut sau inaplicabil. Valoarea null nu
este aceeai cu valoarea 0 (pentru date de tip numeric) sau (pentru datele de tip ir de caractere).
Coloanele de orice tip pot conine valoarea null, cu excepia celor care au fost definite la creare ca
fiind NOT NULL sau chei primare (PRIMARY KEY).
SQL> SELECT name, job, comm
2 FROM scott.emp;

ENAME
-----KING
BLAKE

TURNER

JOB
COMM
---------- -----PRESIDENT
MANAGER
SALESMAN

Se observ c n coloana COMM din tabelul scott.emp doar angajatul TURNER poate avea
comision, ceilali angajai nefiind ndreptii s primeasc comision.
Dac valoarea unei coloane ce apare ntr-o expresie aritmetic este null, rezultatul este null. Dup
cum se tie, o ncercare de mprire la zero genereaz o eroare. n cazul unei mpriri la o
valoarea null, rezultatul este null (necunoscut).
Definirea alias-urilor pentru coloane
La afiarea rezultatului unei interogri, SQL* Plus folosete numele coloanei ca i cap de tabel.
Deoarece n multe cazuri acest cap de tabel nu este sugestiv, se poate schimba numele coloanei
afiate folosind un alias de coloan. Alias-ul se specific n clauza SELECT, imediat dup numele
coloanei. Dac alias-ul conine spaii, caractere speciale ($ sau # - plasate la nceputul alias-ului)
sau dac au importan literele mari (mici) se va scrie alias-ul ntre ghilimele ( ).
5

SQL> SELECT ename AS name, sal salary


2 FROM scott.emp;

NAME
SALARY
---- -------

SQL> SELECT ename Name, sal*12 Annual Salary


2 FROM scott.emp;

Name
-----

Annual Salary
--------------

Primul exemplu afieaz numele i salariul lunar al tuturor angajailor. Cuvntul cheie opional AS
a fost folosit nainte de alias, rezultatul fiind acelai dac AS ar fi lipsit din clauza SELECT. De
notat c alias-urile name i salary au fost scrise cu litere mici, iar la afiare au aprut scrise cu
majuscule.
n cel de-al doilea exemplu se dorete afiarea numelor anagajailor i a salariilor anuale. Deoarece
alias-ul Annual Salary implic folosirea spaiului, alias-ul trebuie scris ntre ghilimele ( ).
Operatorul de concatenare ( || )
n cazul n care se dorete concatenarea unor coloane, a unor expresii aritmetice sau valori constante
pentru a crea expresii de tip ir de caractere se va utiliza operatorul de concatenare (||). Coloanele ce
apar de o parte i de alta a operatorului de concatenare sunt combinate pentru a forma o singur
coloan la afiare.
SQL> SELECT ename || job AS Employees
2 FROM scott.emp;

Employees
-------------KINGPRESIDENT
BLAKEMANAGER
CLARKMANAGER
JONESMANAGER
MARTINSALESMAN

n exemplul de mai sus, coloanele ENAME i JOB sunt concatenate, iar coloanei rezultante i se
atribuie alias-ul Employees. Cuvntul cheie AS folosit naintea alias-ului mrete lizibilitatea
instruciunii SELECT.
iruri de caractere
Un literal este orice caracter, expresie sau numr inclus n lista SELECT care nu este un nume de
coloan sau alias. Un literal este afiat pentru fiecare linie returnat de interogare. Valorile literale
pentru datele calendaristice i caractere trebuie incluse ntre ( ).
SQL> SELECT ename || || is a || job
2 AS Employee Details
3 FROM scott.emp;

Employee Details
-------------------KING is a PRESIDENT
BLAKE is a MANAGER
CLARK is a MANAGER
JONES is a MANAGER
MARTIN is a SALESMAN

Exemplul de mai sus afieaz numele i ocupaia tuturor angajailor, numele coloanei fiind
Employee Details. Spaiile dintre ghilimelele simple din instruciunea SELECT au fost
introduse pentru mbuntirea lizibilitii ieirii.

Eliminarea rndurilor duplicat


In mod predefinit interogrile afieaz toate liniile, inclusiv cele duplicat.
SQL> SELECT deptno
2 FROM scott.emp;

DEPTNO
--------20
30
30
20
......

SQL*Plus va afia rezultatul interogrii fr a elimina rndurile duplicat. Exemplul de mai sus
afieaza toate departamentele din tabelul scott.emp.
Eliminarea duplicatelor se face folosind cuvntul cheie DISTINCT n clauza SELECT.
SQL> SELECT DISTINCT deptno
2 FROM scott.emp;

DEPTNO
--------10
20
30

n cazul n care se specific mai multe coloane dup clauza DISTINCT vor fi afectate toate
coloanele selectate, rezultatul reprezentnd o combinaie distinct a acestor coloane.
SQL> SELECT DISTINCT deptno, job
2 FROM scott.emp;

Comenzi PL*SQL
Afiarea structurii unui tabel
Se folosete comanda SQL*Plus DESC[RIBE] tablename, unde tablename este numele
unui tabel , al unei vederi sau este un sinonim accesibil utilizatorului.
SQL> DESCRIBE scott.dept

Name
--------DEPTNO
DNAME
LOC

Null?
--------NOT NULL

Type
--------NUMBER(2)
VARCHAR2(14)
VARCHAR2(13)

Tabelul de mai sus conine informaii privind structura tabelului scott.dept, numele coloanelor
fiind enumerate n coloana Name. Coloana Null? indic dac o coloan trebuie s conin date.
Valoarea NOT NULL semnific faptul c valoarea null nu este permis n acea coloan. Type
reprezint tipul de date al coloanei.
Tip de date

Descriere

NUMBER(p,s)

Valori numerice avnd un numr maxim de p cifre, unde s este numrul de cifre a prii
subunitare
ir de caractere de lungime variabil cu lungime maxim s
Date calendaristice ntre 1 ianuarie 4712 b.c. i 31 decembrie 9999 a.c.
ir de caractere de lungime fix s

VARCHAR2(s)
DATE
CHAR(s)

Comenzile de editare ale mediului SQL*Plus


Cteva comenzi SQL*Plus utile n gestiunea buffer-ului SQL sunt:

A[PPEND] text

- adaug text la sfritul liniei curente din buffer


7

C[HANGE] / old / new


C[HANGE] / text /
C[LEAR] BUFF[ER]
DEL
DEL n
DEL m n
I[NPUT]
I[NPUT] text
L[IST]
L[IST] n
L[IST] m n
n
n text
0 text

- schimb textul old cu cel new n linia curent


- terge text din linia curent din buffer
- terge toate liniile din bufferul SQL
- terge linia curent din buffer
- terge linia n din buffer
- terge din buffer toate liniile avnd numrul cuprins ntre m i n
- insereaz un numr nedefinit de linii
- insereaz o linie n buffer, coninutul liniei fiind dat de text
- listeaz toate liniile din bufferul SQL
- listeaz linia n din buffer
- listeaz liniile de la m la n din buffer
- linia n devine linia curent din buffer
- nlocuiete linia n din buffer cu text
- insereaz n buffer o linie naintea liniei 1

Not: La prompt-ul SQL se poate introduce doar o singur comand SQL*Plus, ce nu este stocat
n buffer. Pentru a continua o comand pe linia urmtoare se va plasa caracterul (-) la sfritul liniei.
Comenzi SQL*Plus pentru fiiere
SAVE filename
[REP[LACE]APP[END]]
GET filename
START filename
@ filename
ED[IT]
ED[IT] filename
SPO[OL] [filename]
OFF | OUT
EXIT

- salveaz coninutul buffer-ului SQL ntr-un fiier. Opiunea APPEND adaug la sfritul
fiierului, iar opiunea REPLACE suprascrie coninutul fiierului;
- coninutul fiierului filename este ncrcat n buffer-ul SQL (extensia implicit pentru
fiier este .sql);
- ruleaz fiierul script filename;
- are acelai efect ca n cazul utilizrii comenzii START;
- lanseaz editorul i salveaz coninutul buffer-ului n fiierul afiedt.buf;
- lanseaz editorul pentru editarea coninutului unui fiier salvat;
- stocheaz rezultatul unei interogri ntr-un fiier. OFF nchide fiierul. OUT nchide
fiierul i l trimite la imprimant sistem;
- ieire din SQL*Plus;

Restricionarea i sortarea datelor obinute n urma interogrii unei baze


de date
n urma interogrii unei baze de date poate apare necesitatea reducerii numrului de linii afiate sau
specificrii ordinii n care s fie afiate datele. Acest referat prezint regulile SQL folosite pentru
realizarea acestor aciuni, noiunile prezentate fiind nsoite de numeroase exemple.

Limitarea nregistrrilor folosind o selecie:


EMP
EMPNO
7839
7698
7782
7566

ENAME
KING
BLAKE
CLARK
JONES

JOB
PRESIDENT
MANAGER
MANAGER
MANAGER

DEPTNO
10
30
10
20

returneaz toi angajaii din


departamentul 10

EMP

EMPNO

ENAME

JOB

7839
7782
7934

KING
CLARK
MILLER

PRESIDENT
MANAGER
CLERK

DEPTNO
10
10
10

S presupunem, conform exemplului de mai sus, c se dorete afiarea tuturor angajailor din
departamentul 10 (prezint interes doar setul de linii care au valoarea 10 n coloana DEPTNO).
Aceast metod de restricionare reprezint baza clauzei WHERE n SQL.

Limitarea liniilor selectate


Se poate restriciona numrul de linii returnate de o interogare folosind clauze WHERE. O clauz
WHERE conine o condiie ce trebuie ndeplinit de fiecare linie din rezultat i urmeaz imediat dup
clauza FROM.
SELECT [DISTINCT] {*, coloana [alias], }
FROM tabel
[WHERE conditie];

unde:
WHERE
conditie

restricioneaz interogarea la liniile ce ndeplinesc condiia conditie.


reprezint condiia ce trebuie satisfcut de fiecare nregistrare ce
apare n rezultat; este compus din nume de coloane, expresii,
constante i operatori de comparaie.

Clauza WHERE poate compara valorile din coloane, valori literale, expresii aritmetice sau funcii,
fiind compus din trei elemente:
numele coloanei
operatorul de comparaie
nume de coloan, constant sau list de valori
Folosirea clauzei WHERE
SQL> SELECT ename, job, deptno
2 FROM scott.emp
3 WHERE job=CLERK;

ENAME
------JAMES
SMITH
ADAMS
MILLER

JOB
------CLERK
CLERK
CLERK
CLERK

DEPTNO
------30
20
20
10

Exemplul anterior afieaz toi angajaii care au funcia CLERK.


iruri de caractere i date calendaristice
irurile de caractere i datele calendaristice utilizate n clauza WHERE trebuie incluse ntre
apostrofuri ( ). Toate cutrile la nivel de caracter sunt case-sensitive (i.e. se face distincie ntre
litere mici i majuscule). Datele calendaristice sunt memorate de Oracle n formatul secol, an, luna,
zi, ore, minute i secunde. Afiarea implicit a datei este DD-MON-YY.
Not: valorile numerice nu trebuie incluse ntre apostrofuri.
Operatori de comparaie
Operatorii de comparaie (=, >, >=, <, <=, <>) sunt folosii n condiii care compar dou expresii.
Utilizarea lor n clauza WHERE respect urmtorul format:
WHERE expresie operator valoare

Exemple:
WHERE hiredate=01-JAN-95
9

WHERE sal>=1500
WHERE ename=SMITH
Ali operatori de comparaie ce pot fi utilizai ntr-o clauz WHERE sunt prezentai n tabelul
urmtor:
Operator

Semnificaie

BETWEEN AND
IN (list)
LIKE
IS NULL

ntre dou valori (inclusiv)


Potrivete orice valoare din list
Potrivete un tip de caracter
Este valoare null

Operatorul BETWEEN
Operatorul BETWEEN se utilizeaz pentru selectarea valorilor dintr-un interval.
SQL> SELECT ename, sal
2 FROM
scott.emp
3 WHERE sal BETWEEN 1000 AND 1500;
Limita
inferioar

ENAME
------MARTIN
TURNER
WARD
ADAMS
MILLER

Limita
superioar

SAL
-----1250
1500
1250
1100
1300

Operatorul IN
Operatorul IN este utilizat pentru cutare ntr-o list de valori. El poate fi utilizat cu orice tip de
dat.
SQL> SELECT empno, ename, sal, mgr
2 FROM scott.emp
3 WHERE mgr IN (7902, 7566, 7788);

EMPNO
-----7902
7369
7788
7876

ENAME
------FORD
SMITH
SCOTT
ADAMS

SAL
-----3000
800
3000
1100

MGR
----7566
7902
7566
7788

Urmtorul exemplu returneaz cte o linie din tabelul scott.emp pentru fiecare angajat al crui
nume este inclus n lista de nume din clauza WHERE.
SQL> SELECT empno, ename, mgr, deptno
2 FROM scott.emp
3 WHERE ename IN (FORD, ALLEN);

Not: dac n list sunt folosite caractere sau date calendaristice, acestea trebuie incluse ntre
apostrofuri ( ).
Operatorul LIKE
SQL> SELECT ename
2 FROM scott.emp
3 WHERE ename LIKE S%;

Nu ntotdeauna se cunoate valoarea exact pe baza creia se va efectua cutarea. Instruciunea


SELECT permite selectarea liniilor care corespund unui tipar de caractere cu ajutorul operatorului
LIKE. Operaia de potrivire dup un tipar de caractere este referit drept cutare cu caractere
wildcard. Pentru construirea irurilor de cutare pot fi utilizate dou simboluri:

10

Simbol

Descriere

%
_ (underscore)

Reprezint orice secven de caractere


Reprezint un singur caracter

Instruciunea SELECT de mai sus returneaz numele angajailor din tabelul scott.emp al cror
nume ncepe cu S. Numele care ncep cu s nu vor fi returnate.
n anumite cazuri, operatorul LIKE poate fi utilizat n locul operatorului BETWEEN. Urmtorul
exemplu afieaz numele i data angajrii tuturor angajailor a cror angajare s-a fcut ntre ianuarie
1981 i decembrie 1981.
SQL> SELECT ename, hiredate
2 FROM scott.emp
3 WHERE hiredate LIKE %81;

Pot fi combinate diferite tipuri de potriviri pe caracter


ENAME
----JAMES
WARD

SQL> SELECT ename


2 FROM scott.emp
3 WHERE ename LIKE _A%;

Dac se dorete cutarea caracterelor % sau _ se va folosi opiunea ESCAPE, care precizeaz
de fapt caracterul care va fi utilizat drept Escape.
Urmtoarea instruciune SELECT afieaz numele tuturor angajailor al cror nume conine
secvena de caractere A_S.
SQL> SELECT ename
2 FROM scott.emp
3 WHERE ename LIKE %A\_S ESCAPE \;

Operatorul IS NULL
Operatorul IS NULL este utilizat pentru cutarea valorilor null. Deoarece valoarea null are
semnificaia unei valori indisponibile, neatribuite, necunoscute sau neaplicabile ea nu poate apare n
cadrul unei operaii de comparaie, deoarece ar conduce la un rezultat null. De exemplu, pentru a
afia numele, funcia i comisionul tuturor angajailor care nu au dreptul la comision se va folosi
urmtoarea instruciune SELECT:
SQL> SELECT ename, job, comm
2 FROM scott.emp
3 WHERE comm IS NULL;

ENAME
-----KING
BLAKE
CLARK

JOB
--------PRESIDENT
MANAGER
MANAGER

COMM
-----

Operatori logici (AND, OR, NOT)


Un operator logic combin dou componente de tip condiie pentru a produce un singur rezultat
bazat pe acestea sau inverseaz rezultatul unei singure condiii. n SQL sunt disponibili trei
operatori logici: AND, OR i NOT.
Operator

Comentariu

AND
OR
NOT

Returneaz TRUE dac ambele componente ale condiiei sunt adevrate


Returneaz TRUE dac una din componentele condiiei este adevrat
Returneaz TRUE dac respectiva condiie este fals
11

Folosirea operatorului AND


SQL> SELECT empno, ename, job, sal
2 FROM scott.emp
3 WHERE sal>=1100
4 AND job=CLERK;

EMPNO
----7876
7934

ENAME
------ADAMS
MILLER

JOB
-----CLERK
CLERK

SAL
-----1100
1300

n exemplul de mai sus ambele condiii trebuie s fie adevrate pentru a fi selectat o nregistrare.
De aceea, un angajat care are funcia CLERK i ctig mai mult de $1100 va fi selectat.
Not: - toate cutarile de tip caracter sunt case-sensitive.
- irurile de caracter trebuie incluse ntre apostrofuri ( ).
Folosirea operatorului OR
SQL> SELECT empno, ename, job, sal
2 FROM scott.emp
3 WHERE sal>=1100
4 OR job=CLERK;

EMPNO
-----7839
7698
7782
7566
7654

ENAME
-----KING
BLAKE
CLARK
JONES
MARTIN

JOB
---------PRESIDENT
MANAGER
MANAGER
MANAGER
SALESMAN

SAL
-----5000
2850
2450
2975
1250

n exemplul de mai sus, vor fi selectate nregistrrile care ndeplinesc cel puin o condiie: fie
sal>=1100, fie job=CLERK.
Folosirea operatorului NOT
SQL> SELECT ename, job
2 FROM scott.emp
3 WHERE job NOT IN (CLERK, MANAGER, ANALYST);

ENAME
------KING
MARTIN
ALLEN
TURNER
WARD

JOB
--------PRESIDENT
SALESMAN
SALESMAN
SALESMAN
SALESMAN

n exemplul de mai sus este afiat numele i funcia tuturor angajailor a cror funcie nu este
CLERK, MANAGER sau ANALYST.
Not: operatorul NOT poate fi combinat i cu ali operatori SQL, cum ar fi BETWEEN, LIKE i IS
NULL.
WHERE job NOT IN (CLERK, ANALYST)
WHERE sal NOT BETWEEN 1000 AND 1500
WHERE comm IS NOT NULL
Precedena operatorilor
Prioritate

Operator

1 maxim
2
3
4 minim

Toi operatorii de comparaie


NOT
AND
OR

Not: aceste reguli pot fi nclcate folosind paranteze.

12

Clauza ORDER BY
Liniile returnate de o interogare sunt afiate ntr-o ordine oarecare. Pentru sortarea liniilor se
utilizeaz clauza ORDER BY, care, dac este folosit, trebuie s apar ultima n instruciunea
SELECT. Sortarea se poate face dupa o coloan, o expresie sau dup un alias de coloan.
Sintax:
SELECT expresie
FROM tabel
[WHERE conditie]
[ORDER BY {coloana, expresie} [ASC|DESC];

unde:
ORDER BY specific ordinea n care sunt afiate liniile.
ASC
ordoneaz liniile ascendent implicit.
DESC
ordoneaz liniile descendent.
Dac nu este folosit clauza ORDER BY ordinea sortrii este nedefinit i Serverul Oracle poate
afia liniile n ordine diferit pentru dou interogri identice.
SELECT-ul urmtor afieaz rezultatele interogrii ordonate descresctor dup coloana hiredate.
SQL> SELECT ename, job, deptno, hiredate
2 FROM scott.emp
3 ORDER BY hiredate DESC;

ENAME
------ADAMS
SCOTT
MILLER
JAMES
FORD
KING
MARTIN

JOB
DEPTNO
-------- ------CLERK
20
ANALYST
20
CLERK
10
CLERK
30
ANALYST
20
PRESIDENT
10
SALESMAN
30

HIREDATE
--------12-JAN-83
09-DEC-82
23-JAN-82
03-DEC-81
03-DEC-81
17-NOV-81
28-SEP-81

Ordinea implicit a sortrii datelor este cea ascendent:

valorile numerice sunt afiate ncepnd cu cea mai mic valoare de exemplu 1- 999.
datele sunt afiate ncepnd cu cea mai recent de exemplu 01-JAN-92 naintea lui 01-JAN95.
valorile tip caracter sunt afiate n ordine alfabetic de exemplu A naintea lui Z.
valorile null sunt afiate ultimele n cazul sortrilor ascendente si primele pentru cele
descendente.

Urmtoarea instruciune SELECT ordoneaz liniile dup aliasul coloanei sal*12 (de tip expresie
aritmetic).
SQL> SELECT empno, ename, sal*12 annsal
2 FROM scott.emp
3 ORDER BY annsal;

EMPNO
-----7369
7900
7876
7654
7521
7934
7844

ENAME
------SMITH
JAMES
ADAMS
MARTIN
WARD
MILLER
TURNER

ANNSAL
------9600
11400
13200
15000
15000
15600
18000

n urmtorul exemplu liniile sunt sortate dup coloanele deptno i sal, iar liniile avnd aceeai
valoare pentru deptno fiind sortate descendent dup sal.
13

SQL> SELECT ename, deptno, sal


2 FROM scott.emp
3 ORDER BY deptno, sal DESC;

ENAME
------KING
CLARK
MILLER
FORD

DEPTNO
--------10
10
10
20

SAL
-----5000
2450
1300
3000

Not: se poate face sortare i dup o coloan care nu este n lista clauzei SELECT.

Probleme
1. Afiai structura tabelului scott.dept i coninutul lui.
2. Afiai structura tabelului scott.emp. Creai o interogare care s afieze numele, funcia, data
angajrii i numrul angajatului pentru fiecare angajat, numrul angajatului aprnd pe prima
poziie. Salvai instruciunea ntr-un fisier p2.sql.
3. Rulai interogarea din fiierul p2.sql.
4. Afiai funciile (coloana job) din tabelul scott.emp, eliminnd duplicatele.
5. ncrcai fiierul p2.sql n buffer-ul SQL. Modificai instruciunea SQL din buffer astfel nct s
redenumii numele coloanelor cu Emp#, Employee, Job, Hire Date i apoi rulai interogarea.
6. Creai o interogare care s afieze, pe o singur coloan, numele fiecrui angajat concatenat cu
funcia sa, separate de virgul i spaiu. Denumii coloana Employee and Title.
7. Afiai datele din tabelul scott.emp, concatennd toate coloanele. Separai coloanele cu o
virgul i denumii coloana THE_OUTPUT.
Rezultatul interogrii este de forma:

8.
9.
10.
11.
12.
13.
14.
15.
16.
17.

THE_OUTPUT
-------------------------------------------7369,SMITH,CLERK,7902,17-DEC-80,800,,20
7499,ALLEN,SALESMAN,7698,20-FEB-81,1600,300,30
7521,WARD,SALESMAN,7698,22-FEB-81,1250,500,30

Afiai numele i salariul angajailor din tabelul scott.emp care ctig mai mult de $2850.
Salvai instruciunea SQL n fiierul p8.sql i apoi rulai-l.
Modificai p8.sql astfel nct s afiai numele i salariul tuturor angajailor ale cror salarii nu
intr n intervalul $1500 - $2850. Salvai instruciunea n fiierul p9.sql i apoi rulai din nou
interogarea.
Afiai numele i numerele de departament ale angajailor care lucreaz n departamentele 10,
respectiv 30, ordonai alfabetic dup nume.
Modificai fiierul p9.sql i listai numele i salariul angajailor care ctig mai mult de $1500
i lucreaz n departamentul 10 sau 30. Redenumii coloanele din rezultat Angajat i Salar
Lunar. Salvai modificrile n fiierul p11.sql i apoi rulai-l.
Afiai numele i funcia pentru angajaii care nu au manager.
Afiai numele, salariul i comisionul pentru toi angajaii care au comision. Sortai datele n
ordine descendent dup salariu i comision.
Afiai numele angajailor care conin 2 caractere L consecutive n numele lor i ndeplinesc
urmtoarea condiie: lucreaz n departamentul 30 sau au manager cu marca 7782.
Modificai p11.sql i afiai numele, salariul i comisionul pentru toi angajaii care au
comisionul mai mare dect salariul mrit cu 10%. Salvai modificrile n fiierul p15.sql i apoi
rulai-l.
Afiai numele, funcia i salariul angajailor ce au funcia Clerk sau Analyst i al cror salariu
nu este de $1000, $3000 sau $5000.
Afiai numele, funcia i data angajrii persoanelor angajate ntre 10 februarie 1981 i 1 mai
1981. Ordonai nregistrrile returnate de interogare cresctor dup data angajrii.
14

Metode de selecie a datelor din tabele multiple.


Gruparea rezultatelor unei interogri
Metode de selecie a datelor din tabele multiple
Obiective
Dup parcurgerea acestei seciuni, studentul va avea cunotinele necesare:

scrierii unei expresii SELECT pentru a accesa date din mai multe tabele folosind legturi
(jonciuni) de egalitate si nonegalitate;
vizualizrii datelor care nu ndeplinesc o condiie de jonciune folosind condiii de jonciune
extern;
efecturii unei jonciuni ntre un tabel i el nsui;
EMP
EMPNO
7893
7698

7934

DEPT
ENAME
KING
BLAKE

MILLER

EMPNO

DEPTNO
10
30

10

DEPTNO
7893 10
7698 30
7782 10
7566 20
7654 30
7499 30

14 rows selected

DEPTNO

10
20
30
40

DNAME
ACCOUNTING
RESEARCH
SALES
OPERATIONS

LOC
NEW YORK
DALLAS
CHICAGO
BOSTON

LOC
NEW YORK
CHICAGO
NEW YORK
DALLAS
CHICAGO
CHICAGO

Exist situaii cnd trebuie s accesm date din mai multe tabele. n exemplul de mai sus, rezultatul
afiat conine date din dou tabele separate.

atributul EMPNO exist n tabelul EMP;


atributul DEPTNO exist n ambele tabele EMP i DEPT;
atributul LOC exist n tabelul DEPT.

Pentru a obine rezultatul dorit trebuie realizat o legtur ntre tabelele EMP i DEPT.

Definirea jonciunilor
Vom folosi o condiie de jonciune ori de cte ori trebuie s accesm date din mai multe tablele din
baza de date. Se poate crea o coresponden ntre liniile unui tabel i liniile altui tabel pe baza
valorilor comune existente n coloanele corespondente, care sunt de obicei chei primare i strine.
Pentru afiarea datelor din dou sau mai multe tabele aflate n relaie se va scrie o simpl condiie
de jonciune n clauza WHERE:
SELECT tabel1.coloana1, tabel1.coloana2, tabel2.coloana3
FROM tabel1, tabel2
WHERE tabel1.coloana1 = tabel2.coloana3;

unde:
tabel.coloana
tabel1.coloana1 =
tabel2.coloana2

indic tabelul i coloana de unde este extras data


este condiia care leag
cele dou tabele

Observaii:
n momentul scrierii unei expresii SELECT care conine o condiie de jonciune, este indicat ca
numele coloanelor s fie precedate de numele tabelului de care aparin; n acest fel este mrit
claritatea codului SQL i se mbuntete accesul la baza de date.
dac un acelai nume de coloan apare n mai multe tabele, numele coloanei trebuie prefixat cu
numele tabelului de care aparine.
pentru a realiza o legtur ntre n tabele este nevoie de minim n-1 condiii de jonciune (e.g.
pentru a lega 4 tabele sunt necesare 3 jonciuni). Aceast regula s-ar putea s nu se aplice dac
tabelul are o cheie primar format din mai multe atribute i astfel este necesar mai mult de o
coloan pentru a identifica n mod unic fiecare linie.
Produsul Cartezian
Atunci cnd o condiie de jonciune este invalid sau complet omis, rezultatul este un produs
cartezian n care vor fi afiate toate combinaiile de linii din tabelele implicate. Un produs cartezian
tinde s genereze un numr mare de linii, iar rezultatul su este n general nefolositor. De aceea
trebuie inclus ntotdeauna o condiie de jonciune valid n clauza WHERE, cu excepia cazului
cnd se dorete n mod explicit combinarea tuturor liniilor din tabele implicate n relaie.
Exemplul urmtor afieaz numele fiecrui angajat i numele departamentului n care lucreaz din
tabelele EMP i DEPT. Deoarece nu a fost specificat clauza WHERE, toate liniile (14) din tabelul
EMP sunt combinate cu toate liniile (4) din tabelul DEPT, genernd astfel 56 de linii n tabelul
rezultat.
SQL> SELECT emp.ename, dept.dname
2 FROM emp, dept;

ENAME
DNAME
---------------KING
ACCOUNTING
BLAKE
ACCOUNTING
...
KING
RESEARCH
BLAKE
RESEARCH
...
56 rows selected.

Tipuri de condiii de jonciune


Principalele tipuri de condiii de jonciune sunt:
1. echi-jonciune;
2. non-echi-jonciune.
Pe lng acestea mai exist i alte tipuri de condiii de jonciune:
3. jonciune extern;
4. jonciune ntre un tabel i el nsui.
5.
1. Echi-jonciuni
Pentru a determina numele departamentului unui angajat trebuie comparat valoarea din coloana
DEPTNO din tabelul EMP cu valorile DEPTNO din tabelul DEPT. Legtura astfel creat ntre
tabelele EMP i DEPT este o echi-jonciune - valorile din coloana DEPTNO din ambele tabele
trebuie s coincid.

EMP
EMPNO ENAME
7839 KING
7698 BLAKE
7782 CLARK
7566 JONES
7654 MARTIN
7499 ALLEN
7844 TURNER
7900 JAMES
7521 WARD
7902 FORD
7369 SMITH
...
14 rows selected.

DEPT
DEPTNO
10
30
10
20
30
30
30
30
30
20
20

Cheie strin

DEPTNO DNAME
10 ACCOUNTING
30 SALES
10 ACCOUNTING
20 RESEARCH
30 SALES
30 SALES
30 SALES
30 SALES
30 SALES
20 RESEARCH
20 RESEARCH
...
14 rows selected.

LOC
NEW YORK
CHICAGO
NEW YORK
DALLAS
CHICAGO
CHICAGO
CHICAGO
CHICAGO
CHICAGO
DALLAS
DALLAS

Cheie primar

EMPNO ENAME DEPTNO DEPTNO


SQL> SELECT emp.empno, emp.ename,
----- ----- ------ -----2
emp.deptno, dept.deptno, dept.loc 7839 KING
10
10
3 FROM emp, dept
7698 BLAKE
30
30
4 WHERE emp.deptno=dept.deptno;
7782 CLARK
10
10
7566 JONES
20
20

LOC
------NEW YORK
CHICAGO
NEW YORK
DALLAS

14 rows selected.

n exemplul de mai sus:


Clauza SELECT specific numele coloanelor ce vor fi afiate
- numele i numrul angajatului i numrul departamentului, care sunt coloane n tabelul EMP;
- numrul, numele i locaia departamentului sunt coloane n tabelul DEPT.
Clauza FROM specific cele 2 tabele ce conin informaiile utile: tabelul EMP i tabelul DEPT.
Clauza WHERE specific modul n care se va realiza legtura ntre tabele.
Suplimentar condiiei de jonciune, clauza WHERE poate conine i alte criterii necesare operaiei de
selecie a datelor. De exemplu, pentru a afia codul angajatului KING, numele, numrul i locaia
departamentului este nevoie de o condiie suplimentar n clauza WHERE.
SQL> SELECT emp.empno, emp.ename,
2
dept.deptno, dept.loc
3 FROM emp, dept
4 WHERE emp.deptno= dept.deptno
5 AND
INITCAP(emp.ename) = 'King' ;

EMPNO
-----7839

ENAME
-----KING

DEPTNO
------10

LOC
-------NEW YORK

Alias-uri de tabele
Calificarea coloanelor cu ajutorul numelui tabelului poate consuma mult timp, mai ales n cazul n
care numele tabelului este un ir lung. Pentru simplificarea codului SQL se pot folosi alias-uri de
tabele n locul numelor acestora.
SQL> SELECT e.empno, e.ename, e.deptno, d.deptno, d.loc
2 FROM emp e, dept d
3 WHERE e.deptno=d.deptno;

Observatii:
Alias-urile de tabel pot avea lungimea maxim de 30 caractere;
3

dac n clauza FROM se introduce un alias pentru tabel, atunci acel alias trebuie s nlocuiasc
numele tabelului n toat instruciunea SELECT;
alias-urile de tabel ar trebui sa fie semnificative;
alias-ul unui tabel este valid numai pentru SELECT-ul curent.

Realizarea unei legturi ntre mai multe tabele


CUSTOMER
NAME
JOCKSSPORTS
TKB SPORT
VOLLYRITE
JUST TENNIS
K+T SPORTS
SHAPE UP
WOMENS SPORTS
...
9 rows selected.

ORD
CUSTID
100
101
102
103
105
106
107
...

CUSTID
ORDID
100
610
101
611
102
612
103
601
ITEM
105
602
106
ORDID
ITEMID
107
610
3
...
611
1
21 rows selected.
612
1
601
1
602
1
...
64 rows selected.

Uneori apare necesitatea realizrii unei jonciuni ntre mai multe tabele. De exemplu, pentru a afia
numele, numrul comenzii, codul articolelor din comand, total numr articole i totalul fiecrei
comenzi pentru clientul TKB SPORT va trebui s realizm o legtur ntre tabelele CUSTOMER,
ORD i ITEM.
SQL> SELECT c.name, o.ordid, i.itemid,
2
i.itemtot, o.total
3 FROM customer c, ord o, item i
4 WHERE c.custid = o.custid
5 AND
o.ordid = i.ordid
6 AND
c.name = 'TKB SPORT';

NAME
--------TKB SPORT
TKB SPORT
TKB SPORT

ORDID ITEMID
----- -----610
3
610
1
610
2

ITEMTOT
TOTAL
------- -----58
101.4
35
101.4
8.4 101.4

2. Non-echi-jonciuni
EMP
EMPNO ENAME
7839 KING
7698 BLAKE
7782 CLARK
7566 JONES
7654 MARTIN
7499 ALLEN
7844 TURNER
7900 JAMES
...
14 rows selected.

SALGRADE
SAL
5000
2850
2450
2975
1250
1600
1500
950

GRADE
1
2
3
4
5

LOSAL
700
1201
1401
2001
3001

HISAL
1200
1400
2000
3000
9999

"salariul din tabelul EMP este ntre


salariul minim i maxim din tabelul
SALGRADE"

Relaia dintre tabelul EMP si SALGRADE este o non-echi-jonciune, n sensul c nici o coloana din
tabelul EMP nu corespunde direct unei coloane din tabelul SALGRADE. Legtura dintre cele dou
tabele este urmtoarea: coloana SAL din EMP este cuprins ntre coloanele LOSAL i HISAL din
tabelul SALGRADE. Legtura se obine folosind un operator, altul dect operatorul egal (=).
4

SQL> SELECT e.name, e.sal, s.grade


2 FROM emp e, salgrade s
3 WHERE e.sal BETWEEN s.losal AND s.hisal;

ENAME
SAL
GRADE
------ ---- -----JAMES
950
1
SMITH
800
1
ADAMS
1100
1

14 rows selected

Exemplul de mai sus creaz o non-echi-jonciune pentru a determina gradul de salarizare al unui
angajat. Salariul trebuie s fie ntre (between) limita inferioar (LOSAL) i cea superioar
(HISAL) a unui nivel de salarizare.
3. Jonciune extern
EMP

DEPT

ENAME
KING
BLAKE
CLARK
JONES
...

DEPTNO
10
30
10
20

DEPTNO
10
30
10
20
...
40

DNAME
ACCOUNTING
SALES
ACCOUNTING
RESEARCH
OPERATIONS

Nici un angajat n departamentul OPERATIONS


Dac o linie (nregistrare) nu satisface condiia de jonciune, acea linie nu va apare n rezultatul
interogrii. De exemplu, n condiia de echi-jonciune a tabelelor EMP i DEPT, departamentul
OPERATIONS nu va apare pentru c nu exist nici o persoan care lucreaz n acel departament.
Liniile lips pot fi returnate dac n condiia de jonciune se utilizeaz operatorul de jonciune
extern. Operatorul este semnul "+" ntre paranteze - (+) i este plasat n acea parte a condiiei de
jonciune corespunztoare tabelului deficient n informaii. Acest operator are ca efect crearea uneia
sau a mai multor linii nule la care se poate adaug una sau mai multe linii din tabelul ce conine
informaiile neselectate.
SELECT tabel.coloana1, tabel.coloana2, ...
FROM tabel1, tabel2
WHERE tabel1.coloana1 = tabel2.coloana2(+) ;

unde:
tabel1.coloana1 =
tabel2.coloana2(+)

este condiia care realizeaz legtura ntre tabele;


este simbolul pentru jonciune extern; poate fi plasat in oricare parte a
clauzei WHERE, dar nu n ambele pri simultan. Se va plasa operatorul de
jonciune extern dup numele coloanei din tabelul deficitar n informaii.

Urmtorul exemplu afieaz toate numerele i numele departamentelor. Departamentul


OPERATIONS, care nu are nici un angajat este de asemenea afiat.
SQL> SELECT e.ename, d.deptno, d.dname
2 FROM emp e, dept d
3 WHERE e.deptno(+) = d.deptno
4 ORDER BY e.deptno ;

ENAME
-----KING
CLARK

DEPTNO
-----10
10

DNAME
--------ACCOUNTING
ACCOUNTING

40 OPERATIONS
15 rows selected

Restricii n cazul utilizrii unei condiii de jonciune extern:


5

operatorul de jonciune extern poate apare numai ntr-o singur parte a unei expresii - partea
care nu deine informaia ce nu este returnat de interogare. El returneaz acele linii din tabel
care nu au corespondent direct n cellalt tabel.
o condiie ce implic operatorul de jonciune extern nu poate utiliza operatorul IN i nici nu
poate fi legat de o alt condiie prin operatorul OR.

4. Condiii de jonciune a unui tabel cu el nsui


EMP (WORKER)
EMPNO
7839
7698
7782
7566
7654
7499

ENAME
KING
BLAKE
CLARK
JONES
MARTIN
ALLEN

EMP (MANAGER)
MGR

EMPNO

ENAME

7839
7839
7839
7698
7698

7839
7839
7839
7698
7698

KING
KING
KING
BLAKE
BLAKE

"MGR din tabelul WORKER este egal cu EMPNO din tabelul MANAGER"
Unele aplicaii impun realizarea unei jonciuni ntre un tabel i el nsui. De exemplu, pentru a gsi
numele managerului lui Blake va trebui s:
- gsim nregistrarea corespunztoare angajatului Blake n tabelul EMP, inspectnd coloana
ENAME;
- gsim codul managerului lui Blake din coloana MGR. Codul managerului lui Blake este 7839.
- gsim numele managerului avnd codul EMPNO egal cu 7893 n coloana ENAME. Codul
angajatului King este 7839. Deci King este managerul lui Blake.
Pe parcursul acestui proces am cutat n tabel de dou ori. Prima dat pentru a-l gsi pe Blake n
coloana ENAME i pentru a citi valoarea MGR - 7839. A doua oar am cutat n coloana EMPNO
valoarea 7839 i am extras din coloana ENAME valoarea King.
SQL> SELECT worker.ename || 'works for' || man.ename
2 FROM emp worker, emp man
3 WHERE worker.mgr = man.empno

WORKER.ENAME||'WORKSFOR'||MANAG
-------------------------------BLAKE works for KING
CLARK works for KING
JONES works for KING
MARTIN works for BLAKE

13 rows selected

Exemplul de mai sus creaz o legtur ntre tabelul EMP i el nsui. Pentru a simula dou tabele n
clauza FROM, se folosesc dou aliasuri, numite WORKER i MAN pentru acelai tabel EMP. n acest
exemplu, clauza WHERE conine condiia de jonciune care nseamn "pentru care codul
managerului unui angajat coincide cu codul de angajat al managerului".

Gruparea rezultatelor unei interogri


Obiective
Prin parcurgerea acestei seciuni studentul va dobndi cunotinele necesare:
identificrii funciilor grup disponibile;
descrierii modului de utilizare a funciilor grup;
gruprii datelor folosind clauza GROUP BY;
includerii sau excluderii cmpurilor grupate folosind clauza HAVING;

Funcii grup
Funciile grup opereaz pe mulimi de nregistrri i furnizeaz un singur rezultat pentru ntregul
grup. Exemplul de mai jos afieaz salariul maxim din tabelul emp.
EMP
DEPTNO
-------10
10
10
20
20
20
20
20
30
30
30
30
30
30

SAL
-------2450
5000
1300
800
1100
3000
3000
2975
1600
2850
1250
950
1500
1250

salariul maxim n
tabelul EMP

MAX(SAL)
--------5000

n tabelul urmtor sunt descrise funciile grup ce pot fi utilizate n clauza SELECT. Parametrii
implicii apar subliniai.
Funcie

Descriere

AVG([DISTINCT|ALL] n)
COUNT({*|[DISTINCT|ALL] expr})

Returneaz valoarea medie a lui n, ignornd valorile null;


Returneaz numrul de rnduri selectate, unde expr evalueaz
altceva dect valori null. Pentru a numra toate rndurile
selectate, inclusiv rndurile duplicat i cele cu valori null, se
va folosi *;
Returneaz valoarea maxim pentru expr, ignornd valorile
null;
Returneaz valoarea minim pentru expr, ignornd valorile
null;
Calculeaz abaterea standard a lui n, ignornd valorile null;
Calculeaz suma valorilor lui n, ignornd valorile null;
Calculeaz variana lui n, ignornd valorile null;

MAX([DISTINCT|ALL]expr)
MIN([DISTINCT|ALL] expr)
STDDEV([DISTINCT|ALL] n)
SUM([DISTINCT|ALL] n)
VARIANCE([DISTINCT|ALL] n)

Folosirea funciilor grup


SELECT coloana, functie_grup(coloana)
FROM tabel
[WHERE conditie]
[ORDER BY coloana];

DISTINCT implic luarea n considerare numai a valorilor neduplicat. Argumentul ALL ia n


considerare fiecare valoare, inclusiv valorile duplicat; este opiunea implicit.
tipurile de date admise pentru expr sunt: CHAR, VARCHAR2, NUMBER sau DATE.
toate grupurile de funcii, cu excepia funciei COUNT(*) ignor valorile null. Pentru a nlocui
o valoare null cu o alt valoare se poate utiliza funcia NVL (e.g. funcia NVL(COMM,0) va
returna 0 dac COMM are valoarea null i valoarea COMM dac aceasta e diferit de null).

1. Funciile AVG, SUM, MIN i MAX


Funciile AVG i SUM pot fi aplicate doar coloanele ce conin date numerice, n timp ce funciile
MIN i MAX opereaz asupra oricrui tip de date. Exemplul urmtor afieaz media salariilor
lunare, salariul maxim, respectiv minim i suma salariilor lunare pentru toi angajaii cu funcia
SALESMAN.
SQL> SELECT AVG(SAL),MAX(sal),
2
MIN(sal),SUM(sal)
3 FROM emp
4 WHERE job LIKE SALES;

AVG(SAL)
-------1400

MAX(SAL)
-------1600

MIN(SAL)
-------1250

SUM(SAL)
-------5600

Pentru a afia numele primului, respectiv ultimului angajat din lista ordonat alfabetic a tuturor
angajailor se va executa urmtoarea interogare:
SQL> SELECT MIN(ename),MAX(ename)
2 FROM emp;

MIN(ENAME) MAX(ENAME)
--------- ---------ADAMS
WARD

Not : Funciile AVG, SUM, VARIANCE i STDDEV pot fi utilizate doar cu tipuri de date numerice.
2. Funcia COUNT
Funcia COUNT are dou formate:
- COUNT(*) i
- COUNT(expr)
COUNT(*) returneaz numrul de rnduri din interogare, inclusiv liniile duplicat i cele coninnd
valori null, n timp ce COUNT(expr) returneaz numrul valorilor diferite de null din coloana
identificat prin expr. Exemplul de mai jos afieaz numrul angajailor din departamentul 30.
SQL> SELECT COUNT(*)
2 FROM emp
3 WHERE deptno = 30;

COUNT(*)
------6

Clauza GROUP BY
EMP
DEPTNO
-----10
10
10
20
20
20
20
20
30
30
30
30
30
30

SAL
------2450
5000
1300
800
1100
3000
3000
2975
1600
2850
1250
950
1500
1250

salariul mediu n tabelul


scott.emp
pentru fiecare departament
2916.6667
DEPTNO
-----10
20
30

2175

AVG(SAL)
--------2916.6667
2175
1566.6667

1566.6667

Pn acum, toate funciile grup au tratat tabelul ca fiind un grup larg de informaii. Pentru
mprirea tabelului n grupuri mai mici se poate utiliza clauza GROUP BY.
SELECT coloana, functie_grup(coloana)
FROM tabel
[WHERE conditie]
[GROUP BY expresie_de_grupare]
[ORDER BY coloana];

unde expresie_de_grupare specific acele coloane ale cror valori determin criteriul de grupare a
liniilor.
Clauza GROUP BY determin mprirea rndurilor din tabel n grupuri. n cazul utilizrii unei
funcii grup n conjuncie cu clauza GROUP BY se va returna rezultatul funciei grup pentru fiecare
grup.
Observaii:

dac se include o funcie grup ntr-o clauz SELECT, lista coloanelor individuale
(coloanele care nu apar n funcia grup) trebuie s apar n clauza GROUP BY. n caz
contrar se va genera un mesaj de eroare.
utilizarea unei clauze WHERE exclude rndurile care nu satisfac condiia impus nainte de a se
efectua divizarea n grupuri;
n clauza GROUP BY trebuie incluse coloane; este interzis utilizarea unui alias de coloan n
clauza GROUP BY;
rndurile sunt sortate implicit n ordinea ascendent a coloanelor incluse n lista GROUP BY.
Este posibil nclcarea acestei reguli folosind clauza ORDER BY.

Urmtorul exemplu afieaz numrul fiecrui departament mpreun cu media salariilor pe acel
departament. Modul de evaluare al instruciunii SELECT coninnd o clauz GROUP BY este
urmtorul:
-

clauza SELECT specific acele coloane ce urmeaz s fie afiate:


- coloana deptno corespunztoare numrului departamentului
- media salariilor din grupul specificat n clauza GROUP BY
9

- clauza FROM indic tabelul ce trebuie accesat - emp.


- clauza WHERE specific rndurile ce vor fi selectate. Dac nu exist clauz WHERE vor fi luate n
considerare toate rndurile.
- clauza GROUP BY specific modul de grupare al rndurilor. Rndurile sunt grupate dup
numrul departamentului, deci funcia AVG (aplicat coloanei sal) va calcula media salariilor
pentru fiecare departament.
SQL> SELECT deptno, AVG(sal)
2 FROM emp
3 GROUP BY deptno;

DEPTNO
-----10
20
30

AVG(SAL)
--------2916.6667
2175
1566.6667

Not: Coloana ce apare n clauza GROUP BY nu trebuie s apar obligatoriu n clauza SELECT. De
exemplu, instruciunea SELECT de mai jos afieaz media salariilor pentru fiecare departament,
fr s afieze numrul departamentului respectiv. Este permis utilizarea unei funcii grup n
clauza ORDER BY.
SQL> SELECT AVG(sal)
2 FROM emp
3 GROUP BY deptno;
4 ORDER BY AVG(sal);

DEPTNO
------30
20
10

AVG(SAL)
---------1566.6667
2175
2916.6667

Gruparea dup mai multe coloane


EMP
DEPTNO JOB
------ -------10 MANAGER
10 PRESIDENT
10 CLERK
20 CLERK
20 CLERK
20 ANALYST
20 ANALYST
20 MANAGER
30 SALESMAN
30 MANAGER
30 SALESMAN
30 CLERK
30 SALESMAN
30 SALESMAN

suma salariilor din tabelul scott.emp


pentru fiecare funcie, grupate dup
departament

SAL
-----2450
5000
1300
800
1100
3000
3000
2975
1600
2850
1250
950
1500
1250

DEPTNO
------10
10
10
20
20
20
30
30
30

JOB
SUM(SAL)
------ -------CLERK
1300
MANAGER
2450
PRESIDENT
5000
ANALYST
6000
CLERK
1900
MANAGER
2975
CLERK
950
MANAGER
2850
SALESMAN
5600

Unele situaii cer afiarea unor rezultate de sintez pentru grupurile din interiorul altor grupuri.
Figura de mai sus reprezint totalul salariilor pltite pentru fiecare funcie, n cadrul fiecrui
departament. Tabelul emp este grupat mai nti dup numrul departamentului i apoi, n fiecare
grup obinut se realizeaz o grupare dup numele funciei. De exemplu, cei doi angajai cu funcia
CLERK din departamentul 20 sunt grupai mpreuna i este returnat un singur rezultat (salariul total)
pentru toi angajaii din acest grup.
Se pot returna rezultate sintez pentru grupuri i subgrupuri prin specificarea mai multor coloane n
clauza GROUP BY. Ordinea implicit a rezultatelor afiate poate fi controlat prin ordinea n care
apar coloanele n clauza GROUP BY.
10

SQL> SELECT deptno, job,sum(sal)


2 FROM emp
3 GROUP BY deptno, job;

DEPTNO JOB
AVG(SAL)
------ ------- --------10 CLERK
1300
10 MANAGER
2450
10 PRESIDENT
5000
20 ANALYST
6000
20 CLERK
1900
...
9 rows selected.

Observaii: clauza WHERE nu poate fi utilizat pentru restricionarea grupurilor. Dac se dorete
acest lucru se va utiliza clauza HAVING.
SQL> SELECT deptno, AVG(sal)
2 FROM emp
3 WHERE AVG(sal) > 2000
4 GROUP BY deptno;

WHERE AVG(sal)>2000
*
ERROR at line 3:
ORA-00934: group function is not allowed here

Aceast eroarea poate fi corectat prin folosirea clauzei HAVING pentru a restriciona grupurile ce
vor fi afiate.
SQL> SELECT deptno,AVG(sal)
2 FROM emp
3 GROUP BY deptno
4 HAVING AVG(sal)>2000;

DEPTNO
-----10
20

AVG(SAL)
--------2916.6667
2175

Clauza HAVING
n acelai mod n care clauza WHERE este utilizat pentru a restriciona rndurile selectate, se poate
utiliza clauza HAVING pentru a restriciona grupuri. Pentru a gsi salariul maxim din fiecare
departament, dar la afiare s participe doar departamentele n care salariul maxim este mai mare de
$2900 trebuie efectuate urmtoarele operaii:
1. se va cuta salariul maxim pentru fiecare departament, grupnd nregistrrile dup numrul
departamentului;
2. se vor restriciona grupurile la acele departamente cu un salariu maxim mai mare de $2900.
EMP
DEPTNO
------10
10
10
20
20
20
20
20
30
30
30
30
30
30

SAL
-----2450
5000
1300
800
1100
3000
3000
2975
1600
2850
1250
950
1500
1250

5000

3000

salariul maxim pe departament


mai mare de 2900 $
DEPTNO
-----10
20

AVG(SAL)
-------5000
3000

2850

Pentru a pstra n rezultat doar acele grupuri ce ndeplinesc o condiie se va utiliza clauza HAVING.
SELECT coloana, functie_grup
FROM tabel
11

[WHERE conditie ]
[GROUP BY expresie_de_grupare]
[HAVING conditie_grup]
[ORDER BY coloana];

unde conditie_grup
specificat.

restricioneaz grupurile de rnduri la acele grupuri ce satisfac condiia

Serverul Oracle parcurge urmtorii pasi cnd ntlnete o clauz HAVING :


- grupeaz rndurile
- aplic funcia grup fiecrui grup
- afieaz doar grupurile care ndeplinesc criteriul din clauza HAVING.
Exemplul urmtor afieaz numrul departamentului i salariul maxim pentru acele departamente n
care salariul maxim este mai mare de $2900.
SQL> SELECT deptno,max(sal)
2 FROM emp
3 GROUP BY deptno
4 HAVING max(sal)>2900;

DEPTNO
-----10
20

MAX(SAL)
-------5000
3000

Probleme:
1. Scriei o interogare care s afieze numele fiecrui angajat, precum i numrul i numele
departamentului n care lucreaz.
2. Creai un listing unic pentru toate funciile (job) angajailor din departamentul SALES.
3. Scriei o interogare care afieaz numele, numele departamentului i locaia departamentului
pentru toi angajaii ce au dreptul la comision.
4. Afiai numele angajatului i numele departamentului pentru toi angajaii al cror nume conine
un caracter A.
5. Scriei o interogare care afieaz numele, funcia, numrul departamentului i numele
departamentului pentru toi angajaii care lucreaz n DALLAS.
6. Afiai numele angajailor i codurile lor, mpreun cu numele managerilor i codurile acestora.
Redenumii coloanele Employee, Emp#, Manager i Mgr#.
7. Modificai interogarea anterioar pentru a afia toi angajaii, inclusiv pe King care nu are
manager.
8. Creai o interogare care va afia numele fiecrui angajat, numrul departamentului n care
lucreaz i numele tuturor angajailor care lucreaz n acelai departament. Redenumii ct mai
expresiv coloanele.
9. Afiai structura tabelului SALGRADE. Creai o interogare care va afia numele, funcia,
numele departamentului, salariul i gradul de salarizare pentru toi angajaii.
10. Creai o interogare care afieaz numele i data angajrii pentru lucrtorii angajai dup data de
angajare a lui Blake.
11. Afiai toate numele angajailor i datele de angajare mpreun cu numele managerilor i data
lor de angajare pentru toi cei care au fost angajai naintea managerilor lor. Etichetai coloanele
Employee, Emp, Hiredate, Manager i Mgr Hiredate.
12. Afiai numrul managerilor (pe baza valorilor din coloana mgr) din tabelul emp. Etichetai
coloana Numar Manageri.
13. Scriei o interogare care s afieze diferena dintre salariul cel mai mare i cel mai mic din
tabelul emp. Etichetai coloana Diferena.
14. Afiai numrul fiecrui manager i salariul celui mai prost pltit subaltern al su. Excludei
angajaii ce nu au manager. Excludei grupurile care au salariul minim mai mic dect 1000$.
Sortai rezultatele n ordine descresctoare dup salar.
15. Scriei o interogare care s afieze numele fiecrui departament, localitatea, numrul de angajai
i salariul mediu al angajailor din acel departament. Etichetai coloanele Dname, Loc, Nr
Persoane i Salariu.
12

Subinterogri. Rapoarte interactive


Instruciuni pentru manipularea datelor
I. Subinterogri
Obiective

Prin parcurgerea acestei seciuni studentul va cpta cunotinele necesare:


definirii unei subinterogri;
scrierii subinterogrilor single-row, multiple-row, multiple-column;
descrierii i explicrii subinterogrilor atunci cnd sunt returnate valori null;
scrierii unor subinterogri n clauza FROM;
scrierii unei interogri care necesit o variabil de intrare;

S presupunem c dorim s interogm o baz de date pentru a afla numele angajatului cu un


salariu mai mare dect salariul lui Jones.
Pentru rezolvarea acestei probleme sunt necesare dou interogri: o interogare pentru a afla ce
salariu are Jones i o a doua pentru a determina cine ctig mai mult dect aceast sum. Problema
poate fi rezolvat combinnd aceste dou interogri, integrnd una din cereri n cealalt.
O cerere inclus sau subinterogare returneaz o valoare folosit de interogarea exterioar.
Folosirea unei subinterogri este echivalent executrii a dou cereri secveniale i folosirii rezultatului
primei cereri ca valoare de cutare pentru cea de a doua cerere.
SELECT lista_selectie1
FROM tabel1
WHERE expr operator
(SELECT lista_selectie2
FROM tabel2);

O subinterogare reprezint o instruciune SELECT care este inclus ntr-o clauz aparinnd
altei instruciuni SELECT. Se pot astfel construi instruciuni puternice, pornind de la instruciuni
simple, prin utilizarea subinterogrilor. Acestea pot fi utile n cazurile n care se dorete selectarea
unor rnduri dintr-un tabel n raport cu o condiie care depinde de datele din acelai tabel.
Subinterogrile pot fi plasate n clauzele WHERE, HAVING i FROM.
n sintaxa instruciunii SELECT prezentat mai sus operator indic un operator de comparaie
(>, =, IN, ...).
Not: Operatorii de comparaie se mpart n dou clase:
operatori ce acioneaz asupra unui singur rnd (single-row): >, =, >=, <, <>, <=
operatori ce acioneaz asupra mai multor rnduri (multiple-row): IN, ANY, ALL.
Subinterogarea este deseori referit ca fiind o instruciune SELECT inclus, un sub-SELECT sau o
instruciune SELECT intern. n general, subinterogarea se execut prima, iar rezultatul este folosit
pentru a finaliza condiia de cerere din interogarea principal.
SQL> SELECT ename
2 FROM emp
3 WHERE sal > (SELECT sal FROM emp WHERE empno=7566);

ENAME
------KING
FORD
SCOTT

n exemplul anterior cererea intern determin salariul angajatului cu numrul 7566. Cererea
extern preia rezultatul cererii interne i l folosete pentru a afia toi angajaii care ctig un salariu
mai mare dect aceast sum.

Indicaii privind scrierea subinterogrilor:

o subinterogare trebuie inclus ntre paranteze.


o subinterogare trebuie s apar n partea dreapt a unui operator de comparaie.
subinterogrile nu pot conine clauza ORDER BY. Pentru o instruciune SELECT poate exista doar
o singur clauz ORDER BY, iar dac aceast clauz este specificat, ea trebuie s fie ultima
clauz din instruciunea SELECT principal.
subinterogrile folosesc dou clase de operatori de comparare: operatori single-row i operatori
multiple-row.

Tipuri de subinterogri:
1. subinterogri pe coloan (single-row): cereri care returneaz doar un rnd din instruciunea
SELECT intern;
2. subinterogri multi-rnd (multiple-row): cereri care returneaz mai mult de un rnd din
instruciunea SELECT intern;
3. subinterogri multi-coloan (multiple-column): cereri care returneaz mai multe coloane din
instruciunea SELECT intern..

1. Subinterogri single-row
O subinterogare single-row este acea subinterogare care returneaz un singur rnd din
instruciunea SELECT intern. Acest tip de subinterogare folosete un operator single-row.
Exemplu: Afiai numele i postul angajailor al cror post este acelai cu cel al angajatului cu
numrul 7369 i al cror salariu este mai mare dect cel al angajatului 7876.
SQL> SELECT ename, job
2 FROM emp
3 WHERE job = (SELECT job FROM emp WHERE empno = 7369)
5 AND
sal > (SELECT sal FROM emp WHERE empno = 7876);

ENAME
-----MILLER

JOB
----CLERK

Interogarea de mai sus este format din 3 blocuri de cereri: o cerere exterioar i dou cereri
interne. Blocurile de cereri interne se vor executa primele, producnd rezultatele cererii: CLERK,
respectiv 1100. Blocul exterior de cereri este apoi procesat i folosete valorile returnate de cererile
interne pentru a-i finaliza propriile condiii de cutare. Ambele cereri interne returneaz cte o singur
valoare, astfel c aceast instruciune SQL este denumit subinterogare single-row.
Not: Interogrile exterioare i cele incluse pot prelua date din tabele diferite.
O interogare principal poate afia date utiliznd valoarea returnat de o funcie grup din
subinterogare. Subinterogarea se va plasa ntre paranteze, dup operatorul de comparaie.
Exemplul urmtor afieaz numele, postul i salariul tuturor angajailor al cror salariu este
egal cu salariul minim. Funcia MIN returneaz o singur valoare (i anume 800), care este folosit de
interogarea principal.
SQL> SELECT ename, job, sal
2 FROM emp
3 WHERE sal = (SELECT MIN(sal) FROM emp);

ENAME JOB
------ ----SMITH CLERK

SAL
--800

Subinterogri n clauza HAVING


Subinterogrile pot fi folosite nu numai n clauza WHERE, dar i n clauza HAVING. Server-ul
Oracle execut subinterogarea, returnnd apoi rezultatul ctre clauza HAVING a interogrii principale.

Urmtoarea instruciune SQL are ca scop final afiarea tuturor departamentelor la nivelul
crora salariul minim are o valoare mai mare dect valoarea salariului minim din cadrul
departamentului 20.
SQL> SELECT deptno, MIN(sal)
2 FROM emp
3 GROUP BY deptno
4 HAVING MIN(sal) > (SELECT MIN(sal) FROM emp WHERE deptno = 20);

DEPTNO
------10
30

MIN(SAL)
------1300
950

Exemplu: S se gseasc funcia avnd cel mai sczut salariu mediu:


SQL> SELECT job, AVG(sal)
2 FROM emp
3 GROUP BY job
4 HAVING AVG(sal) = (SELECT MIN(AVG(sal)) FROM emp GROUP BY job);

Erori ce pot apare la folosirea subinterogrilor:


-

returnarea mai multor rnduri de ctre o subinterogare dorit a fi de tip single-row;


posibilitatea neselectrii nici unui rnd de ctre interogarea inclus.

2. Subinterogri multiple-row
Subinterogrile care returneaz mai mult de un rnd se numesc subinterogri multiple-row. n
cazul acestui tip de subinterogri se folosesc operatori multiple-row n locul celor single-row.
Operator
IN
ANY
ALL

Semnificaie
Egal cu oricare din elementele listei
Compar valoarea cu fiecare valoare returnat de subinterogare
Compar valoarea cu toate valorile returnate de subinterogare

Urmtorul exemplu selecteaz toi angajaii care ctig un salariu egal cu salariul minim la
nivel de departament.
SQL> SELECT ename, sal, deptno
2 FROM emp
3 WHERE sal IN (SELECT MIN(sal) FROM emp GROUP BY deptno);

Interogarea intern va fi prima executat, producnd ca rspuns la cerere trei rnduri: 800, 950,
1300. Blocul cererii externe este apoi procesat i folosete valorile returnate de ctre interogarea
intern pentru a-i finaliza propria condiie de cutare. De fapt, interogarea principal este privit din
perspectiva server-ului Oracle astfel:
SQL> SELECT ename, sal, deptno
2 FROM emp
3 WHERE sal IN (800, 950, 1300);

Operatorul ANY (i operatorul SOME, sinonim acestuia) compar o valoare cu fiecare valoare
returnat de subinterogare. Exemplul de mai jos afieaz angajaii ale cror salarii sunt mai mici dect
al oricrui angajat cu funcia CLERK i care nu au funcia CLERK. Salariul maxim pe care l ctig
un angajat cu funcia CLERK este $1300. Instruciunea SQL afieaz toi angajaii care nu au funcia
CLERK, dar ctig mai puin de $1300.
SQL> SELECT empno, ename, job
2 FROM emp
3 WHERE sal < ANY (SELECT sal FROM emp WHERE job = 'CLERK')
4 AND job <> 'CLERK';

EMPNO
----7654
7521

ENAME
-----MARTIN
WARD

JOB
-------SALESMAN
SALESMAN

Operatorul ALL compar o valoare cu toate valorile returnate de o subinterogare. Exemplul


urmtor afieaz toi angajaii ale cror salarii sunt mai mari dect salariile medii la nivel de
departamente. Cum cel mai mare salariu mediu al vreunui departament este $2916.6667, rezult c
interogarea va selecta acei angajai ale cror salarii sunt mai mari dect $2916.6667.
SQL> SELECT empno, ename, job
2 FROM emp
3 WHERE sal > ALL (SELECT avg(sal) FROM emp GROUP BY deptno);

EMPNO
----7839
7566
7902
7788

ENAME
-----KING
JONES
FORD
SCOTT

JOB
----PRESIDENT
MANAGER
ANALYST
ANALYST

3. Subinterogri multiple-column
Sintaxa unei subinterogri pe mai multe coloane este:
SELECT coloana1, coloana2,
FROM tabel
WHERE (coloana1, coloana2, ) IN (SELECT coloana3, coloana4, FROM tabel WHERE conditie);

n cazul n care n clauza WHERE se dorete compararea a dou sau mai multe coloane, condiia
corespunztoare va trebui formulat o condiie compus cu ajutorul operatorilor logici. Subinterogrile
multiple-column ofer posibilitatea de a combina dou condiii duplicat de selecie n una singur.
S presupunem c se cere afiarea numelui, a numrului departamentului, a salariului i a comisionului
pentru angajaii ale cror salarii i comisioane coincid cu salariul i comisionul oricrui angajat din
departamentul 30. Aceast cerere va fi formulat cu ajutorul urmtoarei instruciuni SELECT:
SQL> SELECT ename, deptno, sal, comm
2 FROM emp
3 WHERE (sal,NVL(comm,-1)) IN
4
(SELECT sal, NVL(comm,-1)
5
FROM emp
6
WHERE deptno=30);

ENAME
-------JAMES
WARD
MARTIN
TURNER
ALLEN
BLAKE

DEPTNO
------30
30
30
30
30
30

SAL
-----950
1250
1250
1500
1600
2850

COMM
-----500
1400
0
300

n exemplul de mai sus a fost utilizat o subinterogare pe coloane multiple, deoarece


subinterogarea returneaz dou coloane. Condiia din clauza WHERE compar perechea format din
coloanele sal i comm cu perechile returnate de subinterogare.
Comparaiile pe coloane n subinterogrile de tip multiple-row pot fi clasificate n comparaii
pereche sau individuale. Exemplul anterior utilizeaz o comparaie pereche n clauza WHERE, deoarece
fiecare linie returnat de instruciunea SELECT exterioar trebuie s aib acelai salariu i comision ca
un angajat din departamentul 30. Dac se dorete utilizarea unei comparaii individuale va trebui s
folosim o clauz WHERE cu mai multe condiii.
Exemplul urmtor folosete o comparaie individual pentru a afia numele, numrul
departamentului, salariul i comisionul oricrui angajat al crui salariu i comision coincid cu salariul
i comisionul oricrui angajat din departamentul 30:
SQL> SELECT ename, deptno, sal, comm
2 FROM emp
3 WHERE sal IN (SELECT sal FROM emp
4
WHERE deptno=30)
5 AND
6
NVL(comm, -1) IN (SELECT NVL(comm, -1)
7
FROM emp
8
WHERE deptno=30);

ENAME
------JAMES
BLAKE
TURNER
ALLEN
WARD
MARTIN

DEPTNO
------30
30
30
30
30
30

SAL
------950
2850
1500
1600
1250
1250

COMM
------

0
300
500
1400

Dei condiiile din cele dou interogri sunt diferite, rezultatele coincid. Aceast coinciden se
datoreaz datelor coninute de tabelul emp.
Exerciiu: S presupunem c salariul lui CLARK este de $1500, iar comisionul su este de
$300. Explicai de ce rezultatele celor dou interogri prezentate mai sus difer (a doua interogare va
returna nregistrarea suplimentar CLARK 10 1500 300 ).

Returnarea valorilor null n rezultatul unei subinterogri


SQL> SELECT employee.ename
2 FROM emp employee
3 WHERE employee.empno NOT IN
4
(SELECT manager.mgr
5
FROM emp manager);

no rows selected.

Instruciunea SQL de mai sus afieaz toi angajaii care nu au nici un subordonat. Logic,
aceast interogare SQL ar trebui s returneze 8 linii, dar instruciunea SQL nu returneaz nici una. Una
din valorile returnate de interogarea interioar este o valoare null i astfel, condiia de selecie din
interogare principal nu este adevrat pentru nici o linie din tabelul emp. Acest lucru se explic prin
aceea c toate condiiile care compar o valoare null cu o alt valoare vor returna valoarea null.
Not: Cnd exist valori null n rezultatul unei subinterogri nu este indicat folosirea operatorului
NOT IN, deoarece acesta este echivalent cu != ALL. n astfel de cazuri se poate utiliza operatorul
IN.
De exemplu, pentru
instruciune SQL :

afiarea angajailor care au subordonai se poate utiliza urmtoarea

SQL> SELECT employee.ename


2 FROM emp employee
3 WHERE employee.empno IN (SELECT manager.mgr FROM emp manager);

ENAME
-----KING

6 rows selected.

Utilizarea unei subinterogri n clauza FROM


Exemplul urmtor afieaz numele angajailor, salariile, numrul departamentului i media
salariilor din fiecare departament pentru toi angajaii care ctig mai mult dect media salariilor din
departamentul n care lucreaz.
SQL> SELECT a.ename, a.sal, a.deptno, b.salavg
2 FROM emp a, (SELECT deptno, AVG(sal) salavg
3
FROM emp
4
GROUP BY deptno) b
5 WHERE a.deptno = b.deptno
6 AND a.sal > b.salavg;

ENAME
SAL
------- ------KING
5000
JONES
2975
SCOTT
3000
6 rows selected.

DEPTNO
------10
20
20

SALAVG
---------2916.6667
2175
2175

n exemplul anterior instruciunea SELECT va opera pe tabelul emp (cu aliasul a) i pe tabelul
returnat de interogarea din clauza FROM (cu aliasul b). Tabelul b va avea dou coloane (deptno i
salavg) i va conine pentru fiecare departament, numrul su i media salariilor.

II. Rapoarte interactive


Exemplele prezentate pn acum nu au prezentat nici un grad de interactivitate. Prin utilizarea
SQL*Plus este posibil crearea de rapoarte care cer utilizatorului sa furnizeze propriile valori pentru a
limita domeniul datelor returnate. Pentru a crea rapoarte interactive se pot include variabile de
substituie ntr-un fiier de comenzi sau ntr-o singur instruciune SQL.
Variabile de substituie

n SQL*Plus se pot folosi variabile de substituie cu ajutorul caracterului & pentru a stoca
temporar valori. Variabilele pot fi definite cu ajutorul comenzilor ACCEPT sau DEFINE. ACCEPT
citete valoarea introdus de utilizator i o memoreaz ntr-o variabil. DEFINE creeaz i atribuie o
valoare unei variabile.
Utilizarea variabilelor de substituie &
n timpul execuiei unui raport, utilizatorii doresc adeseori s limiteze n mod dinamic rezultatele
returnate de o interogare. SQL*Plus ofer aceast flexibilitate prin intermediul variabilelor utilizator.
Pentru a identifica fiecare variabil din instruciunea SQL se va utiliza caracterul &.
SQL> SELECT empno,ename,sal,deptno
2 FROM emp
3 WHERE empno=&employee_num;

NOTAIE
&variabila_utilizator

Enter value for employee_num:7369


EMPNO
------7369

ENAME
------SMITH

SAL
-----800

DEPTNO
------20

DESCRIERE
Indic o variabil ntr-o instruciune SQL; dac variabila nu exist,
SQL*Plus va crea variabila i va cere utilizatorului s introduc o valoare.

Exemplu de mai sus reprezint o instruciune SQL care va cere utilizatorului s introduc
numrul unui angajat n momentul execuiei.
Not: n cazul utilizrii unui singur & utilizatorul trebuie s introduc valoarea acelei variabile
ori de cte ori se execut instruciunea, n cazul n care variabila nu exist.
Comanda SET VERIFY
SQL>
SQL>
2
3

SET
VERIFY ON
SELECT empno ,sal, deptno
FROM emp
WHERE empno=&employee_num;

Enter value for employee_num:7369


old 3: WHERE empno=&employee_num
new 3: WHERE empno=7369
............

n cazul n care SET VERIFY este activ (pe ON), SQL*Plus este forat s afieze textul unei
instruciuni nainte i dup ce sunt nlocuite variabilele de substituie cu valorile corespunztoare. n
exemplul de mai sus este afiat att valoarea veche ct i cea nou pentru coloana empno.
Regula conform creia ntr-o clauz WHERE valorile de tip caracter i date calendaristice
trebuie ncadrate de apostrofuri ( ) se aplic i n cazul variabilelor de substituie. Pentru a evita
introducerea apostrofurilor n momentul execuiei se va ncadra variabila ntre apostrofuri. n
urmtorul exemplu este prezentat o interogare pentru a afla numele angajatului, numrul
departamentului i salariul anual pe baza funciei introdus la prompt de utilizator.
SQL> SELECT ename,deptno,sal*12
2 FROM emp
3 WHERE job=&job_title;

Enter value for job_title: ANALYST


ENAME
------SCOTT
FORD

DEPTNO
------20
20

SAL*12
------36000
36000

Not: se pot folosi i funciile UPPER i LOWER n conjuncie cu &. (


UPPER(&job_title) va converti caracterele din irul argument n majuscule; efect opus are
funcia LOWER )
Variabilele de substituie pot fi utilizate pentru a suplimenta:
- o condiie WHERE;
- o clauz ORDER BY;
- numele unei coloane;

numele unui tabel;


o instruciune SELECT.

Pentru exemplificare s considerm cererea de a afia numrul de nregistrare al angajailor i


valorile din coloana introdus de la tastatur pe baza unei condiii introdus, de asemenea, de la
tastatur.
Enter value for column_name: job
Enter value for condition: deptno=10

SQL> SELECT empno, &column_name


2 FROM emp
3 WHERE &condition;

EMPNO
------7839
7782
7934

JOB
-------PRESIDENT
MANAGER
CLERK

Not: Dac nu introducei o valoare pentru variabila de substituie se va genera o eroare cnd
se va executa instruciunea de mai sus.

Utilizarea variabilelor de substituie &&


Se va utiliza ampersand dublu (&&) atunci cnd se dorete reutilizarea valorii acelei variabile,
fr a fi necesar reintroducerea de la tastatur a unei valori pentru variabil.
SQL> SET VERIFY ON
SQL> SELECT empno, ename, job,
2
&&column_name
3
FROM emp
4
ORDER BY &column_name;

Enter
old
new
old
new

value for column_name: deptno


1: select empno,ename,job,&&column_name
1: select empno,ename,job,deptno
3: order by &column_name
3: order by deptno

EMPNO ENAME
------ ------7839 KING
7782 CLARK
7934 MILLER
........
14 rows selected

JOB
---------PRESIDENT
MANAGER
CLERK

DEPTNO
-----10
10
10

n exemplul de mai sus, utilizatorului i se cere s furnizeze o valoarea pentru variabila


column_name o singur dat . Valoarea furnizat de utilizator (deptno) va fi utilizat att pentru
afiare ct i pentru ordonarea datelor .
SQL*Plus memoreaz valoarea unei variabile cu ajutorul comenzii SQL*Plus DEFINE i va
utiliza acea valoare ori de cte ori se face referire la variabil. Pentru a terge o variabil trebuie
folosit comanda UNDEFINE.
Variabilele utilizator pot fi definite nainte de a executa o instruciune SELECT cu ajutorul
comenzilor DEFINE i ACCEPT.
Comanda
DEFINE variabil = valoare
DEFINE variabil
DEFINE
ACCEPT

Descriere
Creeaz o variabil de tip CHAR i atribuie acelei variabile o valoare.
Afieaz variabila, valoarea i tipul acesteia.
Afieaz toate variabilele utilizator, mpreun cu valorile asociate i tipurile de date
Citete o linie introdus de utilizator i o memoreaz ntr-o variabil.

Sintaxa comenzii ACCEPT este urmtoarea:


ACCEPT variabila [tip_date] [FORMAT format] [PROMPT text] [HIDE]

unde:
variabila
tip_date
FOR[MAT]

este denumirea variabilei. Dac aceasta nu exist, ea va fi creat de SQL*Plus.


este tipul de date asociat variabilei: NUMBER, CHAR sau DATE.
CHAR are o lungime de maxim 240 octei.
precizeaz modelul de format - de exemplu A10 sau 9.999

format
PROMPT
text
HIDE

afieaz textul text nainte ca utilizatorul s introduc valoarea


ascunde cea ce introduce utilizatorul de exemplu o parol

Not: nu se va prefixa numele variabilei cu & n comanda ACCEPT.


SQL> ACCEPT dept PROMPT Introdu nume dept:
SQL> SELECT *
2 FROM
scott.dept
3 WHERE
dname=UPPER(&dept);

Introdu nume dept: Sales


DEPTNO
-----30

DNAME
-------SALES

LOC
--------CHICAGO

O variabil va rmne definit pn cnd :


- se va utiliza comanda UNDEFINE pentru a o anula;
- se va prsi mediul SQL*Plus.
Cnd anulai o variabil exist posibilitatea de a verifica modificrile efectuate executnd comanda
DEFINE.

III. Instruciuni pentru manipularea datelor


Scopul acestei seciuni este de a prezenta instruciunile SQL caracteristice limbajului de
manipulare a datelor (LMD), instruciuni ce sunt utilizate pentru a opera modificri asupra instanei
bazei de date. Aceste instruciuni permit inserarea ntr-un tabel, precum i actualizarea i tergerea de
nregistrri ntr-un tabel. De asemenea, va fi prezentat i modul n care pot fi controlate tranzaciile cu
ajutorul comenzilor COMMIT, SAVEPOINT i ROLLBACK.
-

Prin parcurgerea acestei seciuni studentul va dobndi cunotinele necesare pentru:


descrierea fiecrei comenzi LMD;
inserarea unei nregistrri ntr-un tabel;
actualizarea nregistrrilor dintr-un tabel;
tergerea unei nregistrri dintr-un tabel;
controlul tranzaciilor.

Limbajul de manipulare a datelor


Limbajul de manipulare a datelor (LMD) reprezint o component important a SQL. O
comand din LMD are ca obiectiv adugarea, modificarea sau tergerea datelor dintr-o baz de date. O
colecie de instruciuni LMD care formeaz o unitate logic de lucru se numete tranzacie.
S considerm o baz de date din domeniul bancar. Atunci cnd un client al bncii dorete s
transfere bani dintr-un depozit ntr-un cont curent, tranzacia ar putea consta n 3 operaii distincte: se
scade suma din depozit, se mrete suma din contul curent, nregistreaz tranzacia n jurnalul de
tranzacii. Serverul Oracle trebuie s garanteze c toate cele 3 instruciuni SQL sunt executate n aa
fel nct s menin corect balana celor dou conturi. Dac o instruciune dintr-o tranzacie este
mpiedicat s se execute, celelalte instruciuni ale tranzaciei n cauz trebuie anulate.
Adugarea unei nregistrri ntr-un tabel
Pentru a introduce nregistrri noi ntr-un tabel se va utiliza instruciunea INSERT, al crei
format este:
INSERT INTO
tabel [(coloana [,coloana])]
VALUES
(valoare [,valoare]);

unde:
tabel
coloana
valoare

este numele tabelului


este numele coloanei n care se vor introduce valori.
este valoarea corespunztoare coloanei.

Not : Instruciunea INSERT mpreun cu clauza VALUES adaug numai un singur rnd la un
tabel.
Exemplu:
SQL> INSERT INTO dept(deptno, dname, loc)
2 VALUES (50, DEVELOPMENT, DETROIT);

n cazul inserrii unei noi nregistrri care conine valori pentru toate coloanele, lista coloanelor
din instruciunea INSERT nu mai este necesar. Dac aceast list nu este precizat, valorile trebuie
enumerate conform ordinii coloanelor din tabel.
Pentru a insera nregistrri ce conin valori null se poate utiliza una din urmtoarele metode:
-

metoda implicit const n omiterea din lista de coloane a coloanei corespunztoare valorii null.

SQL> INSERT INTO dept(deptno, dname)


2
VALUES (60, MIS);

1 row created.

metoda explicit const n specificarea fie a valorii NULL, fie a irului vid () n lista VALUES.
irul vid va fi utilizat doar pentru date de tip dat calendaristic sau ir de caractere.

SQL> INSERT INTO


dept
2 VALUES (70, FINANCE, NULL);

1 row created.

nainte de introducerea unei valori null ntr-un tabel trebuie verificat dac valoarea null este
permis n coloana corespunztoare, inspectnd cmpul Null? furnizat de comanda DESCRIBE.
Inserarea de valori speciale folosind funcii SQL
Pentru a introduce valori speciale n tabele se pot utiliza pseudocoloane. Exemplul urmtor
nregistreaz informaia pentru angajatul Green n tabelul emp. Pentru a introduce data i ora curent
n cmpul HIREDATE este folosit funcia SYSDATE. O alt funcie ce poate fi utilizat este funcia
USER, care furnizeaz numele utilizatorului curent.
SQL>INSERT INTO emp(empno, ename, job, mgr,hiredate, sal, comm, deptno)
2 VALUES (7196, GREEN, SALESMAN, 7782, SYSDATE, 2000, NULL, 10);

1 row created.

Inserarea valorilor de tip dat calendaristic


Formatul folosit pentru inserarea unei valori de tip dat calendaristic este DD-MON-YY. Dac
o dat calendaristic necesit specificarea altui secol sau a altei ore, se va apela funcia TO_DATE.
Exemplul de mai jos nregistreaz informaia despre angajatul Brian n tabelul emp. Cmpul
HIREDATE primete valoarea February 3, 1997. Dac formatul RR este setat, secolul poate fi diferit
de cel curent.
SQL>INSERT INTO emp VALUES (2269, BRIAN, SALESMAN, 7782,
2
TO_DATE(FEB-3 , 97, 'MON DD, YY'), 1300, NULL, 10);
Formatul funciei TO_DATE este: TO_DATE(date_char, fmt)

unde:
date_char
fmt

este data calendaristic sub forma unui ir de caractere


indic formatul argumentului date_char.

1 row created.

Inserarea de valori folosind variabile de substituie


Este permis scrierea unei instruciuni INSERT care s permit utilizatorului s adauge valori
interactiv, folosind variabilele de substituie SQL*Plus.
Exemplul urmtor nregistreaz informaiile pentru un departament n tabelul dept. Numrul
departamentului, numele i locaia sunt introduse n mod interactiv de ctre utilizator. Pentru valori de
tip dat calendaristic sau ir de caractere, ampersandul (&) i numele variabilei sunt ncadrate de
apostrofuri ( ).
SQL>INSERT INTO dept(deptno, dname, loc)
2 VALUES (&department_id,
3 &department_name, '&location');

Enter value for department_id: 80


Enter value for department_name: EDUCATION
Enter value for location: ATLANTA
1 row created.

Crearea unui script pentru manipularea datelor


Instruciunea SQL mpreun cu variabilele de substituie pot fi salvate ntr-un fiier i ori de
cte ori se va executa fiierul script se va cere introducerea unor valori noi pentru variabile. Mesajele
afiate la cererea introducerii valorilor pot fi modificate prin intermediul comenzii SQL*Plus ACCEPT.
ACCEPT
department_id PROMPT 'Introduceti numarul departamentului:'
ACCEPT
department_name PROMPT 'Introduceti numele departamentului:'
ACCEPT
location PROMPT 'Introduceti orasul:'
INSERT INTO dept(deptno, dname, loc)
VALUES(&department_id,'&department_name','&location');
Introduceti numarul departamentului: 90
Introduceti numele departamentului: PAYROLL
Introduceti orasul: HOUSTON
1 row created.

Variabila de substitutie SQL*Plus nu trebuie precedat de & cnd este referit ntr-o comanda
ACCEPT. Pentru a continua o comanda SQL*PLUS pe linia urmtoare se folosete caracterul -.
Copierea nregistrrilor dintr-un alt tabel
Instruciunea INSERT poate fi utilizat pentru adugarea unor nregistrri ntr-un tabel, valorile
atributelor fiind derivate dintr-un tabel existent. Pentru aceasta se folosete n locul clauzei VALUES o
subinterogare.
SQL> INSERT INTO managers(id, name, salary, hiredate)
2
SELECT empno, ename, sal, hiredate
3
FROM emp
4
WHERE job = 'MANAGER';

3 rows created.

Sintaxa este urmtoarea:


INSERT INTO tabel [ coloana (, coloana) ] subinterogare;

unde: tabel
este numele tabelului;
coloana
este numele coloanei din tabelul n care se face inserarea.
subinterogare este subinterogarea care returneaz nregistrri n tabel.
Not: Numrul i tipul cmpurilor (coloanelor) din lista specificat n instruciunea INSERT trebuie s
corespund numrului i tipului valorilor din subinterogare.

Modificarea datelor dintr-un tabel


nregistrrile existente ntr-un tabel pot fi modificate cu ajutorul instruciunii UPDATE.
UPDATE tabel
SET coloana = valoare [, coloana=valoare]
[WHERE conditie];

unde:
tabel
coloana
valoare
conditie

este numele tabelului;


este numele coloanei din tabelul n care se face modificarea;
este valoarea sau subinterogarea corespunztoare coloanei;
identific nregistrrile care trebuie modificate, fiind alctuit din expresii, nume
de coloane, constante, subinterogri i operatori de comparaie.

Confirmarea unei operaii de modificare se obine prin interogarea tabelului, afind tuplurile
modificate.
Not: Este indicat utilizarea cheii primare pentru a identifica o singur nregistrare. Folosirea altor
coloane poate conduce la modificarea mai multor nregistrri. De exemplu, identificarea unei singure
nregistrri din tabelul emp prin atributul ename poate fi periculoas, deoarece pot exista mai muli
angajai cu acelai nume.
Comanda UPDATE modific numai anumite nregistrri dac este specificat clauza WHERE.
Exemplul urmtor transfer angajatul cu numrul 7782 (Clark) la departamentul 20.
SQL>UPDATE emp
2 SET deptno = 20
3 WHERE empno = 7768;

1 row updated.

Not: Dac se omite clauza WHERE vor fi modificate toate nregistrrile din tabel.
Modificarea nregistrrilor folosind subinterogri dup mai multe coloane
Pentru a modifica simultan mai multe valori ale unui tuplu se va utiliza o subinterogare n
clauza SET a instruciunii UPDATE. Formatul unei astfel de instruciuni UPDATE este:
UPDATE tabel
SET (coloana, coloana, ) =
(SELECT coloana, coloana,
FROM tabel
WHERE conditie)
WHERE conditie;

Urmtoarea instruciune UPDATE modific departamentul i funcia angajatului cu numrul


7698 cu valorile corespunztoare angajatului avnd numrul 7499.
SQL> UPDATE emp
2 SET (job, deptno) = (SELECT job, deptno
3
FROM emp
4
WHERE empno = 7499)
5 WHERE empno = 7698;

1 row updated.

Pentru a efectua modificri ntr-un tabel pe baza valorilor din alt tabel este necesar utilizarea
subinterogrilor n instruciunile UPDATE. Exemplul de mai jos actualizeaz tabelul employee pe
baza valorilor din tabelul emp. Este schimbat numrul de departament pentru toi angajaii cu aceeai
funcie ca cea a angajatului 7788, noul lor numr de departament devenind egal cu al acestuia.

SQL> UPDATE employee


2 SET deptno = (SELECT deptno FROM emp
3
WHERE empno = 7788)
4 WHERE job = (SELECT job FROM emp
5
WHERE empno = 7788);

2 row updated.

tergerea nregistrrilor dintr-un tabel


Pentru tergerea uneia sau a mai multor nregistrri dintr-un tabel se va utiliza instruciunea
DELETE, al crei format este.
DELETE [FROM] table [WHERE conditie];

unde: tabel
conditie

este numele tabelului;


identific nregistrrile care trebuie terse i este alcatuit din expresii, nume de
coloane, constante, subinterogri i operatori de comparaie.

Condiia din clauza WHERE identific nregistrrile ce vor fi terse. Dac se omite clauza
WHERE se vor terge toate nregistrrile din tabel.
De exemplu, pentru tergerea persoanelor angajate dup 1 Ianuarie 1997 se va executa
urmtoarea instruciune DELETE:
SQL> DELETE FROM emp
2 WHERE hiredate > TO_DATE('01.01.97', 'DD.MM.YY');

1 row deleted.

tergerea nregistrrilor folosind valori dintr-un alt tabel


Ca i n cazul instruciunii UPDATE se pot folosi subinterogri pentru a terge nregistrri dintrun tabel, folosind informaiile din alt tabel. Exemplul urmtor terge toi angajaii care lucreaz n
departamentul cu numele SALES. Subinterogarea caut n tabelul dept numrul departamentului
SALES, apoi furnizeaz acest numr interogrii principale care terge nregistrrile corespunztoare
din emp.
SQL> DELETE FROM emp
2
WHERE deptno = (SELECT deptno FROM dept
3
WHERE dname = 'SALES');

6 rows deleted.

nclcarea constrngerii de integritate


ncercarea de a terge o nregistrare care conine un cmp legat de o constrngere de integritate
va fi sancionat cu o eroare.
n exemplul de mai jos se ncearc tergerea departamentului cu numrul 10 din tabelul dept,
dar aceast ncercarea ar provoca o eroare dac numrul de departament ar fi o cheie extern pentru
tabelul emp. Dac nregistrarea printe pe care dorim s o tergem are nregistrri fii, atunci se va
genera mesajul de eroare child record found cu numrul ORA - 02292.
SQL> DELETE FROM dept
2 WHERE deptno = 10;

DELETE FROM dept


*
ERROR at line 1
ORA-02292: integrity constraint(USR.EMP_DEPTNO_FK)
violated - child record found

Problema impunerii unor constrngeri de integritate va fi tratat pe larg ntr-un referat ulterior.

Probleme:
1. S se scrie o interogare care s afieze numele i data angajrii pentru toi angajaii din acelai
departament ca Blake (a se exclude Blake).

2. S se scrie o interogare pentru a afia numrul i numele pentru toi angajaii care ctig mai mult
dect salariul mediu. S se sorteze rezultatele n ordinea descresctoare a salariului.
3. S se scrie o cerere care va afia numerele de nregistrare i numele angajailor din departamentele
n care lucreaz cel puin un angajat al crui nume conine litera T.
4. Afiai numele, numrul departamentului i funcia deinut pentru toi angajaii al cror
departament este situat n Dallas.
5. Afiai numele i salariul tuturor angajailor subordonai lui King.
6. Afiai numrul departamentului, numele i funcia tuturor angajailor din departamentul de vnzri
(Sales).
7. Afiai numrul, numele i salariul tuturor angajailor care ctig mai mult dect salariul mediu i,
n plus, lucreaz ntr-un departament care deine cel puin un angajat al crui nume conine litera
T.
8. Scriei o interogare care s afieze numele, numrul departamentului i salariul oricrui angajat al
crui numr de departament i salariu s se potriveasc cu numrul departamentului i salariul
oricrui angajat care poate percepe comision.
9. Afiai numele, numele departamentului i salariul oricrui angajat al crui salariu i comision
coincide cu salariul i comisionul oricrui angajat ce lucreaz n Dallas.
10. Scriei o interogare care s afieze numele, data angajrii i salariul pentru toi angajaii care au
acelai salariu i comision ca angajatul Scott.
11. Scriei o interogare care s afieze angajaii care ctig un salariu mai mare dect al oricrui
angajat cu funcia CLERK. Sortai rezultatele descresctor dup salariu.
12. Scriei un fiier script pentru a afia numele fiecrui angajat, funcia i numele departamentului
pentru acei angajai care lucreaz n localitatea furnizat la prompt de utilizator. Condiia de
cutare a localitii trebuie s fie case-insensitive (s nu depind de tipul caracterelor: majuscule
sau litere mici). Salvai fiierul script cu numele p12.sql .
Indicaie: pentru a efectua o cutare case-insensitive se va utiliza funcia LOWER (transform irul
argument n caractere mici) sau UPPER (transform irul argument n majuscule).
13. Modificai p12.sql pentru a crea un raport ce conine numele departamentului, numele angajatului,
data angajrii, salariul i salariul anual pentru toi angajaii dintr-o anumit localitate, introdus de
utilizator de la tastatur. Se eticheteaz coloanele DEPARTMENT NAME, EMPLOYEE NAME,
START DATE, SALARY i ANNUAL SALARY, plasnd etichetele formate din dou iruri pe
mai multe linii. Se salveaz fiierul script cu numele p6.sql .
14. Executai fiierul script p14.sql pentru a crea tabelul MY_EMPLOYEE, care va fi utilizat de
urmtoarele problemele.
15. Descriei structura tabelului MY_EMPLOYEE pentru a identifica numele cmpurilor.
16. Adugai prima nregistrare din tabelul de mai jos.
ID
1
2
3
4
5

LAST_NAME
Patel
Dancs
Biri
Newman
Ropeburn

FIRST_NAME
Ralph
Betty
Ben
Chad
Audry

USERID
rpatel
bdancs
bbiri
cnewman
aropebur

SALARY
795
860
1100
750
1550

17. Creai un script numit loademp.sql pentru a insera nregistrri n tabelul MY_EMPLOYEE n
mod interactiv. Cerei utilizatorului numrul de identificare (ID), prenumele (FIRST_NAME),
numele de familie (LAST_NAME) i salariul (SALARY) fiecrui angajat. Concatenai prima litera a
prenumelui i primele 7 caractere ale numelui de familie pentru a crea USERID.
Indicaie: pentru extragerea unui subir din alt ir se va utiliza funcia SQL
SUBSTR(string, m, n)
unde:
string este un ir de caractere
m
poziia la care ncepe subirul
n
numrul de caractere din subir
Daca m = 0, se va considera m = 1.

Dac m > 0, Oracle va cuta de la nceputul irului string.


Dac m < 0, Oracle va cuta de la sfritul irului string.
Dac n este omis, Oracle va returna toate caracterele din string. Dac n < 1, se va returna null.
Exemplu: SUBSTR(ABCDEFG,3,4) = CDEF
18. Inserai urmtoarele trei nregistrri din tabelul de mai sus n tabelul MY_EMPLOYEE prin
intermediul fiierului script creat la problema 5.
19. Modificai numele de familie al angajatului avnd ID = 3 n Drexler.
20. Modificai salariul la 1000 pentru toi cei cu salariul < 900.
21. tergei nregistrarea corespunztoare lui Betty Dancs din tabelul MY_EMPLOYEE.
22. tergei toate nregistrrile din tabel.

Seciune opional
Tranzacii n bazele de date
Serverul Oracle asigur consistena datelor pe baza tranzaciilor. Tranzaciile ofer un plus de flexibilitate i
control n modificarea datelor i asigur consistena datelor n eventualitatea unei erori n sistem sau n procesul utilizator.
Tranzaciile constau din instruciuni ale LMD (Limbajul de Manipulare a Datelor) care produc o modificare
consistent a datelor. De exemplu, un transfer de fonduri ntre dou conturi ar trebui s includ debitarea unui cont i
creditarea celuilalt cu aceeai sum de bani. Ambele aciuni ar trebui fie s reueasc mpreun, fie s eueze mpreun.
Operaia de creditare nu trebuie s fie efectuat fr ca cea de debit s aib succes.

Tipuri de tranzacii
Tip

Descriere

Limbajul de manipulare a datelor (LMD)

Const din orice numr de instruciuni LMD pe care serverul


Oracle le trateaz ca fiind o singur unitate logic de lucru.
Const dintr-o singur instruciune LDD

Limbajul de definire a datelor (LDD)

O tranzacie ncepe cnd este ntlnit prima instruciune SQL executabil i se termin n momentul apariiei
unuia din urmtoarele evenimentele:

se execut instruciunea COMMIT sau ROLLBACK;


se execut o instruciune LDD, cum ar fi, de exemplu, instruciunea CREATE;
se execut o instruciune LCD (instuciuni de acordare provilegii);
utilizatorul prsete mediul SQL*Plus;
apare o eroare de sistem.

Dup ncheierea unei tranzacii, urmtoarea tranzacie va ncepe automat la ntlnirea primei instruciuni SQL.
Modificrile realizate de o instruciune LDD sunt salvate automat i de aceea ncheie n mod implicit o tranzacie.

Comenzi pentru controlul explicit al tranzaciilor


Logica tranzaciilor poate fi controlat cu ajutorul instruciunilor COMMIT, SAVEPOINT i ROLLBACK.
Tranzacie
INSERT
COMMIT

UPDATE

Punct salvare A

INSERT

DELETE

Punct salvare B
ROLLBACK la punctul B
ROLLBACK la punctul A
ROLLBACK

Comand
COMMIT
SAVEPOINT nume
ROLLBACK [TO
SAVEPOINT nume]

Descriere
ncheie actuala tranzacie, toate modificrile efectuate asupra datelor devenind
permanente.
Marcheaz un punct de ntoarcere n cadrul tranzaciei curente.
Instruciunea ROLLBACK ncheie tranzacia curent pierzndu-se toate modificrile
temporare asupra datelor. Instruciunea ROLLBACK TO SAVEPOINT nume terge
punctul de ntoarcere specificat de nume i anuleaz toate schimbrile survenite dup el.

Procesarea implicit a tranzaciilor

Salvarea automat a modificrilor are loc n urmtoarele circumstane:


- se execut o comand LDD;
-

se prsete normal mediul SQL*Plus, fr a executa explicit instruciunea COMMIT sau ROLLBACK

Un rollback automat se produce n condiiile unei terminri anormale a sesiunii SQL*Plus sau n cazul unei cderi
a sistemului.

Not: n SQL*Plus este disponibil o a treia comand, instruciunea AUTOCOMMIT, ce poate fi setat ON sau OFF. Dac
este setat pe ON, fiecare instruciune LMD conduce la salvarea modificrilor imediat ce este executat. n acest caz nu se
mai poate reface starea anterioar (un rollback nu mai este posibil). Dac este setat pe OFF, instruciunea COMMIT poate fi
executat explicit. De asemenea, COMMIT este executat odat cu o instruciune LDD sau la prsirea mediului SQL*Plus.
Fiecare modificare efectuat n timpul unei tranzacii este temporar pn n momentul execuiei comenzii
COMMIT.
Starea datelor nainte de un COMMIT sau ROLLBACK:

operaiile de manipulare a datelor afecteaz iniial buffer-ul bazei de date; de aceea, starea iniiala a datelor
poate fi reconstituit;
utilizatorul curent poate revedea schimbrile efectuate prin interogarea tabelelor;
ali utilizatori nu pot vedea modificrile fcute de utilizatorul curent. Serverul Oracle asigur consistena
datelor la citire pentru a se asigura c fiecare utilizator vede datele aa cum existau ele n momentul ultimei
salvri.
nregistrrile afectate de modificri sunt protejate (locked), astfel nct ali utilizatori s nu poat efectua
modificri asupra lor.

Starea datelor dup execuia instruciunii COMMIT:

modificrile asupra datelor sunt salvate n baza de date;


starea anterioar a datelor nu mai poate fi restaurat;
toi utilizatorii pot vedea rezultatele tranzaciei;
protecia nregistrrilor modificate este nlturat; astfel, aceste nregistrri pot fi modificate de ali utilizatori;
toate punctele de ntoarcere sunt terse.

Urmtorul exemplu creeaz un nou departament ADVERTISING cu cel puin un angajat i salveaz modificrile
fcute.
SQL> INSERT INTO department(deptno, dname, loc)
2 VALUES (50, 'ADVERTISING','MIAMI');

1 row created.

SQL> UPDATE employee


2 SET deptno = 50
3 WHERE empno = 7876;
SQL> COMMIT;

1 row updated.

Commit complete.

Anularea modificrilor (refacerea strii iniiale)


Anularea modificrilor temporare se face cu ajutorul instruciunii ROLLBACK. Dup un ROLLBACK:

modificrile efectuate sunt anulate;


este refcut starea anterioar a datelor;
este ridicat protecia asupra nregistrrilor implicate n tranzacie.

Ca exemplu, n ncercarea de a terge o nregistrare din tabelul emp, se poate ntmpla s tergem accidental
ntregul tabel. Aceast greeal se poate corecta, urmnd ca apoi s se execute instruciunile corecte i s se salveze
modificrile.
SQL> DELETE FROM emp;

14 rows deleted.

SQL> ROLLBACK;

Rollback complete.

SQL> DELETE FROM emp


2 WHERE empno = 7902;
SQL> SELECT *
2 FROM emp
3 WHERE empno = 7902;
SQL> COMMIT;

1 row deleted.
No rows selected.

Commit complete.

Anularea modificrilor pn la un punct de salvare


Crearea unui marcaj n cadrul tranzaciei curente se poate face cu ajutorul instruciunii SAVEPOINT. Astfel,
tranzacia poate fi mprit n seciuni mai mici, oferind posibilitatea anulrii modificrilor temporare pn la acel marcaj
folosind instruciunea ROLLBACK TO SAVEPOINT nume_savepoint. Dac se creeaz un al doilea punct de salvare
cu acelai nume ca unul anterior, punctul anterior de salvare este ters.
SQL> UPDATE
SQL> SAVEPOINT update_done;

Savepoint created.

SQL> INSERT
SQL> ROLLBACK TO update_done;

Rollback complete.

Instruciunea ROLLBACK anterioar va anula modificrile efectuate de instruciunea INSERT.

Rollback la nivel de comand


Se poate anula o parte din tranzacie printr-un rollback implicit dac este detectat o eroare la execuia unei
instruciuni. Dac o singur instruciune LMD eueaz n timpul execuiei unei tranzacii, efectul ei este anulat printr-un
rollback la nivel de comand, dar schimbrile efectuate de comenzi anterioare nu vor fi anulate. Ele pot fi salvate
(COMMIT) sau anulate (ROLLBACK) n mod explicit de ctre utilizator.
Oracle execut o comand COMMIT implicit nainte i dup orice comand LDD. n cazul n care o instruciune
LDD nu se execut cu succes, nu pot fi anulate instruciunile anterioare pentru c serverul a executat un COMMIT.

Consistena la citire
Utilizatorii unei baze iniiaz dou tipuri de acces la baza de date:

operaii de citire (instruciunea SELECT);


operaii de scriere (instruciunile INSERT, UPDATE, DELETE).

Consistena la citire este necesar pentru ca:

utilizatorii care citesc / modific datele s aib o vedere consistent asupra datelor;
utilizatorii care citesc datele s nu vad datele care sunt n curs de modificare;
utilizatorii care modific datele s aib sigurana c schimbrile n baza de date se fac n mod consistent;
modificrile efectuate de un utilizator s nu intre n conflict sau s afecteze modificrile efectuate de un alt
utilizator.

Scopul consistenei la citire este s asigure c fiecare utilizator vede datele n starea n care erau la ultima salvare,
nainte de execuia unei instruciuni LMD.

Implementarea consistenei la citire


Consistena la citire este o implementare automat ce pstreaz o copie parial a bazei de date n segmente de
rollback.
Cnd se realizeaz o operaie de inserare, actualizare sau tergere asupra bazei de date serverul Oracle copie
datele, nainte de modificare, ntr-un segment de rollback. Toi utilizatorii, cu excepia celui care a iniiat modificarea, vd

baza de date n starea anterioar nceperii modificrii; de fapt ei vd copia datelor iniiale din segmentul de rollback. Cnd
rezultatul unei instruciuni LMD este salvat, modificarea din baza de date devine vizibil oricrui utilizator ce execut o
instruciune SELECT. Spaiul ocupat de datele vechi din segmentul de rollback este eliberat pentru a fi reutilizat.
Dac tranzacia este anulat, modificrile sunt la rndul lor anulate:

datele originale din segmentul rollback sunt rescrise n tabel;


toi utilizatorii vd baza de date aa cum era nainte de nceperea tranzaciei.

Comenzi SQL*Plus pentru formatarea modului de afiare a rezultatelor


Urmtoarele comenzi pot fi utilizate pentru a controla anumite caracteristici de afiare ale unui raport:
Comanda

Descriere

COL[UMN] [coloana optiune]


TTI[TLE] [text | OFF | ON ]
BTI[TLE] [text | OFF | ON ]
BRE[AK] [ON elem_raport]

Controleaz formatul coloanelor


Specific un header care va apare n partea superioar a fiecrei pagini
Specific un footer care va apare n partea de jos a fiecrei pagini
Anuleaz valorile duplicat i mparte liniile din raport. Pentru mai multe detalii
executai comanda HELP break.

Indicaii: - toate comenzile de formatare rmn valabile pn la sfritul sesiunii SQL*Plus sau pn n momentul rescrierii
sau tergerii acestor opiuni.
- dup fiecare raport se vor restaura setrile SQL*Plus la valorile implicite.
- dac se va crea un alias pentru o coloan, referirile ulteriore se vor face la acel alias, nu la numele coloanei.

Comanda COLUMN
COL[UMN] [ {coloana | alias} [optiuni]]

Optiune
CLE[AR]
FOR[MAT] format
HEA[DING] text
JUS[TIFY] {aliniere}
NOPRI[NT]
NUL[L] text
PRI[NT]
TRU[NCATED]
WRA[PPED]

Descriere
anuleaz orice format de coloan
modific formatul de afiare al datelor din coloan
seteaz titlul coloanei. Dac nu este utilizat opiunea JUSTIFY, o linie vertical (|) va
fora trecerea pe rndul urmtor a textului rmas din header.
aliniaz titlul coloanei la stnga, centrat sau la dreapta
ascunde coloana.
indic textul ce va fi afiat pentru valori null
arat coloana
trunchiaz irul la sfritul primei linii de afiaj
transfer sfritul de ir pe linia urmtoare

Exemple de utilizare a comenzii COLUMN:


COLUMN ename HEADING Employee|Name FORMAT A15
noua denumire a coloanei ename este Employee Name (scris pe dou
rnduri), iar pentru valori se aloc un spaiu de 15 caratere
COLUMN sal JUSTIFY LEFT FORMAT $99,999.00
COLUMN mgr FORMAT 99999999 NULL No manager
COLUMN ename - afieaz setarea curent pentru coloana ENAME
COLUMN ename CLEAR anuleaz setrile pentru coloana ENAME
Modele de format pentru coloane:
Element
An
9
0
$
L
.
,

Descriere
Seteaz limea zonei de afiare la n caractere
O singur cifr, cu suprimarea valorilor 0
prefixeaz numrul cu un zero
Simbolul pentru dolar
Moneda local
Poziia punctului zecimal
Virgul pentru separarea cifrei zecilor de mii

Exemplu
N/A
999999
099999
$9999
L9999
9999.99
9,999

Rezultat
N/A
1234
01234
$1234
L1234
1234.00
1,234

Comenzile TTITLE i BTITLE


TTI[TLE]

[text | OFF | ON]

BTI[TLE]

[text | OFF | ON]

unde: text

reprezint titlul raportului. Se introduc apostrofuri dac textul conine mai


cuvinte.

multe

Comanda TTITLE este utilizat pentru a formata header-ul paginii, iar comanda BTITLE pentru footers.

Procedura de creare a unui fiier script care s execute un raport


1. Se creeaz instruciunea SQL SELECT
2. Se salveaza instruciunea SELECT ntr-un fiier script
3. Se ncarc fiier script ntr-un editor text
4. Se adaug comenzile de formatare naintea instruciunii SELECT
5. Se verific dac dup instruciunea SELECT urmeaz caracterul / sau ;
6. Dup instruciunea SELECT se anuleaz comenzile de formatare
7. Se salveaz fiierul script
8. Se execut comanda START fisier pentru a executa script-ul

Exemplu de raport
Fri Oct 24

page

Employee
Report
Job
Category
.............................................
CLERK
CLERK
CLERK
CLERK
MANAGER
MANAGER
MANAGER
SALESMAN
SALESMAN
SALESMAN
SALESMAN

Employee
...........................................
ADAMS
JAMES
MILLER
SMITH
BLAKE
CLARK
JONES
ALLEN
MARTIN
TURNER
WARD

Salary
................................
$1,100.00
$950.00
$1,300.00
$800.00
$2,850.00
$2,450.00
$2,975.00
$1,600.00
$1,250.00
$1,500.00
$1,250.00

Confidential
S se creeze un fiier script pentru a executa un raport care afieaz funcia, numele i salariul fiecrui angajat al
crui salariu este sub 3000$. Se adaug ca header irul Employee Report, centrat, pe dou rnduri i ca footer irul
Confidential, centrat. Se redenumete coloana JOB Job category, desprit pe dou rnduri. Se redenumete coloana
angajailor Employee. Se redenumete coloana pentru salariu Salary i se alege formatul corespunztor exemplului
$2,500.00
TTITLE
EmployeeIReport
BTITLE
Confidential
COLUMN
job
HEADING Job|Category Format
A15
COLUMN
ename HEADING Employee
Format
A15
COLUMN
sal
HEADING Salary Format $99,999.99
REM ** Insert SELECT statement
SELECT
job,ename,sal
FROM scott.emp
WHERE sal<3000
ORDER BY job,ename
Not: REM indic un comentariu n SQL*Pus

Crearea i gestionarea tabelelor.


Definirea constrngerilor de integritate n SQL
Obiective
Scopul acestui referat este de a prezenta instruciunile LDD ce pot fi utilizate pentru modificarea
schemei logice a unei baze de date (crearea de tabele, modificarea structurii unui tabel,
redenumirea unui tabel). De asemenea, este indicat modul n care pot fi utilizate constrngerile
de integritate pentru a preveni introducerea unor date invalide n baza de date. Dup parcurgerea
acestui referat, studentul va deine cunotinele necesare:

descrierii obiectelor din baza de date;


pentru crearea unui tabel;
descrierii tipurilor de date ce pot fi utilizate n momentul specificrii definiiilor de coloane;
modificrii structurii unui tabel;
tergerii, redenumirii i trunchierii tabelelor.
definirii constrngerilor de integritate;

O baz de date Oracle poate conine structuri de date multiple. Fiecare structur trebuie definit
n faza de proiectare a bazei de date, astfel nct s poat fi creat n momentul construirii bazei
de date. Tipurile de obiecte ale unei baze de date sunt date n tabelul urmtor.
Obiect
Tabel
Vedere
Secven
Index
Sinonim

Descriere
Unitatea de baz pentru stocarea datelor; compus
din linii i coloane.
Reprezentare logic a unei submulimi de date
dintr-unul sau mai multe tabele.
Genereaz valori pentru chei primare.
mbuntete performanele n cazul unor
interogri.
Furnizeaz alte nume obiectelor.

Instruciunea CREATE TABLE


Aceast instruciune face parte din Limbajul de Definire a Datelor (LDD) i permite crearea unui
tabel n care vor fi stocate date. n general, instruciunile LDD reprezint o submulime a
instruciunilor SQL i sunt utilizate pentru crearea, modificarea i tergerea obiectelor unei baze
de date Oracle. Pentru ca un utilizator s poat crea un tabel, el trebuie s dein dreptul CREATE
TABLE i o zon de stocare n care va crea obiecte de tip tabel. Dreptul de a crea un tabel este
acordat de administratorul bazei de date prin intermediul instruciunilor LCD (Limbajul de
Control al Datelor) GRANT i REVOKE.

Sintaxa instruciunii CREATE TABLE este urmtoarea:


CREATE TABLE [schema.]tabel
(col tip_date [DEFAULT expr]
[, col tip_date [DEFAULT expr] ...]);
unde:
schema
tabel
DEFAULT expr
col
tip_date

coincide cu numele utilizatorului proprietar al tabelului;


numele tabelului;
specific o valoare implicit;
numele coloanei;
tipul de date i lungimea coloanei col.

Convenii pentru denumirea tabelelor

numele trebuie sa nceap cu o liter;


numele unui tabel poate avea lungimea de 1-30 caractere;
caracterele permise sunt numai A-Z, a-z, 0-9, _, $ i #;
numele unui tabel nu trebuie s coincid cu numele altor obiecte din baza de date (obiecte ale
aceluiai utilizator);
nu trebuie sa fie un nume rezervat Oracle.

Opiunea DEFAULT
Unei coloane i se poate asigna o valoare implicit utiliznd opiunea DEFAULT. Aceast opiune
previne introducerea unor valori NULL n tabel n cazul inserrii unei linii care nu specific o
valoare pentru coloana n cauz. Valoarea implicit poate fi o valoare literal, o expresie sau o
funcie SQL, cum ar fi SYSDATE sau USER, dar nu poate fi cea a unei alte coloane sau o
pseudocoloan (cum ar fi NEXTVAL sau CURRVAL). Valoarea implicit trebuie s corespund
tipului de date al coloanei.
hiredate DATE DEFAULT SYSDATE,
Pentru coloana hiredate s-a definit valoarea implicit returnat de funcia SYSDATE (data
sistemului).
Exemplul urmtor creeaz tabelul dept, avnd trei coloane: DEPTNO, DNAME i LOC. Pentru a
se confirma crearea tabelului dept se va executa comanda DESCRIBE.
SQL> CREATE TABLE DEPT
2
(deptno NUMBER(2),
3
dname VARCHAR(14),
4
loc
VARCHAR(13));
Table created.
SQL> DESCRIBE dept
Name
---------------DEPTNO
DNAME
LOC

Null?
Type
--------- ---------NOT NULL NUMBER(2)
VARCHAR(14)
VARCHAR(13)
2

Interogarea dicionarului de date


Rezultatele execuiei instruciunilor LDD sunt memorate n dicionarul de date. Prin interogarea
dicionarului de date se pot obine diverse informaii despre obiectele aparinnd unui utilizator.
Tabelele cele mai utilizate din dicionarul de date sunt USER_TABLES (conine informaii
despre tabelele create de utilizatorul curent), USER_OBJECTS (conine informaii despre toate
obiectele create de utilizatorul curent) i USER_CATALOG.

Afiarea tabelelor unui utilizator:


SQL> SELECT table_name
2 FROM user_tables;

Afiarea obiectelor distincte aparinnd unui utilizator:


SQL> SELECT DISTINCT object_name, object_type
2 FROM user_objects;

Afiarea tabelelor, vederilor, sinonimelor i secvenelor unui utilizator:


SQL> SELECT *
2 FROM user_catalog;

Deoarece tabelul USER_CATALOG are definit un sinonim, numit CAT, se poate folosi acest
nume n loc de USER_CATALOG.
SQL> SELECT *
2 FROM CAT;

Tipuri de date
Tipurile de date ce pot fi utilizate n definiiile de coloane sunt prezentate n tabelul urmtor:
Tipul de data
Descriere
VARCHAR2(size) Dat de tip ir de caractere, de lungime variabil (trebuie specificat
dimensiunea maxim size; valoarea implicit este 1, iar cea maxim
4000)
Dat de tip ir de caractere de lungime size fix (valoarea implicit i
CHAR(size)
cea minim este 1, iar cea maxim 2000)
Numr avnd p cifre i s cifre zecimale. (p poate lua valori ntre 1 i
NUMBER(p,s)
38, s ntre 84 i 127)
Valori de tip dat calendaristic i timp cuprinse ntre Ianuarie 1, 4712
DATE
B.C. i Decembrie 31, 9999 A.D.
Dat de tip ir de caractere de lungime variabil, dimensiunea maxim
LONG
fiind 2 Gb.
Dat de tip ir de caractere pe 1 octet, dimensiunea maxim fiind 4 Gb.
CLOB
Dat binar de dimensiune size octei. Dimensiunea maxim este de
RAW(size)
2000 octei. Valoarea size trebuie specificat.
Dat binar de dimensiune maxim 2 Gb.
LONG RAW
Dat binar de dimensiune maxim 4 Gb.
BLOB
Conine un pointer ctre un fiier binar extern bazei de date ce poate
BFILE
avea dimensiunea maxim de 4 Gb.
3

Crearea unui tabel utiliznd o subinterogare


A doua metod de creare a unui tabel const n utilizarea clauzei AS subinterogare n
instruciunea CREATE TABLE, care creeaz tabelul i insereaz nregistrrile furnizate de
subinterogare. Sintaxa acestei instruciuni este:
SQL> CREATE TABLE tabel
2
(coloana [, coloana ])
3 AS subinterogare;
unde:
tabel
coloana

numele tabelului;
numele coloanei mpreun cu valoare implicit i constrngeri de
integritate (ultimele dou elemente sunt opionale);
subinterogare instruciunea SELECT care furnizeaz mulimea de nregistrri ce trebuie
inserate n tabel.

Instruciunea urmtoare creeaz tabelul dept30, insernd informaii despre angajaii ce


lucreaz n departamentul 30. Structura tabelului dept30 este dat de lista de coloane din
clauza SELECT.
SQL> CREATE TABLE dept30
2 AS
3
SELECT empno, ename, sal*12 ANNSAL, hiredate
4
FROM emp
5
WHERE deptno=30;
Table created.
SQL> DESCRIBE dept30
Name
----------EMPNO
ENAME
ANNSAL
HIREDATE

Null?
Type
------------- ----------NOT NULL
NUMBER(4)
VARCHAR(10)
NUMBER
DATE

Instruciunea ALTER TABLE


Aceast instruciune este util dac se urmrete modificarea structurii unui tabel prin:
adugarea unei coloane;
tergerea unei coloane;
modificarea definiiei unei coloane existente;
definirea unei valori implicite pentru o coloan.
Pentru adugarea unei coloane se va utiliza instruciunea ALTER TABLE mpreun cu clauza
ADD, iar pentru modificarea unei coloane se va utiliza clauza MODIFY. Dac se dorete
eliminarea unor coloane din definiia tabelului se va utiliza clauza DROP.
4

SQL> ALTER TABLE tabel


2 ADD (coloana tip_date [DEFAULT expr]
3
[, coloana tip_date ...]);
SQL> ALTER TABLE tabel
2 MODIFY (coloana tip_date [DEFAULT expr]
3
[, coloana tip_date ...]);
SQL> ALTER TABLE tabel
2 DROP (coloana [, coloana ]);
unde:
tabel
coloana
tip_date
DEFAULT expr

nume tabel;
nume coloan;
tipul de date i dimensiunea;
specific valoarea implicit pentru coloan.

Urmtorul exemplu introduce o nou coloan n tabelul emp30, numele acestei coloane fiind
job, iar tipul de date asociat este varchar(9). Pentru verificare se utilizeaz instruciunea
SELECT.
SQL> ALTER TABLE dept30
2 ADD (job VARCHAR(9));
Table altered.
SQL> SELECT * FROM dept30;
EMPNO ENAME
------ -------7698
BLAKE
7654
MARTIN
7499
ALLEN
7844
TURNER

6 rows selected

ANNSAL
------34200
15000
19200
18000

HIREDATE
--------01-MAY-81
28-SEP-81
20-FEB-81
08-SEP-81

JOB
-----

Observaii:
Cu ajutorul instruciunii ALTER TABLE se pot aduga, modifica i terge coloane n cazul
inserrii unei coloane nu se poate specifica locul de apariie al acesteia n schema tabelului. Noua
coloan devine automat ultima coloan. Dac tabelul conine nregistrri n momentul adugrii
unei coloane noi, atunci noua coloan va fi iniializat cu valori NULL pentru toate nregistrrile.
Se pot modifica specificaiile coloanelor utiliznd instruciunea ALTER TABLE cu clauza
MODIFY. Modificrile permise sunt schimbarea tipului de date, a dimensiunii, a valorii iniiale i
impunerea unei constrngeri NOT NULL.
SQL> ALTER TABLE dept30
2 MODIFY (ename VARCHAR(15));
Table altered.
5

Observaii:
se poate mri precizia sau scala unei coloane numerice;
se poate micora limea unei coloane dac aceasta conine numai valori NULL sau dac
tabelul nu are nregistrri;
se poate schimba tipul de date dac n coloana respectiv exist numai valori NULL;
se poate converti o coloan de tip CHAR la tipul VARCHAR2 sau invers dac aceasta
conine valori NULL sau dac nu se modific limea;
schimbarea valorii implicite pentru o coloan afecteaz numai inserrile ulterioare n tabel.

tergerea unui tabel


Comanda DROP TABLE terge definiia unui tabel. Atunci cnd se terge un tabel, baza de date
pierde toate nregistrrile din tabel, mpreun cu indecii asociai acestuia.
Sintaxa instruciunii DROP TABLE este:
DROP TABLE nume_tabel;
Exemplu:
SQL> DROP TABLE dept30;
Table dropped.
Observaii:

toate datele sunt terse;


orice obiect dependent de tabel (vedere sau sinonim) va continua s existe, dar va fi invalid;
orice tranzacie n curs va fi finalizat;
numai utilizatorul care a creat tabelul sau cel care are privilegiul DROP ANY TABLE poate
terge un tabel.

Redenumirea unui obiect din baza de date


Pentru a modifica numele unui tabel, a unei vederi, secvene sau sinonim se utilizeaz
instruciunea RENAME.
RENAME nume_vechi TO nume_nou;
SQL> RENAME dept30 TO department;
Table renamed.
Not: Numai proprietarul poate modifica numele unui obiect.

Trunchierea unui tabel


Instruciunea TRUNCATE TABLE face parte din LDD i terge toate nregistrrile din tabelul
specificat, elibernd spaiul folosit de tabel. Operaiunea este ireversibil, n sensul c
instruciunea ROLLBACK nu va restaura coninutul tabelului.
6

TRUNCATE TABLE nume_tabel;


SQL> TRUNCATE TABLE department;
Table truncated.
Pentru tergerea nregistrrilor dintr-un tabel se poate utiliza instruciunea DELETE, dar aceasta
instruciune nu elibereaz spaiul de stocare.

Adugarea comentariilor de tabel i de coloan


Se pot aduga comentarii avnd maxim 2000 octei unei coloane, unui tabel sau unei vederi
utiliznd instruciunea COMMENT.
COMMENT ON <TABLE tabel | COLUMN tabel.col>
IS text;
unde:
tabel
col
text

numele tabelului;
numele coloanei din tabel;
textul comentariului, ncadrat de apostrofuri ( ).

Comentariile sunt stocate n dicionarul de date i pot fi vizualizate n coloana COMMENTS a


uneia din urmtoarele vederi:
-

ALL_COL_COMMENTS; - conine toate comentariile de coloane


USER_COL_COMMENTS; - conine comentariile asociate coloanelor utilizatorului curent
ALL_TAB_COMMENTS; - conine toate comentariile de tabele
USER_TAB_COMMENTS. - conine toate comentariile asociate tabelelor utilizatorului curent
SQL> COMMENT ON TABLE emp
2 IS Employee Information;
Comment created.

Se poate renuna la un comentariu, setndu-l ca fiind irul vid ().


SQL> COMMENT ON TABLE emp IS ;

Impunerea constrngerilor de integritate n SQL


Serverul Oracle utilizeaz constrngerile de integritate pentru prevenirea introducerii unor date
invalide n tabele. Constrngerile pot fi utilizate pentru:
- forarea unor reguli la nivel de tabel atunci cnd o linie este inserat, actualizat sau tears;
constrngerea trebuie satisfcut pentru ca operaia s se termine cu succes.
- prevenirea tergerii unui tabel dac exist dependene din alte tabele.
- oferirea unor reguli pentru alte medii Oracle, cum ar fi Developer/2000.

Exist cinci tipuri de constrngeri de integritate ce pot fi impuse:


-

- specific faptul c o coloan nu poate conine o valoare NULL;


- specific o coloan (o combinaie de coloane) a crei valoare
(combinaie de valori) trebuie s fie unic pentru toate nregistrrile din
tabel;
PRIMARY KEY - identific unic fiecare nregistrare;
FOREIGN KEY - stabilete o legtur pe baza unei chei externe ntre o coloan
din tabel i o coloan din tabelul referit;
CHECK - specific o condiie ce trebuie satisfcut de fiecare nregistrare.
NOT NULL
UNIQUE

Toate constrngerile definite de un utilizator sunt pstrate n dicionarul de date. Pentru


vizualizarea constrngerilor impuse unui tabel putem interoga dicionarul de date, mai exact
vederea USER_CONSTRAINTS.
Definirea constrngerilor
Sintaxa instruciunii CREATE ce impune constrngeri asupra unei coloane sau asupra unui tabel
este:
CREATE TABLE [schema.]tabel
( coloana tip_date [DEFAULT expr]
[constrangere_coloana],

[constrangere_tabel]);
unde:
schema
tabel
DEFAULT expr
coloana
tip_date
constrangere_coloana
constrangere_tabel

numele utilizatorului proprietar;


numele tabelului;
specific o valoare implicit, dac este omis o valoare
pentru atribut la inserare;
numele coloanei;
tipul de date i dimensiunea;
constrngere de integritate ca parte a definiiei de coloan;
constrngere de integritate ca parte a definiiei tabelului.

CREATE TABLE emp(


empno
NUMBER(4),
ename
VARCHAR(2),

deptno
NUMBER(7,2) NOT NULL,
CONSTRAINT emp_empno_pk
PRIMARY KEY(EMPNO));
Constrngerile sunt de obicei definite n acelai timp cu tabelul. Ele pot fi adugate i dup
crearea tabelului cu ajutorul instruciunii ALTER TABLE. Constrngerile pot fi definite la unul
din urmtoarele dou nivele:
Nivel
Descriere
constrngere
Coloan
face referire la o singur coloan i poate defini orice tip de constrngere
Tabel
face referire la una sau mai multe coloane i este definit separat de definiiile
coloanelor din tabel; poate defini orice tip de constrngere, cu excepia
constrngerii NOT NULL
8

Constrngere la nivel de coloan


coloana [CONSTRAINT nume_constrangere] tip_constrangere,

Constrngere la nivel de tabel


coloana , ...
[CONSTRAINT nume_constrangere] tip_constrangere
(coloana, ...), ...

unde:
nume_constrangere
tip_constrangere

este numele constrngerii;


este tipul constrngerii.

n definiia constrngerii utilizatorul poate furniza un nume sugestiv pentru aceasta. n acest caz
constrngerea trebuie definit la nivel de tabel. Dac unei constrngeri nu i se furnizeaz un
nume, serverul Oracle genereaz un nume dup formatul SYS_Cn, unde n este un ntreg care
determin unicitatea numelui.
Constrngerea NOT NULL
Constrngerea NOT NULL indic faptul c valoarea NULL nu este permis n coloana afectat de
constrngere. Coloanele fr constrngeri NOT NULL pot conine, implicit, valori NULL.
EMP
EMPNO
7839
7698
7782
7566

ENAME
KING
BLAKE
CLARK
JONES

Constrngere NOT NULL


(nici o nregistrare nu
poate conine o valoare
NULL n aceast coloan)

JOB
PRESIDENT
MANAGER
MANAGER
MANAGER

COMM

Absena constrngerii NOT


NULL (orice nregistrare
poate conine valoarea
NULL pentru aceast
coloan)

DEPTNO
10
30
10
20

Constrngere NOT
NULL

Constrngerea NOT NULL poate fi specificat numai la nivel de coloan.


SQL> CREATE TABLE emp(
2
empno
NUMBER(4)
3
ename
VARCHAR2(10) NOT NULL
4
job
VARCHAR2(9)
5
mgr
NUMBER(4)
6
hiredate
DATE
7
sal
NUMBER(7,2)
8
comm
NUMBER(7,2)
9
deptno
NUMBER(7,2) NOT NULL);

n exemplul de mai sus se aplic constrngerea NOT NULL coloanelor ename i deptno din
tabelul emp. Deoarece aceste constrngeri nu au nume, server-ul Oracle va crea automat nume
pentru ele.
Numele unei constrngeri poate fi indicat n definiia constrngerii, doar dac aceasta apare la
nivelul tabelului (dup definirea tuturor coloanelor):
deptno NUMBER(7,2)
CONSTRAINT emp_deptno_nn NOT NULL
Constrngerea UNIQUE
constrngere UNIQUE
DEPT
DEPTNO
10
20
30
40

DNAME
ACCOUNTING
RESEARCH
SALES
OPERATIONS

LOC
NEW YORK
DALLAS
CHICAGO
BOSTON

Insert
50
60

SALES

nu e permis
( DNAME=SALES
exist deja)

DETROIT
BOSTON
Permis

O constrngere de integritate de tip cheie unic cere ca fiecare valoare din coloan sau din
mulimea de coloane s fie unice dou nregistrri ale tabelului nu pot avea valori duplicat
corespunztoare cheii unice. Coloana (mulimea de coloane) inclus n definiia cheii unice se
numete cheie unic. Dac o cheie unic conine mai multe coloane se numete cheie unic
compus.
O constrngere de tip cheie unic permite introducerea valorilor NULL dac nu a fost definit o
constrngere NOT NULL pentru acea coloan. De fapt, orice numr de nregistrri pot include
valori NULL n coloane fr constrngeri NOT NULL, deoarece valorile NULL nu sunt egale cu
nimic. O valoare NULL ntr-o coloan (sau n toate coloanele unei chei unice compuse) va
satisface ntotdeauna o constrngere de cheie unic.
Not: Din cauza mecanismului de cutare a constrngerilor UNIQUE n una sau mai multe
coloane, nu este permis existena unor valori identice n coloanele NOT NULL a unei
constrngeri de cheie unic compus.
Constrngerea de tip cheie unic (UNIQUE) definit la nivel de tabel sau de coloan
Constrngerile de tip cheie unic pot fi definite la nivel de coloan sau de tabel. O cheie unic
compus este creat utiliznd definiia la nivel de tabel (dup definirea tuturor coloanelor).
SQL> CREATE TABLE dept(
2
deptno NUMBER(2),
3
dname
VARCHAR(14),
4
loc
VARCHAR(13),
5
CONSTRAINT dept_dname_uk UNIQUE(dname));
10

n exemplul anterior se aplic constrngerea de cheie unic coloanei dname din tabelul dept,
numele constrngerii fiind DEPT_DNAME_UK.
Not: Serverul Oracle foreaz implicit constrngerea de cheie unic n momentul crerii unui
index unic dup cheia unic.
Constrngerea PRIMARY KEY
PRIMARY KEY
DEPT
DEPTNO
10
20
30
40

DNAME
ACCOUNTING
RESEARCH
SALES
OPERATIONS

LOC
NEW YORK
DALLAS
CHICAGO
BOSTON

INSERT
20

MARKETING
FINANCE

Nu este permis
(DEPTNO=20 exist
deja)

DALLAS
NEW YORK
Nu este permis
(DEPTNO este
NULL)

Constrngerea de cheie primar creeaz o cheie primar pentru tabel. Doar o singur cheie
primar poate fi creat pentru un anumit tabel. O cheie primar este o coloan sau mulime de
coloane ce identific unic fiecare nregistrare din tabel. Aceast constrngere foreaz unicitatea
coloanei sau a mulimii de coloane i asigur c nici o coloan din cheia primar nu poate
conine valoarea NULL.
Constrngerea cheii primare definit la nivel de coloan sau de tabel
Constrngerea de cheie primar (PRIMARY KEY) poate fi definit la nivel de tabel (dac
implic mai multe coloane sau dac i se atribuie un nume) sau de coloan (implic o singur
coloan i este nedenumit). O cheie primar compus este creat utiliznd definiia la nivel de
tabel.
SQL> CREATE TABLE dept(
2
deptno
NUMBER(2),
3
dname
VARCHAR2(14),
4
loc
VARCHAR2(13),
5
CONSTRAINT dept_dname_uk UNIQUE (dname),
6
CONSTRAINT dept_deptno_pk PRIMARY KEY(deptno));
Exemplul de mai sus definete o cheie primar format din coloana deptno din tabelul dept.
Numele constrngerii este DEPT_DEPTNO_PK.
Not: Un index unic este creat automat pentru o coloan cheie primar.
11

Constrngerea FOREIGN KEY (sau de referin)

PRIMARY KEY

EMP
EMPNO
7839
7698

ENAME
KING
BLAKE

DEPT
DEPTNO
10
20
.

JOB
PRESIDENT
MANAGER

DNAME
ACCOUNTING
RESEARCH

COMM

DEPTNO
10
30

200
200

LOC
NEW YORK
DALLAS

FOREIGN
KEY

INSERT
7571
7571

FORD
FORD

MANAGER
MANAGER

Nu este permis (DEPTNO=9


nu exist n tabelul DEPT)

Permis

Cheia extern sau constrngerea de integritate referenial desemneaz o coloan sau o


combinaie de coloane pe post de cheie extern i stabilete o relaie cu o cheie primar sau o
cheie unic din acelai tabel sau din alt tabel. n exemplul de mai sus, coloana deptno a fost
definit cheie extern n tabelul emp (denumit dependent sau tabel copil); ea refer coloana
DEPTNO din tabelul dept (denumit referit sau tabel printe).
Valoarea unei chei externe trebuie s coincid cu o valoare deja existent n tabelul printe sau
s fie NULL.
Observaie: Cheile externe sunt bazate pe valorile datelor din cele dou tabele i sunt pointeri
pur logici, nu fizici.
Constrngere de referin definit la nivel de coloan sau tabel
Constrngerile de chei externe pot fi definite la nivelul unui tabel sau unei coloane. O cheie
extern compus este creat folosind definiia la nivel de tabel.
SQL> CREATE TABLE emp(
2
empno
NUMBER(4),
3
ename
VARCHAR2(10) NOT NULL,
4
job
VARCHAR2(9),
5
mgr
NUMBER(4),
6
hiredate DATE,
7
sal
NUMBER(7,2),
8
comm
NUMBER(7,2),
9
deptno
NUMBER(7,2) NOT NULL,
10
CONSTRAINT emp_detpno_fk FOREIGN KEY (deptno)
REFERENCES dept (deptno));
12

Exemplul de mai sus definete o constrngere de tip cheie extern pe coloana deptno din
tabelul emp. Numele constrngerii este EMP_DEPTNO_FK.
Sintaxa constrngerii de referin este urmtoarea:
[CONSTRAINT nume_constr] FOREIGN KEY (col, ...)
REFERENCES tabel_referit (col, ...) [ON DELETE <CASCADE | SET NULL>]

FOREIGN KEY
Definete coloana din tabelul copil la nivelul constrngerii de tabel.
REFERENCES
Identific tabelul printe i coloana din tabelul printe.
ON DELETE CASCADE
Indic faptul c n situaia n care se terge o linie din tabelul printe, liniile dependente din
tabelul copil vor fi terse.
ON DELETE SET NULL
Dac se terge o linie din tabelul printe, liniile dependente din tabelul copil vor primi valori
NULL n coloanele implicate n constrngere.
Fr opiunea ON DELETE CASCADE | SET NULL linia din tabelul printe nu va putea fi
tears dac este referit n tabelul copil.

Constrngerea CHECK
Constrngerea de tip CHECK definete o condiie ce trebuie ndeplinit de fiecare linie dintr-un
tabel. Condiia poate utiliza aceleai construcii ca i condiiile de interogare, cu urmtoarele
excepii:
referiri la pseudocoloanele CURRVAL, NEXTVAL, LEVEL i ROWNUM.
apeluri de funcii SYSDATE, UID, USER i USERENV.
interogri care fac referire la alte valori din alte rnduri.
Nu exist o limitare pentru numrul de constrngeri CHECK ce pot fi definite pe o coloan.
Constrngerile CHECK pot fi definite la nivel de coloan sau de tabel.
Exemplul de mai jos definete o constrngere CHECK pentru coloana deptno din tabelul emp,
condiia constrngerii fiind ca valoarea din coloan s fie cuprins ntre 10 i 99.
, deptno NUMBER(2),
CONSTRAINT emp_deptno_ck
CHECK (DEPTNO BETWEEN 10 AND 99)
Adugarea unei constrngeri
Adugarea unei constrngeri la un tabel deja existent se face cu instruciunea ALTER TABLE cu
clauza ADD.
ALTER TABLE tabel
ADD [ CONSTRAINT nume_constrangere] tip (coloana);
unde:
tabel
nume_constrangere
tip
coloana

este numele tabelului


este numele constrngerii
este tipul constrngerii
este numele coloanei afectat de constrngere
13

Atentie! Dei denumirea constrngerilor este opional este recomandat furnizarea unor nume.
n caz contrar va fi generat un nume de ctre sistem.
Observaii:
se poate aduga, terge, activa sau dezactiva o constrngere, dar nu se poate modifica
definiia acesteia.
se poate aduga o constrngere de tip NOT NULL la o coloan existent folosind clauza
MODIFY din instruciunea ALTER TABLE.
Exemplul urmtor creeaz o constrngere de referin (FOREIGN KEY) n tabelul emp.
Impunerea acestei constrngeri externe indic faptul c un manager trebuie s existe ca angajat
activ n tabelul EMP.
SQL> ALTER TABLE emp
2 ADD CONSTRAINT emp_mgr_fk
3 FOREIGN KEY(mgr) REFERENCES emp(empno);
Table altered.
Eliminarea unei constrngeri
Pentru a elimina o constrngere trebuie identificat numele constrngerii. Aceast identificare se
poate face cu ajutorul vederilor USER_CONSTRAINTS i USER_CONS_COLUMNS din
dicionarul de date. Odat identificat numele constrngerii se va utiliza instruciunea ALTER
TABLE mpreuna cu clauza DROP.
ALTER TABLE tabel
DROP PRIMARY KEY | UNIQUE (coloana) |
CONSTRAINT nume_constrangere [CASCADE];
unde:
tabel
coloana
nume_constrangere

este numele tabelului


este numele coloanei afectat de constrngere
este numele constrngerii.

Opiunea CASCADE din clauza DROP are ca efect eliminarea tuturor constrngerilor dependente.
Atentie: Cnd se elimin o constrngere de integritate, aceasta nu mai este folosit de ctre
serverul Oracle i nu mai este disponibil n dicionarul de date.
Pentru eliminarea constrngerii n raport cu managerii din tabelul emp se va utiliza instruciunea
SQL> ALTER TABLE emp
2 DROP CONSTRAINT emp_mgr_fk;
Table altered.
Pentru eliminarea constrngerii de tip cheie primar din tabelul dept, mpreun cu
constrngerea extern asociat coloanei deptno se poate folosi instruciunea:
SQL> ALTER TABLE dept
2 DROP PRIMARY KEY CASCADE;
Table altered.
14

Dezactivarea constrngerilor
Se poate dezactiva o constrngere fr s fie necesar eliminarea acesteia sau recrearea sa
folosind instruciunea ALTER TABLE mpreuna cu clauza DISABLE.
ALTER TABLE tabel
DISABLE CONSTRAINT nume_constrangere [CASCADE];
unde:
tabel
nume_constrangere

este numele tabelului


este numele constrngerii.

Not:
- clauza DISABLE se poate folosi att n instruciunea CREATE TABLE, ct i n
instruciunea ALTER TABLE.
- clauza CASCADE dezactiveaz constrngerile de integritate dependente.
Exemplul urmtor dezactiveaz constrngerea de tip cheie primar din tabelul emp. Prin
utilizarea clauzei CASCADE vor fi dezactivate toate constrngerile dependente.
SQL> ALTER TABLE emp
2 DISABLE CONSTRAINT emp_empno_pk

CASCADE;

Table altered.
Pentru verificare se va afia valoarea din coloana STATUS din vederea USER_CONSTRAINTS
pentru constrngerea n cauz. Dac este afiat valoarea ENABLED atunci constrngerea este
activat. n cazul n care constrngerea este dezactivat se va afia valoarea DISABLED.
Activarea unei constrngere dezactivate se face prin utilizarea instruciunii ALTER TABLE
mpreuna cu clauza ENABLE.
ALTER TABLE tabel
ENABLE CONSTRAINT nume_constrangere;
unde:
tabel
nume_constrangere

este numele tabelului.


este numele constrngerii.

Not:
- dac se activeaz o constrngere, constrngerea va fi aplicat tuturor datelor din tabel. Toate
datele din tabel trebuie s satisfac constrngerea.
- dac se activeaz o constrngere de tip UNIQUE sau PRIMARY KEY, atunci este creat n
mod automat un index UNIQUE sau PRIMARY KEY.
-

clauza ENABLE se poate folosi att n instruciunea CREATE TABLE, ct i n instruciunea


ALTER TABLE.
Exemplu:
SQL>
2

ALTER TABLE emp


ENABLE CONSTRAINT emp_empno_pk;

Table altered.

15

Vizualizarea constrngerilor
Dup crearea unui tabel, se poate confirma existena sa prin folosirea instruciunii DESCRIBE.
Singura constrngere care poate fi verificat n acest mod este constrngerea NOT NULL. Pentru
a vedea toate constrngerile din tabel, este necesar interogarea tabelului
USER_CONSTRAINTS.
Exemplul urmtor afieaz toate constrngerile definite n tabelul EMP.
SQL>
2
3
4

SELECT constraint_name, constraint_type,


search_condition
FROM user_constraints
WHERE table_name=EMP;

CONSTRAINT_NAME
---------------SYS_C00674
SYS_C00675
EMP_EMPNO_PK

C
C
C
P

SEARCH_CONDITION
---------------EMPNO IS NOT NULL
DEPTNO IS NOT NULL

Not: Constrngerilor care nu primesc un nume de la proprietarul tabelului li se atribuie un nume


automat de ctre sistem. Coloana C indic tipul constrngerii: C provine de la CHECK, P de la
PRIMARY KEY, R de la integritate referenial i U de la UNIQUE. De observat faptul c o
constrngere NOT NULL este de fapt o constrngere de tip CHECK.
Vizualizarea coloanelor asociate constrngerilor
Pentru vizualizarea numelor coloanelor implicate n constrngeri se va interoga vederea
USER_CONS_COLUMNS din dicionarul de date. Aceast vizualizare este util n cazul utilizrii
mecanismului de asociere automat a numelor pentru contrngeri de ctre sistem.
SQL> SELECT constraint_name, column_name,
2 FROM user_cons_columns
3 WHERE table_name=EMP;
CONSTRAINT_NAME
---------------EMP_DEPTNO_FK
EMP_EMPNO_PK
EMP_MGR_FK
SYS_C00674
SYS_C00675

COLUMN_NAME
----------DEPTNO
EMPNO
MGR
EMPNO
DEPTNO

16

Probleme:
1. Creai tabelul DEPARTMENT avnd structura din tabelul urmtor. Salvai instruciunea n
scriptul p1.sql, executai scriptul i verificai crearea tabelului.
Column Name
Nulls/Unique
Datatype
Length

Id

Name

Number
7

Varchar2
25

2. Introducei nregistrri n tabelul DEPARTMENT folosind nregistrrile din tabelul DEPT.


Includei doar coloanele de care avei nevoie.
3. Creai tabelul EMPLOYEE avnd structura din tabelul urmtor. Salvai instruciunea n
fiierul script p3.sql i apoi executai scriptul.
Column Name
Nulls/Unique
Datatype
Length

ID

LAST_NAME

FIRST_NAME DEPT_ID

Number
7

Varchar2
10

Varchar2
25

Number
7

4. Modificai tabelul EMPLOYEE pentru a permite stocarea unor nume mai lungi (de exemplu
de lungime 25 de caractere) n coloana LAST_NAME.
5. Verificai c cele dou tabele create sunt stocate n dicionarul de date (Indicaie: afiai
datele de interes din vederea USER_TABLES).
6. Creai tabelul EMPLOYEE2 avnd aceeai structur ca i tabelul EMP, incluznd doar
coloanele EMPNO, ENAME i DEPTNO. Redenumii coloanele n noul tabel astfel: ID,
LAST_NAME, DEPT_ID. Se vor prelua nregistrrile din tabelul emp.
7. tergei tabelul EMPLOYEE.
8. Redenumii tabelul EMPLOYEE2 n EMPLOYEE.
9. Adugai comentarii la definiiile celor 2 tabele, descriind semnificaia tabelului respectiv.
Vizualizai modificrile din dicionarul de date.
10. Adugati o constrngere de tip PRIMARY KEY la tabelul EMPLOYEE folosind coloana ID.
Constrngerea trebuie s fie activat la creare.
11. Creai o constrngere PRIMARY KEY n tabelul DEPARTMENT folosind coloana ID.
Constrngerea trebuie s fie activat la creare.
12. Adugai o referin de tip cheie extern la tabelul EMPLOYEE care va asigura c angajaii nu
sunt asignai la un departament inexistent.
13. Confirmai constrngerile adugate interognd tabelul USER_CONSTRAINTS. Observai
numele i tipul constrngerilor.
CONSTRAINT_NAME
---------------------DEPARTEMENT_ID_PK
EMPLOYEE_ID_PK
EMPLOYEE_DEPT_ID_FK

C
P
P
R

14. Afiai numele i tipul obiectelor din vederea USER_OBJECTS pentru tabelele EMPLOYEE
i DEPARTMENT.
OBJECT_NAME
----------------DEPARTMENT
DEPARTMENT_ID_PK
EMPLOYEE
EMPLOYEE_ID_PK

OBJECT_TYPE
----------TABLE
INDEX
TABLE
INDEX
17

CREAREA I UTILIZAREA VEDERILOR.


UTILIZAREA OBIECTELOR DE TIP SECVEN
PENTRU GENERARE AUTOMAT DE VALORI
Obiective
O vedere este un tabel logic bazat pe un alt tabel sau pe o alt vedere i nu conine date
proprii. Tabelele pe baza crora sunt create vederile se numesc tabele de baz. La nivelul
bazei de date o vedere este stocat sub forma unei instruciuni SELECT n dicionarul de
date. Prin parcurgerea acestui referat studentul va dobndi cunotinele necesare pentru:
-

descrierea unei vederi;


crearea unui obiect de tip vedere;
extragerea datelor dintr-o vedere;
modificarea structurii unei vederi;
inserarea, actualizarea i tergerea datelor dintr-o vedere;
tergerea unei vederi;
crearea i utilizarea generatoarelor de secvene.

Avantajele utilizrii vederilor


-

restricioneaz accesul la baza de date deoarece o vedere pune la dispoziia utilizatorilor


doar o parte a datelor din baza de date;
permit utilizatorilor s apeleze la interogri simple pentru a obine rezultatele unor
interogri complexe. De exemplu, vederile permit utilizatorilor s extrag informaii din
mai multe tabele fr a cunoate modul de realizare a jonciunilor..
asigur independena datelor pentru utilizatori i aplicaii. O singur vedere poate fi
utilizat pentru a obine date din mai multe tabele;
furnizeaz grupurilor de utilizatori accesul la date n conformitate cu anumite criterii,
stabilite de administratorul bazei de date.

Vederile se clasific n dou grupe: simple i complexe. Diferena de baz ntre cele dou
grupe este legat de operaiile LMD (inserare, actualizare i tergere).
Caracteristici
Numr de tabele
Conine funcii
Conine grupuri de date
Operaii LMD

Vederi simple
1
Nu
Nu
Da

O vedere simpl este o vedere care:


-

furnizeaz date dintr-un singur tabel;


nu conine funcii sau grupuri de date;
permite execuia unor operaii LMD.

O vedere complex este o vedere care :


-

extrage date din mai multe tabele;


conine funcii sau grupuri de date;
nu permite ntotdeauna operaii LMD.
1

Vederi complexe
1 sau mai multe
Da
Da
Nu ntotdeauna

Crearea unei vederi


Instruciunea ce permite crearea unei vederi este CREATE VIEW, avnd urmtoarea sintax.
CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW nume_vedere
[(alias[, alias...])]
AS subinterogare
[WITH CHECK OPTION [CONSTRAINT nume_constr]]
[WITH READ ONLY]

unde:
OR REPLACE
FORCE
NOFORCE
nume_vedere
alias

subinterogare
WITH CHECK OPTION
nume_constr
WITH READ ONLY

- recreeaz vederea dac aceasta exist deja


- creeaz vederea indiferent daca exist sau nu tabelele
de baz
- creeaz vederea numai dac exist tabelele de baz;
este opiunea implicit
- este numele vederii
- specific noul nume pentru o coloan a vederii;
numrul de alias-uri trebuie s corespund numrului de
expresii selectate de vedere
- este o instruciune SELECT; se pot utiliza alias-uri
pentru coloanele din clauza SELECT
- specific faptul c pot fi actualizate doar liniile
accesibile vederii
- este numele constrngerii
- interzice execuia unei instruciuni LMD pe vedere.

Pentru a crea o vedere numit EMPVU10 care conine detalii despre angajaii din
departamentul 10 se va executa urmtoarea instruciune:
CREATE VIEW empvu10
AS SELECT empno, ename, job
FROM emp
WHERE deptno=10;
Observaii:
-

subinterogarea care definete o vedere poate conine o instruciune SELECT complex


(inclusiv jonciuni, grupuri i subinterogri);
subinterogarea care definete o vedere nu poate conine clauza ORDER BY. Aceast
clauz va fi specificat n momentul interogrii vederii;
opiunea OR REPLACE poate fi utilizat pentru a putea modifica vederea fr a o terge
i recrea.

Redenumirea coloanelor ce apar n vedere se poate face n dou moduri:


1. se includ alias-urilor de coloan n subinterogare:
CREATE VIEW
AS SELECT
FROM
WHERE

salvu30
empno EMPLOYEE_NUMBER, ename NAME, sal SALARY
emp
deptno=30;
2

Exemplul anterior creeaz o vedere care conine numrul, numele i salariul angajailor din
departamentul 30. Coloanele acestei vederi au numele EMPLOYEE_NUMBER, NAME i
SALARY.
2. se includ alias-uri de coloan n clauza CREATE VIEW.
CREATE VIEW
AS SELECT
FROM
WHERE

salvu30 (EMPLOYEE_NUMBER, NAME, SALARY)


empno, ename, sal
emp
deptno=30;

Interogarea vederilor
Extragerea datelor din vederi se face n acelai mod ca n cazul tabelelor.
SQL> SELECT *
2 FROM salvu30;
EMPLOYEE_NUMBER
---------------7698
7654
7499
7844
7900
7521

NAME
SALARY
------- ------BLAKE
2850
MARTIN
1250
ALLEN
1600
TURNER
1500
JAMES
950
WARD
1250

Odat creat vederea, se poate interoga tabelul USER_VIEWS din dicionarul de date pentru
a obine numele i definiia vederii. Textul instruciunii SELECT care implementeaz
vederea este memorat ntr-o coloan de tip LONG (ir de caractere).
Accesarea datelor din baza de date corespunztoare unei vederi presupune execuia
urmtoarelor operaii de ctre serverul Oracle:
1. extrage definiia vederii din dicionarul de date (mai exact din tabelul USER_VIEWS);
2. verific privilegiile de acces pentru tabelele de baz;
3. convertete interogarea vederii ntr-o operaie echivalent asupra tabelului (tabelelor) de
baz. Cu alte cuvinte, datele sunt extrase din, sau actualizate n tabelul (tabelele) de baz.
Modificarea unei vederi
Opiunea OR REPLACE permite crearea unei vederi, chiar dac exist deja o vedere cu
acelai nume, nlocuindu-se astfel vechea versiune a vederii cu cea nou. Aceasta nseamn
c o vedere poate fi modificat fr a fi necesar tergerea i recrearea ei.
Urmtorul exemplu modific vederea EMPVU10 utiliznd clauza CREATE OR REPLACE
VIEW. Suplimentar se adaug un alias pentru fiecare coloan.
SQL>
2
3
4
5

CREATE OR REPLACE VIEW empvu10


(employee_number, employee_name, job_title)
AS SELECT empno, ename, job
FROM emp
WHERE deptno=10;
3

Not: Cnd se furnizeaz nume alternative (alias-uri) coloanelor n clauza CREATE VIEW,
alias-urile trebuie listate n aceeai ordine ca i coloanele din subinterogare.
Crearea unei vederi complexe
SQL>
2
3
4
5
6

CREATE VIEW dept_sum_vu


(name, minsal, maxsal, avgsal)
AS SELECT d.dname, MIN(e.sal), MAX(e.sal), AVG(e.sal)
FROM emp e, dept d
WHERE e.deptno=d.deptno
GROUP BY d.dname;

Exemplul anterior creeaz o vedere complex care conine numele, salariul minim, salariul
maxim i salariul mediu pentru fiecare departament. De notat c au fost specificate alias-uri
pentru vedere. Acest lucru este necesar dac una din coloanele vederii rezult din
evaluarea unei funcii sau expresii.
Reguli pentru executarea operaiilor LMD asupra unei vederi
Pentru a putea executa operaii LMD asupra datelor din baza de date prin intermediul vederii
trebuie avute n vedere o serie de reguli.
1.
-

Nu se poate terge o linie aparinnd unei vederi dac definiia vederii conine :
funcii grup;
clauz GROUP BY;
cuvntul cheie DISTINCT.

2.
-

Nu se pot modifica datele dintr-o vedere dac vederea conine:


oricare din elementele de la punctul 1;
coloane definite prin expresii (de exemplu, SALARY*12);
pseudocoloana ROWNUM.

3. Nu pot fi inserate date ntr-o vedere dac:


- vederea conine oricare din elementele de la punctul 1 i 2;
- exist coloane NOT NULL fr valoare implicit n tabelul de baz i care nu au fost
selectate n vedere.
Utilizarea clauzei WITH CHECK OPTION
Exist posibilitatea ca, prin intermediul vederilor, s se efectueze verificri de integritate
referenial asupra datelor. Se pot, de asemenea, fora constrngeri la nivelul bazei de date. O
vedere poate fi utilizat pentru a asigura integritatea datelor, dar ntr-o manier destul de
limitat.
Clauza WITH CHECK OPTION specific faptul c instruciunile INSERT i UPDATE
executate asupra vederii nu pot crea linii noi pe care vederea nu le poate selecta. Prin urmare,
vederile pot fora verificri asupra datelor ce vor fi inserate sau actualizate. Dac se ncearc
execuia unei operaii LMD pe linii care nu au fost selectate de vedere se va afia un mesaj de
eroare, mpreun cu numele constrngerii (dac acesta a fost specificat).
4

Pentru exemplificare s considerm vederea


SQL>
2
3
4
5

CREATE OR REPLACE VIEW empvu20


AS SELECT *
FROM emp
WHERE deptno=20
WITH CHECK OPTION CONSTRAINT empvu20_ck;

Orice ncercare de a modifica numrul departamentului pentru orice linie din vedere va eua
deoarece nu respect constrngerea WITH CHECK OPTION.
SQL> UPDATE empvu20
2 SET deptno=10
3 WHERE empno=7788;
update empvu20
*
ERROR at line 1:
ORA-01402: view WITH CHECK OPTION where-clause violation
Nici o linie nu este actualizat pentru c, dac numrul departamentului ar deveni 10, vederea
nu ar mai putea selecta acel angajat. Datorit faptului c vederea poate vedea doar angajaii
din departamentul 20, utilizarea clauzei WITH CHECK OPTION nu permite ca numrul
departamentului pentru aceti angajai sa fie schimbat prin intermediul vederii.
Interzicerea operaiilor LMD
Dac se dorete ca asupra vederii s nu poat fi executat nici o operaie LMD, la crearea
vederii trebuie specificat opiunea WITH READ ONLY.
SQL>
2
3
4
5
6

CREATE OR REPLACE VIEW empvu10


(employee_number, employee_name, job_title)
AS SELECT empno, ename, job
FROM emp
WHERE deptno=10
WITH READ ONLY;

Exemplul de mai sus modific vederea EMPVU10 pentru a mpiedica orice operaie LMD
asupra vederii. Orice ncercare de tergere a unei linii din vedere va genera o eroare.
SQL> DELETE FROM empvu10
2 WHERE employee_number=7782;
DELETE FROM empvu10
*
ERROR at line 1:
ORA_01752: Cannot delete from view without exactly one
key-preserved table
tergerea definiiei unei vederi

Pentru a terge o vedere se va utiliza instruciunea:


DROP VIEW nume_vedere;
Exemplu:
DROP VIEW empvu10;
Aceast instruciune elimin definiia vederii din baza de date. tergerea vederilor nu are nici
un efect asupra tabelelor pe care se bazeaz vederea. Vederile sau aplicaiile bazate pe o
vedere tears devin invalide. tergerea unei vederi poate fi efectuat fie de creatorul vederii
fie de un utilizator ce deine privilegiul DROP ANY VIEW.

Obiecte de tip secven


Multe aplicaii necesit folosirea de valori distincte pentru o cheie primar. Pentru a ndeplini
aceast cerin fie se scriu linii de cod, fie se recurge la utilizarea obiectelor de tip secven
pentru a genera automat aceste numere distincte. O secven este un obiect creat de un
utilizator i poate fi folosit de mai muli utilizatori. Secvena este generat i incrementat
(sau decrementat) de o rutin intern Oracle. Numerele secvenei sunt stocate i generate
independent de tabel. Prin urmare, aceeai secven poate fi folosit n mai multe tabele.
Crearea unui obiect de tip secven
Instruciunea CREATE SEQUENCE definete o secven ce va genera automat numere
secveniale. Sintaxa acestei instruciuni este urmtoarea:
CREATE SEQUENCE secventa
[INCREMENT BY n]
[START WITH n]
[{MAXVALUE n | NOMAXVALUE}]
[{MINVALUE n | NOMINVALUE}]
[{CYCLE | NOCYCLE}]
[{CACHE n | NOCACHE}];
unde:
secventa

este numele generatorului de secven;

INCREMENT BY n

specific intervalul dintre dou numere consecutive ale


secvenei, unde n este un ntreg. Dac aceast clauza
lipsete, n este implicit 1;

START WITH n

specific primul numr al secvenei. Dac aceast


clauz lipsete, implicit n = 1;

MAXVALUE n

specific valoarea maxim pe care secvena o poate


genera;

NOMAXVALUE

specific o valoare maxim de 1027 pentru o secven


cresctoare i 1 pentru o secven descresctoare.
Aceste valori sunt implicite;
6

MINVALUE n

specific valoarea minim a secvenei;

NOMINVALUE

specific o valoare minim de 1 pentru o secven


cresctoare i (1027) pentru una descresctoare.
Aceste valori sunt implicite;

CYCLE | NOCYCLE

specific dac secvena continu s genereze valori


dup ce a fost atins valoarea maxim / minim, sau
dac nu mai genereaz nici o valoare. Opiunea
NOCYCLE este implicit;

CACHE n | NOCACHE

specific serverului Oracle pentru cte valori s aloce


spaiu n memorie. Implicit n are valoarea 20.

Exemplul urmtor creeaz secvena DEPT_DEPTNO, folosit pentru coloana DEPTNO din
tabelul DEPT. Secvena ncepe cu valoarea 91, nu permite alocare de memorie i nu permite
cicluri de generare.
SQL>
2
3
4
5
6

CREATE SEQUENCE dept_deptno


INCREMENT BY 1
START WITH 91
MAXVALUE 100
NOCACHE
NOCYCLE;

Sequence created.
Not: Nu se recomand folosirea clauzei CYCLE atunci cnd secvena este folosit pentru a
genera valorile unei chei primare, excepie fcnd cazul cnd se dispune de un mecanism
sigur de ndeprtare a vechilor nregistrri i mai rapid dect ciclurile secvenei.
Confirmarea existenei obiectelor de tip secven
Odat creat o secven, ea este nscris n dicionarul de date i poate fi identificat cu
ajutorul tabelului USER_OBJECTS. De asemenea, se pot confirma setrile unei secvene prin
interogarea tabelului USER_SEQUENCES.
SQL> SELECT sequence_name, min_value, max_value,
2
increment_by, last_number
3 FROM user_sequences;

Coloana LAST_NUMBER conine urmtorul numr disponibil al secvenei.


SEQUENCE_NAME
MIN_VALUE
-------------- ---------CUSTID
1
DEPT_DEPTNO
1
ORDID
1
PRODID
1

MAX_VALUE
---------1.000E+27
100
1.000E+27
1.000E+27

INCREMENT_BY
-----------1
1
1
1

LAST_NUMBER
----------109
91
622
200381

Pseudocoloanele NEXTVAL i CURRVAL


Odat creat secvena, ea poate fi folosit pentru a genera numere ce vor fi utilizate ulterior
n tabele. Referirea urmtoarei valori din secven i a valorii curente se face cu ajutorul
pseudocoloanelor NEXTVAL i CURRVAL.
7

Pseudocoloana NEXTVAL este folosit pentru a extrage numere succesive dintr-o anumit
secven. Referirea la NEXTVAL se face mpreun cu numele secvenei. Atunci cnd se face
referire la secventa.NEXTVAL se genereaz un nou numr al secvenei, ce va fi memorat
n CURRVAL.
Pseudocoloana CURRVAL este folosit pentru a referi numrul unei secvene ce tocmai a fost
generat. nainte de a se face referire la CURRVAL trebuie utilizat NEXTVAL pentru a genera
un nou numr. Referirea lui CURRVAL se face mpreun cu numele secvenei. Cnd
sequence.CURRVAL este referit, va fi afiat ultima valoare generat de secven.
Reguli pentru utilizarea pseudocoloanelor NEXTVAL i CURRVAL
Folosirea pseudocoloanelor NEXTVAL i CURRVAL este permis n urmtoarele situaii:

n clauza SELECT a unei instruciuni SELECT ce nu face parte dintr-o subinterogare;


n clauza SELECT a unei subinterogri dintr-o instruciune INSERT;
n clauza VALUES a unei instruciuni INSERT;
n clauza SET a unei instruciuni UPDATE.

Nu este permis utilizarea pseudocoloanelor NEXTVAL i CURRVAL n urmtoarele situaii:

n clauza SELECT a unei vederi;


ntr-o instruciune SELECT ce conine cuvntul cheie DISTINCT;
ntr-o instruciune SELECT ce conine clauzele GROUP BY, HAVING sau ORDER BY;
ntr-o subinterogare din instruciuni SELECT, DELETE sau UPDATE;
ntr-o expresie DEFAULT n instruciuni CREATE TABLE sau ALTER TABLE.

Utilizarea unei secvene


Exemplul urmtor insereaz un nou departament n tabelul DEPT. Se utilizeaz secvena
DEPT_DEPTNO pentru generarea unui nou numr pentru departament.
SQL> INSERT INTO dept(deptno, dname, loc)
2 VALUES(dept_deptno.NEXTVAL,
3
MARKETING, SAN DIEGO);
1 row created.
Pentru vizualizarea valorii curente pentru secvena DEPT_DEPTNO se va executa urmtoarea
instruciune:
SQL> SELECT dept_deptno.CURRVAL
2 FROM dual;
CURRVAL
-------91
Stocarea secvenelor n memorie permite o accesare mai rapid a valorilor secvenei, stocarea
realizndu-se la prima referire a secvenei. Dup ce a fost utilizat ultima valoare din
secven, urmtoarea cerere de generare determin o alt stocare a secvenei n memorie.

Dei generatorul de secvene furnizeaz numere consecutive fr goluri, aceast aciune se


petrece independent de un commit sau un rollback. De aceea, dac se execut un rollback pe
o instruciune ce utilizeaz o valoare dintr-o secven, acea valoare este pierdut. Un alt
eveniment ce poate provoca goluri n secven este o cdere a sistemului. Dac valorile
secvenei sunt stocate n memorie, acestea se pierd n cazul unei cderi de sistem.
Este posibil vizualizarea urmtoarei valori disponibile din secven fr a o incrementa,
doar dac secvena a fost creat cu opiunea NOCACHE, prin interogarea tabelului
USER_SEQUENCES.

Modificarea unei secvene


Dac se atinge valoarea MAXVALUE ntr-o secven definit cu opiunea NOCYCLE nu va mai
fi atribuit nici o valoare suplimentar i se va genera un mesaj de eroare ce indic faptul c
secvena a atins valoarea maxim. Pentru a putea folosi n continuare aceast secven, va
trebui s modificm definiia secvenei cu ajutorul instruciunii ALTER SEQUENCE.
ALTER SEQUENCE nume_secv
[INCREMENT BY n]
[{MAXVALUE n | NOMAXVALUE}]
[{MINVALUE n | NOMINVALUE}]
[{CYCLE | NOCYCLE}]
[{CACHE n | NOCACHE}];
unde:
nume_secv

este numele generatorului de secvene

Exemplul urmtor modific valoarea incrementului, valoarea maxim i minim, opiunea de


ciclare i de stocare pentru secvena DEPT_DEPTNO.
SQL>
2
3
4
5

ALTER SEQUENCE dept_deptno


INCREMENT BY 1
MAXVALUE 999999
NOCACHE
NOCYCLE;

Sequence altered.
Pentru verificare se vor afia informaiile din vederea USER_SEQUENCES.
Observaii:
o secven poate fi modificat doar de utilizatorul care a creat secvena sau de un
utilizator ce deine privilegiul ALTER pentru secvena n cauz;
sunt afectate doar numerele ce urmeaz s fie generate;
secvena trebuie distrus i recreat pentru a ncepe secvena cu un alt numr (specificat
n clauza START WITH).
tergerea unei secvene
Pentru tergerea unei secvene din dicionarul de date se utilizeaz instruciunea DROP
SEQUENCE. Aceast operaie poate fi realizat doar de proprietarul secvenei sau de
utilizatorul cu privilegiul DROP ANY SEQUENCE.
9

DROP SEQUENCE nume_secv;


Exemplu:
SQL> DROP SEQUENCE dept_deptno;
Sequence dropped.

Probleme
1. Creai o vedere EMP_VU care s conin numrul, numele i departamentul angajailor
din tabelul emp. Redenumii coloana corespunztoare numelui EMPLOYEE. Afiai
coninutul vederii EMP_VU.
2. Vizualizai informaiile despre vederea creat la problema 1 din vederea USER_VIEWS
(coloanele view_name i text).
3. Folosind vederea EMP_VU scriei o interogare pentru a afia numele tuturor angajailor,
mpreun cu departamentele n care lucreaz.
4. Creai vederea DEPT20 care s conin urmtoarele informaii despre angajaii ce
lucreaz n departamentul 20: numr angajat, nume angajat i numr departament.
Etichetai coloanele vederii astfel: EMPLOYEE_ID, EMPLOYEE i DEPARTMENT_NO.
Nu permitei ca unui angajat s i se poat modifica numrul departamentului prin
intermediul vederii.
5. Afiai structura i coninutul vederii DEPT20.
6. ncercai s nlocuii numrul departamentului pentru angajatul Smith cu valoarea 30.
Explicai cauza ce a condus la generarea erorii semnalat de server.
7. Creai vederea SALARY_VU care s conin numele angajatului, numele departamentului,
salariul i gradul de salarizare pentru toi angajaii din emp. Etichetai coloanele astfel:
Employee, Department, Salary i Grade.
8. S se creeze o secven ce va fi folosit mpreun cu cheia primar a tabelului
DEPARTMENT. Secvena trebuie s nceap cu 60 i s aib o valoare maxim de 200.
Incrementul secvenei este de 10. Numele secvenei va fi DEPT_ID_SEQ.
9. S se afieze urmtoarele informaii despre secvena de la problema 8: nume, valoarea
maxim, mrimea incrementului i ultimul numr creat.
10. S se realizeze un program interactiv pentru a insera o nregistrare n tabelul
DEPARTMENT. Pentru introducerea valorilor n coloana ID se va utiliza secvena creat
la problema 8. Se va cere introducerea de la tastatur a numelui departamentului. S se
adauge dou departamente numite Education i Administration. S se confirme
adugarea celor dou nregistrri.
Structura tabelului DEPARTMENT este urmtoarea:
Column Name
Nulls/Unique
Datatype

ID

NAME

Number(7)

Varchar2(25)

10

Limbajul PL/SQL
PL/SQL (Procedural Language/SQL) este extensia procedural a limbajului SQL dezvoltat de
Oracle Corporation, ce permite includerea instruciunilor de manipulare i interogare a datelor n
uniti de cod procedurale i structurate pe bloc. PL/SQL este o tehnologie adoptat de server-ul
Oracle i de unele produse Oracle (eg. Developer/2000 Forms). Blocurile PL/SQL sunt trimise
motorului PL/SQL i executate de acesta, motor ce se poate afla fie n cadrul aplicaiei din care s-a
executat blocul, fie pe serverul Oracle. PL/SQL poate fi utilizat pentru gruparea mai multor
instruciuni ntr-un singur bloc i trimiterea ntregului bloc la server printr-un singur apel. Fr
PL/SQL, instruciunile SQL ar fi procesate una cte una, fiecare instruciune genernd un apel ctre
serverul Oracle.

Structura orientat pe blocuri a PL/SQL


n PL/SQL programele pot fi divizate n blocuri logice, principalele tipuri de blocuri ce pot fi
utilizate fiind:
- blocuri anonime - bloc nedenumit i care nu formeaz corpul unei proceduri, funcii sau
declanator (trigger);
- blocuri de tip funcie i procedur similare funciilor i procedurilor din alte limbaje de
programare i sunt definite ca blocuri PL/SQL;
- blocuri declanatoare (trigger) blocuri PL/SQL ce definesc codul ce urmeaz a fi executat
atunci cnd au loc anumite aciuni sau evenimente la nivelul bazei de date;
- blocuri imbricate utilizate pentru tratarea erorilor i pentru creterea modularitii codului
scris.

Blocuri anonime
Un bloc anonim PL/SQL este format din trei seciuni:
-

seciunea declarativ (opional) conine toate variabilele, constantele, cursoarele i excepiile


utilizator ce sunt referite n seciunile executabile i declarative;

seciunea executabil (obligatorie) conine instruciuni SQL pentru manipularea datelor din baza
de date i instruciuni PL/SQL pentru manipularea datelor din cadrul blocului;

seciunea de tratare a excepiilor (opional) specific aciunile ce vor fi executate n momentul


apariiei unor erori sau condiii anormale n seciunea executabil.

Structura unui bloc PL/SQL este urmtoarea:


Opional
- variabile, cursori, excepii utilizator
BEGIN
Obligatoriu
- instruciuni SQL
- instruciuni PL/SQL
EXCEPTIONS - Opional
- aciuni executate n caz de eroare
END;
- Obligatoriu
DECLARE

Pentru execuia blocurilor PL/SQL n mediul gazd SQL*PLUS se va ine cont de urmtoarele
reguli:
- se va plasa caracterul ; la sfritul unei instruciuni SQL sau a unei instruciuni de control
PL/SQL;
- se va plasa caracterul / pentru rularea blocurilor anonime din buffer-ul SQL. Execuia cu
succes a unui astfel de bloc va fi anunat prin mesajul
PL/SQL procedure successfully completed
-

se va plasa . pentru a nchide buffer-ul SQL (un bloc PL/SQL este tratat ca o singur
instruciune i caracterele ; plasate n interiorul blocului nu vor nchide sau rula buffer-ul).

Variabile PL/SQL
Variabilele PL/SQL trebuie declarate n seciunea declarativ, nainte de utilizarea lor ntr-un bloc
PL/SQL. Sintaxa ce permite declararea unei variabile este urmtoarea:
identificator [CONSTANT] tip_date [NOT NULL]
[:= | DEFAULT expr]

unde:
identificator
CONSTANT
tip_date
NOT NULL
expr

este numele variabilei;


utilizat n cazul n care identificator este o constant; constantele
trebuie iniializate;
tipul de date al variabilei (scalar, compus, referin sau LOB);
constrnge variabila s conin valori diferite de NULL; variabilele
NOT NULL trebuie iniializate la declarare;
o expresie PL/SQL care poate fi un literal, o alt variabil sau o
expresie ce implic operatori i funcii.

PL/SQL suport patru categorii de tipuri de date:


1. scalar tipurile de date din aceast categorie permit stocarea unei singure valori; n aceast
categorie intr tipurile de date utilizate pentru coloanele de tabele;
2. compus permit definirea i manipularea grupurilor de cmpuri n blocuri PL/SQL; aceast
categorie conine tipurile de date (numite i colecii) TABLE, RECORD, VARRAY;
3. referin tipurile din aceast categorie sunt utilizate pentru memorarea pointerilor ctre alte
elemente ale unui program;
4. LOB stocheaz informaii ce indic locaia obiectelor de dimensiuni mari (imagini grafice,
video-clipuri).
Exemplul urmtor indic modul de declarare a unor variabile:
DECLARE
v_job
varchar2(9);
v_count
number(9,2) := 0;
c_tax_rate CONSTANT number(3,2) := 8.25;
v_valid
boolean NOT NULL := TRUE;
g_mgr
number(4) DEFAULT 7839;
BEGIN
...

Regulile urmrite la declararea unei variabile sunt urmtoarele:


- dac se dorete iniializarea unei variabile cu o expresie, n momentul declarrii se va utiliza
operatorul de asignare := sau se va specifica cuvntul cheie DEFAULT. Dac variabila nu se
iniializeaz la declarare ea va conine valoarea NULL pn n momentul iniializrii.
- dac se utilizeaz constrngerea NOT NULL, variabila TREBUIE iniializat.
- declararea unei singure variabile pe linie ajut la citirea i ntreinerea cu mai mult uurin a
codului.
- pentru declararea constantelor trebuie utilizat identificatorul CONSTANT naintea tipului de date.
O constant trebuie iniializat la declarare, n caz contrar generndu-se un mesaj de eroare de
compilare.
Pentru asignarea de valori unei variabile se va utiliza sintaxa
identificator := expr;

unde:
identificator
expr

este numele variabilei


poate fi o variabil, un literal sau un apel de funcie, dar nu un nume de
coloan

Un literal este o valoare explicit de tip numeric, caracter, ir de caractere sau boolean (exemple de
literali: numrul 25.36, irul Test, valoarea TRUE).
Dac se declar o variabil pentru a fi utilizat cu scopul de a memora valorile unei coloane, tipul de
date al variabilei trebuie ales n conformitate cu domeniul de definiie al coloanei. Pentru aceasta se
poate utiliza atributul %TYPE, care permite declararea unei variabile pe baza tipului unei alte
variabile sau al unei coloane. %TYPE se utilizeaz, cel mai adesea, atunci cnd se declar o variabil
ce va fi folosit pentru stocarea valorilor din coloana unui tabel sau pentru nscrierea datelor ntr-o
coloan. Acest atribut nlocuiete tipul de date al variabilei i va fi prefixat de numele tabelului i al
coloanei n cauz sau cu numele variabilei.

v_ename
v_balance
v_min_balance

emp.ename%TYPE;
NUMBER(7,2);
v_balance%TYPE := 10;

n exemplul de mai sus, tipul variabilei v_ename va fi dat de domeniul de definiie al coloanei
ename din tabelul emp.
Tipurile de date scalare ce pot fi utilizate la declararea unei variabile sunt prezentate n anexa 1.
Variabilele booleene (declarate cu tipul BOOLEAN) sunt variabile ce pot avea valorile TRUE,
FALSE sau NULL. Astfel de variabile pot fi unite prin operatorii logici AND, OR sau NOT. Expresiile
booleene sunt formate din expresii simple sau complexe, separate de operatori logici (e.g. clauza
WHERE a unei instruciuni SELECT conine o expresie boolean ce specific liniile dintr-un tabel
afectate de instruciune).
De exemplu, dac
v_sal1 := 5000;
v_sal2 := 6000;

atunci expresia v_sal1 < v_sal2 va returna TRUE.


v_comm_sal BOOLEAN := (v_sal1 < v_sal2); reprezint declaraia i iniializarea unei

variabile booleene.
O variabil de legtur este o variabil declarat ntr-un mediu gazd (de exemplu SQL*Plus) i
utilizat n momentul execuiei pentru a pasa valori spre, respectiv pentru a primi valori din unul sau
mai multe programe PL/SQL. O variabil de legtur poate fi tratat n aceeai manier ca
variabilele obinuite. Pentru a declara o variabil de legtur n mediul SQL*Plus se va utiliza
comanda VARIABLE.
SQL> VARIABLE return_code NUMBER

Att SQL ct i SQL*Plus pot referi variabilele de legtur, iar SQL*Plus poate afia i valoarea lor
prin intermediul comenzii PRINT:
SQL> PRINT return_code

O alt modalitate de a afia valoarea unei variabile de legtur const n utilizarea funciei
PUT_LINE din pachetul DBMS_OUTPUT. nainte de utilizarea acestei funcii trebuie executat
comanda SET SERVEROUTPUT ON (o singur dat pe sesiune) la promptul SQL*Plus, n caz
contrar nu se va afia nimic pe ecran.
DECLARE
y number := 3;
BEGIN
:x := y;
DBMS_OUTPUT.PUT_LINE('Valoarea variabilei x este ' || :x);
END;
/

Valoarea variabilei x este 3


PL/SQL procedure successfully completed
Pentru a face referire la o variabil de legtur, numele variabilei trebuie prefixat de :. n acest fel
se va face distincie ntre aceste variabile i cele PL/SQL:
:host_sal := v_sal;
:global_var1 := TRUE;

Deoarece PL/SQL este o extensie a limbajului SQL, regulile generale de sintax ce se aplic n SQL
sunt valabile i n PL/SQL:
-

unitile lexicale (identificatori sau literali) pot fi separate de unul sau mai multe spaii sau de
ali delimitatori. Spaiile nu pot fi incluse n unitile lexicale cu excepia literalilor sau
comentariilor;

instruciunile pot fi desprite pe mai multe linii; cuvintele cheie nu pot fi desprite;

Delimitatorii utilizai n PL/SQL sunt:

Simbol
+
*
/
=
@
;

Descriere
operatorul aditiv
operatorul de diferen sau negaie
operatorul multiplicativ
operatorul de diviziune
operator relaional
indicator de acces la distan
terminator de instruciune

Simbol
<>
!=
||
-/*
*/
:=

Descriere
operator relaional
operator relaional
operatorul de concatenare
indicator de comentariu pe o linie
delimitator nceput comentariu
delimitator sfrit comentariu
operatorul de atribuire

Vizibilitatea identificatorilor n PL/SQL


Unul din avantajele PL/SQL n comparaie cu SQL const n abilitatea de a imbrica instruciuni. Se
pot imbrica blocuri oriunde este permis utilizarea instruciunilor executabile. Seciunea excepiilor
(erorilor) poate conine, de asemenea, blocuri imbricate.
Zona de vizibilitate a unui obiect este regiunea din program ce poate face referire la acel obiect.
Variabilele declarate pot fi referite n cadrul seciunii de execuie.
Un identificator este vizibil doar n blocul n care este declarat i n toate sub-blocurile, procedurile
i funciile imbricate. Dac un bloc nu gsete identificatorul declarat local, va cuta n seciunea
declarativ a blocurilor printe. Nu se caut declaraia unui identificator n sub-blocuri sau n
blocurile de pe acelai nivel.

x REAL;
BEGIN

DECLARE
y NUMBER;
BEGIN

END;

END;

zona de vizibilitate pentru x

zona de vizibilitate pentru y

n exemplul de mai sus, variabila y poate face referire la variabila x, n timp ce variabila x nu poate
referi variabila y.

Funcii PL/SQL
Aproape toate funcii ce pot fi utilizate n SQL sunt valide n PL/SQL, cu excepia funciilor grup
(MAX, MIN, AVG, SUM, COUNT) i a altor funcii speciale, cum ar fi DECODE i DUMP.
n Anexa 2 sunt prezentate cteva din funciile ce pot fi utilizate n PL/SQL.
n Anexa 3 sunt prezentate abloanele ce pot fi utilizate cu funciile TO_DATE, TO_CHAR i
TO_NUMBER.
Exemple:
SELECT TO_CHAR(SYSDATE, MONTH DDTH YYYY) Azi FROM DUAL
Azi
-----------------NOVEMBER 28TH 2006

DECLARE
v_convert_date DATE := TO_DATE(0611-2067, MMDDSYYYY);
v_hold_date
VARCHAR2(100);
BEGIN
v_hold_date := TO_CHAR(v_convert_date, MMDDSYYYY);
DBMS_OUTPUT.PUT_LINE(Data convertita este: || v_hold_date);
END;

/
Data convertita este: 0611-2067

DECLARE
v_convert_date
DATE;
BEGIN
V_convert_date:= TO_DATE(061167, DDMMYY);
DBMS_OUTPUT.PUT_LINE(Data convertita este: || v_convert_date);
END;

/
Data convertita este: 06-11-2067

DECLARE
v_convert_number
VARCHAR2(20) := 1997;
v_hold_number
NUMBER;
BEGIN
V_hold_number:= TO_NUMBER(v_convert_number, 9999);
DBMS_OUTPUT.PUT_LINE(Nr convertit este: || v_hold_number);
DBMS_OUTPUT.PUT_LINE(Nr convertit plus 10 este:||(v_hold_number+10));
END;

/
Nr convertit este: 1997
Nr convertit plus 10 este: 2007

Operatori PL/SQL
Operatorii utilizai n PL/SQL corespund celor utilizai n SQL:
Operator
**, NOT
+, *, /
+, -, ||
=, !=, <>, <, >, <=, >=, IS NULL, LIKE, BETWEEN,
IN
AND
OR

Descriere
operatorii exponenial i negaie logic
operatori de semn (+ i -)
multiplicare, diviziune
adunare, scdere, concatenare
operatori de comparaie
Conjuncie
Disjuncie

Precedena operatorilor corespunde sgeii desenate n stnga tabelului.

Instruciuni SQL n PL/SQL


PL/SQL suport toate instruciunile din Limbajul de Manipulare a Datelor (LMD) i comenzile de
control a tranzaciilor din SQL. O instruciune SQL poate fi utilizat pentru a popula variabile cu
valori rezultate din interogarea unui tabel.

Un bloc PL/SQL nu este o unitate de tranzacie. Salvarea datelor (COMMIT), setarea unor puncte de
salvare (SAVEPOINT) i revenirea la un punct de salvare sau la ultimul COMMIT (ROLLBACK) sunt
operaii independente de bloc, dar aceste instruciuni se pot executa n interiorul unui bloc. PL/SQL
nu suport instruciunile din Limbajul de Definire a Datelor (LDD), cum ar fi CREATE
TABLE, ALTER TABLE sau DROP TABLE. De asemenea, PL/SQL nu suport instruciunile
din Limbajul de Control a Datelor (GRANT, REVOKE).
Sintaxa PL/SQL pentru extragerea unor informaii din baza de date i stocarea lor n variabile
PL/SQL este:
SELECT lista_tinta
INTO
{nume_var [, nume_var] ...
| nume_inreg}
FROM
tabel
WHERE conditie;

unde:
lista_tinta

este o list format din cel puin o coloan i poate include expresii SQL i funcii
agregat;
nume_var este variabil scalar ce va memora valoarea returnat
nume_inreg este variabila de tip RECORD ce va pstra valorile returnate
tabel
indic numele tabelului
conditie
este compus din nume de coloane, expresii, constante i operatori de comparaie,
inclusiv variabile i constante PL/SQL
Exemplu:
DECLARE
v_deptno NUMBER(2);
v_loc
VARCHAR2(15);
BEGIN
SELECT deptno, loc INTO v_deptno, v_loc
FROM
dept
WHERE
dname=SALES;
DBMS_OUTPUT.PUT_LINE(Valoarea v_deptno este || TO_CHAR(v_deptno));
DBMS_OUTPUT.PUT_LINE(Valoarea v_loc este || v_loc);
END;

/
Valoarea v_deptno este 30
Valoarea v_loc este CHICAGO

Clauza INTO este OBLIGATORIE i este poziionat ntre clauzele SELECT i FROM. Aceast
clauz este utilizat pentru specificarea variabilelor ce vor memora valorile returnate de clauza
SELECT. Se furnizeaz cte o variabil pentru fiecare element din clauza SELECT, ordinea
variabilelor trebuind s corespund ordinii din lista clauzei SELECT.
Utilizarea unei instruciuni SQL ntr-un bloc PL/SQL trebuie s returneze numai o singur
linie. n caz contrar se va genera un mesaj de eroare.
Observaii:
-

instruciunile SQL trebuie terminate cu caracterul ;


clauza INTO este obligatorie atunci cnd o instruciune SQL este nglobat intr-un bloc PL/SQL

clauza WHERE este opional i poate fi utilizat pentru a specifica variabile de intrare,
constante, literali sau expresii PL/SQL
numrul variabilelor de ieire din clauza INTO trebuie s corespund numrului de coloane ce
apar n clauza SELECT.

Urmtorul exemplu returneaz suma salariilor tuturor angajailor dintr-un anumit departament.
DECLARE
v_sum
emp.sal%TYPE;
v_deptno
NUMBER NOT NULL := 10;
BEGIN
SELECT SUM(sal)
-- funcie agregat
INTO v_sum

FROM emp

WHERE deptno = v_deptno;


DBMS_OUTPUT.PUT_LINE(Valoarea variabilei v_sum este ||
TO_CHAR(v_sum));
END;

/
Valoarea variabilei v_sum este 8750

PL/SQL permite utilizarea instruciunilor de manipulare a datelor INSERT, UPDATE i DELETE.


DECLARE
v_empno
emp.empno%TYPE;
BEGIN
SELECT empno_sequence.NEXTVAL -- memoreaza urmatoarea
-- valoare a secventei in
-- variabila v_empno
INTO v_empno
FROM
dual;
INSERT INTO emp(empno, ename, job, deptno)
VALUES(v_empno, HARDING, CLERK, 10);
END;
/

Exemplul de mai sus insereaz n tabelul emp o nou nregistrare, valoarea cheii primare fiind
obinut cu ajutorul secvenei empno_sequence.
Urmtorul exemplu mrete salariile angajailor din tabelul emp avnd funcia ANALYST.
DECLARE
v_sal_increase
emp.sal%TYPE := 2000;
BEGIN
UPDATE emp
SET sal = sal + v_sal_increase
WHERE job = ANALYST;
END;

Se poate produce ambiguitate n clauza SET datorit faptului c, dei membrul stng este numele
unei coloane, membrul drept poate fi o coloan sau o variabil PL/SQL. n situaia n care o coloan
i o variabil au acelai nume, serverul Oracle va cuta n baza de date mai nti coloan, i apoi
variabila.
tergerea liniilor din tabelul emp ce corespund angajailor din departamentul 10 se poate efectua cu
ajutorul urmtorului bloc PL/SQL:
DECLARE
v_deptno
emp.deptno%TYPE := 10;
BEGIN
DELETE FROM emp
WHERE deptno = v_deptno;
END;
/

Pentru evitarea situaiilor de ambiguitate se poate avea n vedere urmtoarea convenie de denumire:
coloanele din baza de date i variabilele trebuie s aib nume distincte.
Controlul logicii tranzaciilor se poate face cu ajutorul instruciunilor COMMIT i ROLLBACK.
Sintaxa acestor instruciuni este:
COMMIT [WORK]
ROLLBACK [WORK]
unde WORK apare din motive de compatibilitate cu standardele ANSI.

Structuri de control a execuiei n PL/SQL


Principalele structuri de control a execuiei sunt construciile condiionale (instruciuni IF) i cele
repetitive.
Instruciunea IF
Instruciunea IF permite execuia selectiv a unor aciuni pe baza unor condiii. Sintaxa instruciuni
IF este:
IF conditie THEN
instructiuni;
[ELSIF conditie THEN
instructiuni;]
[ELSE
instructiuni;]
END IF;

unde:
conditie
instructiuni
ELSIF

este o variabil boolean sau o expresie (TRUE, FALSE sau NULL); ea este
asociat unei secvene de instruciuni ce se va executa dac expresia are
valoarea TRUE
pot fi una sau mai multe instruciuni PL/SQL sau SQL; pot include alte
instruciuni IF.
este un cuvnt cheie ce introduce o nou expresie boolean; dac prima
condiie este FALSE sau NULL, atunci ELSIF introduce condiii
suplimentare;

ELSE

este un cuvnt cheie, care odat atins, are ca efect execuia instruciunilor ce
urmeaz imediat dup el.

Exemplul urmtor seteaz funcia SALESMAN, numrul departamentul 35 i comisionul de 20%


din salariul curent dac numele este MILLER:

IF v_ename = MILLER THEN


v_job := SALESMAN;
v_deptno := 35;
v_comm := sal * 0.2;
END IF;

Observaii:
- se pot specifica mai multe clauze ELSIF;
- poate exista cel mult o clauz ELSE;
S considerm urmtoare structur IF:
IF conditie1 THEN
instructiuni
ELSIF conditie2 THEN
instructiuni
ELSE
instructiuni
END IF;

Modul de execuie al acestei structuri este urmtorul:


- dac se evalueaz conditie1 i rezult TRUE se vor executa instruciunile de pe ramura THEN;
- altfel se evalueaz conditie2. Dac rezult TRUE se execut instruciunile de pe ramura THEN;
- altfel se execut instruciunile de pe ramura ELSE.
Exemplu:

IF v_start > 100 THEN


v_start := 2 * v_start;
ELSIF v_start >=50 THEN
v_start := 0.5 * v_start
ELSE
v_start := 0.1 * v_start;
END IF;

Structuri repetitive
Aceste structuri sunt utilizate pentru repetarea unei instruciuni sau a unei secvene de instruciuni de
un anumit numr de ori.
1. Structuri de tip LOOP
Sintaxa acestei structuri este urmtoarea:

LOOP
instruciune1;

EXIT [WHEN conditie]


END LOOP;

unde:
conditie

este o variabil boolean sau o expresie;

De fiecare dat cnd fluxul de execuie atinge END LOOP, controlul este predat instruciunii LOOP
corespunztoare. Pentru ieirea din bucl trebuie utilizat instruciunea EXIT. Se poate executa
EXIT fie ca o aciune n cadrul unei instruciuni IF, fie ca instruciune din bucl. La instruciunea
EXIT se poate ataa o clauz WHEN de prsire condiionat a buclei.
Exemplu de utilizare a structurii LOOP:
DECLARE
v_ordid
item.ordid%TYPE := 10;
v_counter NUMBER(2) := 1
BEGIN
LOOP
INSERT INTO item(ordid, itemid) VALUES(v_ordid, v_counter);
v_counter := v_counter + 1;
EXIT WHEN v_counter > 10;
END LOOP;
END;
/

2. Structuri de tip FOR


Sintaxa instruciunii FOR este:
FOR contor IN [REVERSE]
limita_inf..lim_sup LOOP
instructiune1;
instructiune2;

END LOOP;

unde:
contor

este o variabil ntreag declarat implicit, a crei valoare este incrementat


sau decrementat (se face decrementare dac se specific REVERSE) cu o
unitate la fiecare iteraie, pn se atinge lim_sup, respectiv lim_inf.
Not: contor nu trebuie declarat ca variabil; el este declarat implicit ca ntreg.
Exemplu:
DECLARE
v_ordid item.ordid%TYPE := 101;
BEGIN
FOR i IN 1 .. 100 LOOP
INSERT INTO item(ordid, itemid)
VALUES(v_ordid, i);
END LOOP;

END;
/

3. Structuri WHILE
Cu ajutorul instruciunii WHILE se poate repeta o secven de instruciuni pn n momentul n care
condiia de control devine FALSE sau NULL.
WHILE conditie LOOP
instructiune1;
instructiune2;
...
END LOOP;

Probleme
1. Creai un bloc PL/SQL care selecteaz numrul maxim de departament din tabelul dept i
memoreaz aceast valoare ntr-o variabil SQL*Plus. Se va afia rezultatul pe ecran.
2. Creai un bloc PL/SQL care s permit introducerea unei noi nregistrri n tabelul dept. Se va
cere introducerea de la tastatur a numrului de departament i a numelui su. Verificai
inserarea noului departament.
3. Creai un bloc PL/SQL care s tearg departamentul inserat la punctul 2. Se va prelua de
tastatur numrul departamentului ce urmeaz a fi ters.
4. Creai tabelul MESAJE avnd urmtoarea schem:
MESAJE(Rezultate NUMBER(3))
Inserai n acest tabel numerele de la 1 la 10, exceptnd valorile 6 i 8. Salvai modificrile
efectuate asupra tabelului.
Coninutul tabelului dup executarea blocului PL/SQL este cea din tabelul de mai jos.
Rezultate
--------1
2
3
4
5
7
9
10

5. Creai un bloc PL/SQL care actualizeaz comisionul unui anumit angajat din tabelul emp
conform urmtoarelor reguli:
- dac salariul su este mai mic dect 1000, comisionul este de 10% din salariu;
- dac salariul su este ntre 1000 i 1500, comisionul este de 15% din salariu;
- dac salariul su este mai mare dect 1500, comisionul este de 20% din salariu;
- dac salariul su este NULL, comisionul este 0.
Numrul angajatului va fi introdus de la tastatur.
Dup ce se opereaz o modificare asupra tabelului emp salvai acea modificare.
Verificai corectitudinea modificrii.

Tipuri de date compuse


Tipurile de date compuse (cunoscute i sub numele de colecii) ce pot fi utilizate n PL/SQL sunt:
-

RECORD
TABLE
tabele imbricate
VARARRAY

n continuare vor fi prezentate doar dou dintre aceste tipuri compuse i anume tipul RECORD i
TABLE.
Tipul RECORD
O variabil de tip RECORD (numit nregistrare) reprezint o colecie de date memorate n cmpuri,
fiecare cmp avnd asociat un nume i un tip. S presupunem c dispunem de diverse informaii
despre un angajat, cum ar fi nume, salariu i data angajrii. O nregistrare ce conine cte un cmp
pentru fiecare tip de informaie permite tratarea datelor ca o singur unitate logic.
Caracteristici ale nregistrrilor:
- o nregistrare poate avea un numr arbitrar de cmpuri;
- o nregistrare poate avea o valoare iniial sau poate fi definit ca fiind NOT NULL;
- cmpurile fr valori iniiale sunt iniializate cu valori NULL;
- cuvntul cheie DEFAULT poate fi utilizat i la definirea cmpurilor;
- se pot defini tipuri RECORD i se pot declara variabile de tip nregistrare n seciunea declarativ
a oricrui bloc, subprogram sau pachet;
- se pot declara i apoi referi nregistrri imbricate (nregistrri ce au drept component o alt
nregistrare).
Sintaxa ce permite definirea tipului RECORD este:
TYPE nume_tip IS RECORD
( declaratie_camp {, declaratie_camp} );
declaratie_camp respect sintaxa:
nume_camp <tip_camp | variabila%TYPE |
tabel.coloana%TYPE | tabel%ROWTYPE>
[[NOT NULL] <:= | DEFAULT> expr]
unde: nume_tip
nume_camp
tip_camp
expr

numele tipului RECORD


numele cmpului n cadrul nregistrrii
tipul cmpului. Poate fi orice tip PL/SQL, exceptnd REF CURSOR
expresie de tipul tip_camp sau valoare iniial

Constrngerea NOT NULL previne iniializarea cmpului corespunztor cu valoarea NULL i


foreaz iniializarea cmpului.

O nregistrare se declar n seciunea declarativ, cu ajutorul sintaxei:


identificator

nume_tip;

Fiecare cmp are un nume unic i un tip de date specific. Deoarece n PL/SQL nu exist tipuri de
date predefinite pentru nregistrri, va trebui s definim mai nti tipul de date i apoi s declarm o
variabil de tipul respectiv, aa cum este ilustrat n urmtorul exemplu:
DECLARE
TYPE tip_inreg_emp IS RECORD
-- defineste un tip RECORD
(empno
NUMBER(4) NOT NULL := 100,
ename
emp.ename%TYPE,
job emp.job%TYPE);
inreg_emp tip_inreg_emp;
-- declara o variabila
....
-- de tipul tip_inreg-emp
Accesarea unui cmp dintr-o nregistrare se face pe baza numelui cmpului, conform sintaxei:
nume_inreg.nume_camp
De exemplu, accesarea cmpului job din variabila inreg_emp se face astfel:
inreg_emp.job ...
iar asignarea valorii 'CLERK' cmpului job se face cu instruciunea:
inreg_emp.job := 'CLERK';
nregistrrile definite de utilizator sunt instaniate la intrarea n bloc i nceteaz s existe la ieirea
din bloc.
Urmtorul exemplu utilizeaz o nregistrare format din trei cmpuri (ename, job, sal) pentru a
stoca informaiile furnizate de o instruciune SELECT. Trebuie s existe o coresponden ntre
cmpurile nregistrrii i lista int a instruciunii SELECT.
DECLARE
TYPE tip_inreg_emp IS RECORD
(ename emp.ename%TYPE, job emp.job%TYPE, sal emp.sal%TYPE);
inreg_emp tip_inreg_emp;
BEGIN
SELECT ename, job, sal
INTO inreg_emp
FROM emp
WHERE empno = 7369;
DBMS_OUTPUT.PUT_LINE('deptno = ' || inreg_emp.ename);
DBMS_OUTPUT.PUT_LINE('dname = ' || inreg_emp.job);
DBMS_OUTPUT.PUT_LINE('loc = ' || inreg_emp.sal);
END;
/
Atributul %ROWTYPE
DECLARE
identificator referinta%ROWTYPE
...
unde: identificator

este numele nregistrrii

referinta

este numele tabelului, vederii sau variabilei de tip cursor pe care se


bazeaz nregistrarea. Referina TREBUIE s fie valid n momentul
declarrii nregistrrii (tabelul sau vederea trebuie s existe, iar
cursorul trebuie s fie declarat).

Atributul %ROWTYPE poate fi utilizat pentru declararea unei variabile de tip nregistrare pe baza
tuturor coloanelor dintr-un tabel sau dintr-o vedere. Cmpurile din nregistrare vor prelua numele i
tipurile de date ale coloanelor din tabel sau din vedere. Exemplul urmtor declar o nregistrare
folosind atributul %ROWTYPE:
DECLARE
inreg_emp emp%ROWTYPE;
...
nregistrarea inreg_emp va fi format din urmtoarele cmpuri:
empno
ename
job
mgr
hiredate
sal
comm
deptno

NUMBER(4),
VARCHAR2(10),
VARCHAR2(9),
NUMBER(4),
DATE,
NUMBER(7, 2),
NUMBER(7, 2),
NUMBER(2)

Un cmp individual din nregistrare va fi referit folosind notaia:


identificator.nume_camp
La fel ca n cazul variabilelor scalare, instruciunea SELECT poate fi utilizat pentru a stoca valorile
returnate de o interogare ntr-o nregistrare. Singura restricie este ca instruciunea SELECT s
returneze toate coloanele din tabelul (vederea) ce st la baza definiiei nregistrrii.
-- Nu uitati sa executati SET SERVEROUTPUT ON la promptul SQL
DECLARE
inreg_dept dept%ROWTYPE; -- campurile inregistrarii corespund
BEGIN
-- coloanelor din tabelul dept
-- instructiunea SELECT se va executa cu succes doar daca
-- returneaza o singura linie
SELECT * INTO inreg_dept from dept WHERE dname = 'SALES';
DBMS_OUTPUT.PUT_LINE('Valorile memorate in inregistrare: ');
DBMS_OUTPUT.PUT_LINE('deptno = ' || inreg_dept.deptno);
DBMS_OUTPUT.PUT_LINE('dname = ' || inreg_dept.dname);
DBMS_OUTPUT.PUT_LINE('loc = ' || inreg_dept.loc);
END;
/
Tipul TABLE
Obiectele de tip TABLE, denumite i tabele PL/SQL, sunt asemntoare tabelelor din baza de date,
cu unele diferene.
Un tabel PL/SQL:
- este similar unui vector;

poate avea cel mult dou coloane:


o o cheie primar de tipul BINARY_INTEGER, ce indexeaz tabelul PL/SQL;
o o coloan scalar sau nregistrare, ce stocheaz elementele tabelului;
se poate mri n mod dinamic, deoarece nu este limitat ca dimensiune fizic.

Diferena dintre un tabel PL/SQL i un vector const n urmtoarele:


- un vector are o limit superioar pentru valoarea indexului, n timp ce indexul unui tabel
PL/SQL este nelimitat;
- un vector trebuie sa fie dens (i.e. s aib valori consecutive pentru index). Prin urmare, nu
vom putea elimina elemente din vector. Iniial, un tabel PL/SQL este dens, dar ulterior pot fi
terse elemente astfel nct s apar goluri n valorile indexului. Cu ajutorul metodei NEXT
putem determina indexul urmtorului element din tabel.
Crearea unui tabel PL/SQL implic parcurgerea urmtorilor pai:
- definirea unui tip TABLE;
- declararea unei variabile de tipul respectiv.
TYPE nume_tip IS TABLE OF
<tip_coloana | variabila%TYPE
| tabel.coloana%TYPE | tabel%ROWTYPE> [NOT NULL]
INDEX BY BINARY_INTEGER;
identificator nume_tip;
unde: nume_tip
tip_coloana
identificator

este numele tipului TABLE;


este orice tip scalar (de exemplu VARCHAR2, DATE,
NUMBER) sau compus;
este numele variabilei ce reprezint ntregul tabel PL/SQL.

DECLARE
TYPE tip_tabel_date IS TABLE OF DATE
INDEX BY BINARY_INTEGER;
tabel_datetip_tabel_date;
TYPE tip_tabel_ename IS TABLE OF emp.ename%TYPE
INDEX BY BINARY_INTEGER;
tabel_datetip_tabel_date;
...
n exemplul de mai sus au fost definite dou tipuri de date: tipul tip_tabel_date ce va conine
date calendaristice i tipul tip_tabel_ename ce va conine nume de angajai.
Ca i n cazul tabelelor din baza de date, dimensiunea unui tabel PL/SQL nu este constrns, ea
crescnd cu fiecare linie adugat. Tabelele PL/SQL pot avea o singur coloan i o cheie primar,
ambele elemente fiind nedenumite. Coloana poate aparine oricrui tip de date scalar sau compus,
dar cheia primar trebuie s fie de tipul BINARY_INTEGER. Nu se poate iniializa un tabel PL/SQL
la declarare. Gama de variaie a unei valori BINARY_INTEGER este 2.147.483.647
+2.147.483.647, deci indexul unui tabel PL/SQL poate avea valori negative. Nu este obligatoriu ca
indexarea s nceap cu valoarea 1.
Exemplul urmtor declar dou variabile de tip tabel i ilustreaz modul n care se pot referi
elementele tabelelor.
DECLARE
TYPE tip_tabel_emp IS TABLE OF emp.ename%TYPE

INDEX BY BINARY_INTEGER;
TYPE tip_tabel_hiredate IS TABLE OF DATE
INDEX BY BINARY_INTEGER;
tabel_ename
tip_tabel_ename;
tabel_hiredate tip_tabel_hiredate;
BEGIN
tabel_ename(1) := CAMERON;
tabel_hiredate(3) := SYSDATE + 7;
IF tabel_ename.EXISTS(1) THEN
INSERT INTO ...
...
END;
Referirea unei linii dintr-un tabel PL/SQL se face astfel:
nume_tabel(valoare_cheie_primara)
n exemplul de mai sus, tabel_ename(1) reprezint prima linia din tabelul tabel_ename, n
timp ce tabel_hiredate(3) indic a treia linie din tabel_hiredate.
Dac la definirea unui tip tabel se utilizeaz tabel%ROWTYPE se va crea un tabel de nregistrri
(fiecare element al tabelului va fi o nregistrare).
DECLARE
TYPE tip_tabel_dept IS TABLE OF dept%ROWTYPE
INDEX BY BIMARY_INTEGER;
tabel_dept tip_tabel_dept;
-- fiecare element din tabel_dept este o inregistrare
n acest caz, referirea unui cmp al unui element al tabelului utilizeaz sintaxa:
nume_tabel(index).nume_camp
Exemplu:
tabel_dept(3).loc := ATLANTA;
-- se initializeaza campul loc din al treilea element din
-- tabel
PL/SQL pune la dispoziie un set de metode ale obiectului TABLE. Sintaxa de apel a unei astfel de
metode este:
nume_tabel.nume_metoda [(parametri)]
Metoda
EXISTS(n)
COUNT
FIRST
LAST
PRIOR(n)
NEXT(n)

Descriere
Returneaz TRUE dac exist elementul n n tabel; ncercarea de a referi un
element ce nu exist va genera eroarea ORA-01403
returneaz numrul de elemente din tabel
- returneaz indexul primului, respectiv ultimului element din tabel;
- returneaz NULL dac tabelul este vid.
returneaz valoarea indexului care precede indexul n
returneaz valoarea indexului care succede indexul n

DELETE[(m
[,n])]

DELETE elimin toate elementele din tabel;


DELETE(n) elimin elementul de pe poziia n din tabel;
DELETE(m, n) elimin toate elementele de la poziia m la n din tabel;

Exemplu de utilizare a metodelor pentru tabele PL/SQL.


DECLARE
TYPE tip_tabel_dept IS TABLE OF dept.dname%TYPE
INDEX BY BINARY_INTEGER;
tabel_dept
tip_tabel_dept;
i
BINARY_INTEGER := 7;
v_dname
dept.dname%TYPE;
BEGIN
FOR j IN 1..4 LOOP
SELECT dname
INTO v_dname
FROM dept
WHERE deptno = j * 10;
IF i = 10 THEN
i := 2 * i;
ELSE
i := i + 1;
END IF;
tabel_dept(i) := v_dname;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Informatii tabel PL/SQL:');
DBMS_OUTPUT.PUT_LINE('Nr. valori in tabel:'||tabel_dept.count);
IF tabel_dept.EXISTS(1) THEN
DBMS_OUTPUT.PUT_LINE('Elementul cu indexul 1 exista.');
ELSE DBMS_OUTPUT.PUT_LINE('Elementul cu indexul 1 nu exista.');
END IF;
DBMS_OUTPUT.PUT_LINE('Indexul primului element:' ||
tabel_dept.first);
DBMS_OUTPUT.PUT_LINE('Indexul ultimului element:' ||
tabel_dept.last);
DBMS_OUTPUT.PUT_LINE('Indexul elem. ce precede elem. 10: '
|| tabel_dept.prior(10));
DBMS_OUTPUT.PUT_LINE('Indexul elem. ce succede elem. 10:'
|| tabel_dept.next(10));
tabel_dept.delete(20); -- sterge elementul cu indexul 20
DBMS_OUTPUT.PUT_LINE('Informatii tabel PL/SQL dupa stergere:');
DBMS_OUTPUT.PUT_LINE('Nr. valori in tabel:'||tabel_dept.count);
DBMS_OUTPUT.PUT_LINE('Indexul primului element: ' ||
tabel_dept.first);
DBMS_OUTPUT.PUT_LINE('Indexul ultimului element: '||
tabel_dept.last);
END;
Informatii tabel PL/SQL:
Nr. valori in tabel:4

Indexul primului element: 8


Elementul cu indexul 1 nu exista.
Indexul ultimului element: 20
Indexul elementului ce precede elementul 10: 9
Indexul elementului ce succede elementul 10: 20
Informatii tabel PL/SQL dupa stergere:
Nr. valori in tabel:3
Indexul primului element: 8
Indexul ultimului element: 10
PL/SQL procedure successfully completed.
Probleme
1.

Creai tabelul TOP_SAL avnd urmtoarea structur:


TOP_SAL(
nume
VARCHAR2(25),
salariu
NUMBER(11,2))

2.

Scriei un bloc PL/SQL pentru a extrage numele i salariul unui anumit angajat din tabelul emp,
pe baza numrului su de nregistrare (utilizai tabele PL/SQL).
a. declarai dou tabele PL/SQL (tabel_ename i tabel_sal) pentru a memora
temporar numele, respectiv salariul angajatului;
b. extragei din emp numele i salariul angajatului al crui numr de nregistrare a fost
furnizat de la tastatur i memorai-le n tabelele PL/SQL;
c.
inserai n TOP_SAL informaiile din tabelele PL/SQL.
Introduceti numarul de inregistrare: 7934
PL/SQL procedure successfully completed
SQL> SELECT *
2 FROM top_sal;
Nume
Salariu
------- ------MILLER
1300

Anexa 1 - Tipuri de date scalare utilizate la declararea unei variabile

Tip date
VARCHAR2 (lungime_maxima)
CHAR [(lungime_maxima)]

NUMBER[(precizie,[scala])]

BINARY_INTEGER

PLS_INTEGER
DATE

BOOLEAN
LONG
RAW (lungime)

LONG RAW (lungime)

Descriere
- ir alfanumeric de lungime variabil.
- se utilizeaz 1 octet pe caracter i poate avea o lungime maxim de
32767 octei.
- ir alfanumeric de lungime fix.
- spre deosebire de irurile VARCHAR2, un ir CHAR conine
ntotdeauna numrul maxim de caractere; irurile mai scurte dect
lungimea maxim sunt completate cu spaii.
- se utilizeaz 1 octet pe caracter i poate avea o lungime maxim de
32767 octei.
- dac nu se specific lungime_maxima, se consider valoarea
implicit de 1.
- tipul de baz pentru numerele n virgul fix sau mobil.
- precizie indic numrul de cifre utilizat pentru reprezentarea
numrului, iar scala indic poziia punctului zecimal.
- acoper domeniul de valori 1.0E-123 - 9.99E125
- utilizat pentru declararea numerelor ntregi cu semn.
- variabilele BINARY_INTEGER sunt stocate n format binar, ocupnd
astfel mai puin spaiu. De asemenea, calculele cu ntregi binari se
efectueaz mai rapid, deoarece valorile sunt deja n format binar.
- utilizat pentru declararea numerelor ntregi cu semn n domeniul
2.147.483.647...2.147.483.647
- utilizeaz instruciuni cod main native pentru realizarea calculelor.
- utilizat pentru a stoca data i momentul de timp, domeniul acoperit
fiind de la 1 ianuarie 4712 BC pn la 31 decembrie 4712 AD.
- dac nu se specific un moment de timp, se va utiliza valoarea
implicit 12:00:00 AM.
- utilizat pentru stocarea valorilor TRUE/FALSE/
- similar tipului VARCHAR2, diferena constnd n aceea c o variabil
LONG poate avea maxim 32760 caractere
- utilizat pentru a stoca iruri de date orientate pe octei.
- diferena fa de VARCHAR2 st n aceea c o valoare de tip RAW nu
va fi interpretat de Oracle (nu se face translare de seturi de caractere
pe date brute (raw)).
- argumentul lungime poate fi o valoare ntre 1 i 32767.
- similar tipului RAW.
- argumentul lungime poate fi o valoare ntre 1 i 32760.

Anexa 2 - Funcii utilizate n PL/SQL


Nume funcie
Funcii ce opereaz pe iruri de caractere
ASCII(caracter)
CHR(cod_ascii)
CONCAT(sir1, sir2)
LENGTH(sir)
LPAD(sir,lung_totala,[caract])

LPAD(sir,lung_totala,[caract])
Funcii numerice
ABS(numar)
CEIL(numar)
FLOOR(numar)
ROUND(numar, [nr_zec])

Funcii de conversie
TO_CHAR(data,format,[param_NLS])

TO_CHAR(num,format,[param_NLS])
TO_DATE(sir,format,[NLS_LANG])

TO_NUMBER(sir,format,[param_NLS])

Descriere
Returneaz echivalentul zecimal al caracterului ASCII
Returneaz caracterul avnd codul ASCII furnizat
Concateneaz cele dou iruri argumente
Returneaz lungimea irului
Completeaz sir la stnga cu caracter, lungimea maxim a
irului astfel obinut fiind lung_totala. Dac este omis
parametrul caracter se consider valoarea implicit spaiu.
Comportare similar funciei LPAD, completarea realizndu-se la
dreapta argumentului sir.
Returneaz valoarea absolut
Returneaz cel mai mic numr ntreg care este mai mare sau egal
cu numar
Returneaz cel mai mare numr ntreg care este mai mic sau egal
cu numar
Rotunjete numar la numrul de zecimale specificat. Dac
nr_zec este omis se va rotunji la ntregul cel mai apropiat; dac
nr_zec>0 rotunjirea se face la dreapta separatorului zecimal;
dac nr_zec<0 se va rotunji la stnga separatorului zecimal
Convertete o valoare DATE ntr-un ir VARCHAR2, permind
prezentarea datei ntr-un anumit format. param_NLS indic
specificarea limbii utilizat la afiarea pe ecran. O parte din
mtile de format ce pot fi utilizate sunt descrise n tabelul
urmtor.
Convertete orice numr n ir VARCHAR2. Formatele ce pot fi
utilizate sunt descrise n tabelul urmtor.
Convertete un ir de caractere (CHAR sau VARCHAR2), delimitat
de apostrofuri, la o valoare DATE. Parametrul opional
NLS_LANG permite precizarea limbii n care se va face afiarea.
Limitri:
- irul argument nu poate avea mai mult de 220 caractere;
- suntem limitai la mtile din tabelul urmtor;
- nu putem combina formatele, cum ar fi specificarea
formatului de 24 ore i, n acelai timp, AM sau PM;
- nu putem specifica acelai element de dou ori n ablonul de
conversie (de exemplu, YYYY-MM-MMM-DD)
Convertete un ir de caractere (CHAR sau VARCHAR2) sau
dat calendaristic ntr-un numr, cu scopul de a executa calcule
numerice.Mtile de formatare sunt decrise n tabelul urmtor.

Anexa 3 - abloanele utilizate cu funciile TO_DATE, TO_CHAR i


TO_NUMBER
Tip ablon
Mti de formatare DATE
BC sau B.C.
AD sau A.D.
SYYYY, YYYY
YYY, YY, Y
YEAR, SYEAR
MM
MONTH
RM
WW
W
D
DD
DDD
DAY
HH, HH12
HH24
MI
SS
AM sau A.M.
PM sau P.M.
Mti de formatare NUMERE
Masc
Exemplu
9
9999
0
$
D

09999 sau
99990
$9999
99D99

Descriere
Indicator Before Christ
Indicator Anno Domini
Anul cu 4 cifre. ntoarce un numr negativ dac se utilizeaz BC cu SYYYY.
Ultimele 3, 2 sau ultima cifr a reprezentrii anului
Returneaz anul, n litere. SYEAR returneaz o valoare negativ dac se utilizeaz cu
BC
Numrul lunii, de la 01 la 12
Numele lunii, totdeauna pe 9 caractere, eventual completate la dreapta cu spaii
Numr roman reprezentnd luna, de la I la XII
Numrul sptmnii n an, de la 1 la 53
Numrul sptmnii nlun, de la 1 la 5. Prima sptmn ncepe n prima zi a lunii
Numrul zilei din sptmn, cu valori de la 1 la 7
Numrul zilei din lun, cu valori de la 1 la 31
Numrul zilei din an, cu valori de la 1 la 366
Numrul zilei din sptmn, n litere, totdeauna reprezentat pe 9 caractere, eventual
completat la dreapta cu spaii
Ora din zi, cu valori de la 1 la 12
Ora din zi, cu valori de la 1 la 23
Numrul minutului din or, de la 0 la 59
Numrul secundei din minut, de la 0 la 59
Indicator al orei ante-meridian
Indicator al orei post-meridian

Fiecare 9 este considerat o cifr semnificativ. Zerourile din faa numrului sunt tratate
drept spaii
Zerourile din stnga sau dreapta numrului sunt tratate i afiate ca zerouri
Prefix reprezentnd simbolul monetar, plasat n faa numrului
Indic poziia punctului zecimal. Cifrele de 9 indic numrul maxim de cifre de o parte
i de alta a separatorului zecimal

Cursori n PL/SQL
La fiecare execuie a unei instruciuni SQL serverul Oracle deschide o zon de memorie n care
este analizat i executat instruciunea. Aceast zon de memorie se numete cursor.
Exist dou tipuri de cursori:
- cursor implicit;
- cursor explicit.
Cursor implicit
Un cursor implicit este deschis ori de cte ori un bloc PL/SQL execut o instruciune SQL. Acest
cursor poate fi referit cu ajutorul identificatorului SQL i este gestionat automat de PL/SQL.
Interaciunea cu un cursor implicit se poate face doar prin intermediul a patru atribute ce permit
evaluarea rezultatului execuiei ultimei utilizri a cursorului implicit. Aceste atribute sunt:
a) SQL%ROWCOUNT
- este o valoare ntreag, reprezentnd numrul de linii afectate de cea mai recent instruciune
SQL.
b) SQL%FOUND
- este TRUE dac cea mai recent instruciune SQL a afectat una sau mai multe linii.
c) SQL%NOTFOUND
- este TRUE dac cea mai recent instruciune SQL nu a afectat nici o linie.
d) SQL%ISOPEN
- are ntotdeauna valoarea FALSE deoarece PL/SQL nchide cursorul implicit imediat dup
utilizare.
Exemplul urmtor terge acele linii din tabelul emp pentru care sal = 950. Pe ecran se va
afia numrul de linii terse.
DECLARE
v_sal NUMBER := 950;
BEGIN
DELETE FROM emp
WHERE sal = v_sal;
DBMS_OUTPUT.PUT_LINE(Numar linii sterse: ||
SQL%ROWCOUNT);
END;
/
Numar linii sterse: 2
PL/SQL procedure successfully completed

Cursor explicit
Un cursor explicit se va utiliza pentru a procesa, linie cu linie, rezultatul execuiei unei
instruciuni SELECT multi-linie (instruciunea returneaz mai multe linii). Un cursor explicit
poate fi controlat conform urmtoarei diagramei din figura 1.
1. se declar cursorul (se furnizeaz numele su i interogarea cu care va fi utilizat).
2. se deschide cursorul. Instruciunea OPEN execut interogarea i realizeaz legtura cu
eventualele variabile referite. Liniile identificate de interogare formeaz mulimea activ i
sunt gata pentru a fi extrase.

No
1.
DECLARE
creeaz o zon
SQL identificat
printr-un nume

2.
OPEN
identific
mulimea
activ
(rezultatul
interogrii)

3.
FETCH
ncarc linia
curent n
variabile

EMPTY?
testeaz existena
altor linii;
se ntoarce la
FETCH dac mai
exist linii

Yes

4.
CLOSE
elibereaz
mulimea
activ

Figura1. Controlul unui cursor explicit


3. se extrag datele din cursor. Instruciunea FETCH ncarc linia curent din cursor n variabile.
Fiecare extragere determin cursorul s-i avanseze pointerul la urmtoarea linie din
mulimea activ. n diagrama anterioar fiecare extragere testeaz dac mai exist linii
neparcurse nc. Dac da, ncarc linia curent n variabile, dac nu, nchide cursorul.
4. se nchide cursorul. Instruciunea CLOSE elibereaz mulimea activ de linii.
n continuare vom analiza cei patru pai enumerai anterior.
1. Declararea unui cursor
Declararea unui cursor se face n seciunea declarativ a unui bloc PL/SQL cu ajutorul
urmtoarei sintaxe:
CURSOR nume_cursor IS
instructiune_SELECT;

unde: nume_cursor
instructiune_SELECT

este un identificator PL/SQL


este o instruciune SELECT FR clauz INTO

n instruciunea SELECT se poate face referire la alte variabile, dar acestea trebuie declarate
naintea cursorului.
DECLARE
v_deptno dept.deptno%TYPE;
CURSOR c1 IS
SELECT empno, ename
FROM emp;
CURSOR c2 IS
SELECT *
FROM dept
WHERE deptno = v_deptno;
BEGIN

...
2. Deschiderea unui cursor
Instruciunea ce realizeaz deschiderea unui cursor este
OPEN nume_cursor;

OPEN este o instruciune ce realizeaz urmtoarele operaii:


- aloc dinamic memorie pentru o zon de memorie context ce poate conine informaii
importante pentru procesare;
- valideaz corectitudinea instruciunii SELECT;

leag variabilele de intrare (seteaz valoarea variabilelor de intrare);


identific mulimea rezultat mulimea de linii ce satisfac criteriul de selecie. Execuia
acestei instruciuni nu conduce la extragerea liniilor din rezultat n variabile;
poziioneaz pointerul naintea primei linii din mulimea activ.

Not:
- dac interogarea nu returneaz nici o linie n momentul deschiderii cursorului, PL/SQL nu va
genera nici o excepie;
- n cazul cursorilor declarai cu clauz FOR UPDATE instruciunea OPEN blocheaz accesul
la liniile returnate.
3. Extragerea datelor dintr-un cursor
Instruciunea FETCH extrage cte o linie din mulimea activ. Dup fiecare extragere, cursorul
avanseaz la urmtoarea linie din mulime.
FETCH nume_cursor INTO <var1, var2, | nume_inregistrare>

unde: nume_cursor
var1, var2
nume_inregistrare

este numele unui cursor;


sunt variabile de ieire ce memoreaz rezultatele;
este numele nregistrrii n care sunt stocate datele extrase.
nregistrarea poate fi declarat utiliznd atributul
%ROWTYPE.

Indicaii:
- includei acelai numr de variabile n clauza INTO a instruciunii FETCH cte coloane sunt
precizate n lista int a instruciunii SELECT i asigurai-v c tipurile de date sunt
compatibile;
- corespondena ntre variabile i coloane se face pe baza poziiei n cele dou liste;
- ca alternativ la utilizarea variabilelor se poate declara o variabil de tip nregistrare pe baza
cursorului, clauza INTO referind nregistrarea;
- obligatoriu trebuie realizat un test pentru a verifica dac mai exist linii n cursor. Dac un
FETCH nu mai extrage nici o linie nseamn c nu mai exist linii de procesat i nu se va
genera nici o eroare.
Operaiile realizate de instruciunea FETCH sunt:
-

avanseaz pointerul la urmtoarea linie din mulimea activ;

citete datele din linia curent n variabile de ieire PL/SQL;

DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
i
NUMBER := 1;
CURSOR c1 IS
SELECT empno, ename
FROM emp;
BEGIN
OPEN c1;
FOR i IN 1..10 LOOP
FETCH c1 INTO v_empno, v_ename;
...
END LOOP;
CLOSE c1;
END;
/

Acest exemplu memoreaz n variabilele v_empno i v_ename numrul de nregistrare i


numele fiecrui angajat din tabelul emp.
4. nchiderea unui cursor
nchiderea unui cursor se realizeaz cu instruciunea
CLOSE nume_cursor;

Aceast instruciune dezactiveaz cursorul, mulimea activ devine nedefinit, iar zona context
este eliberat. ncercarea de a extrage date dintr-un cursor nchis va rezulta n ridicarea excepiei
INVALID_CURSOR.
Ca i n cazul cursorilor implicii, exist patru atribute ce pot fi utilizate pentru a obine
informaii n legtur cu starea unui cursor.
Atribut

Tip

Descriere

%ISOPEN
%NOTFOUND

boolean
boolean

%FOUND

boolean

%ROWCOUNT

number

evaluat TRUE dac este deja deschis cursorul


evaluat TRUE dac cea mai recent instruciune FETCH
nu returneaz nici o linie
evaluat TRUE dac cea mai recent instruciune FETCH
returneaz o linie
indic numrul total de linii extrase pn n momentul
respectiv

Not: ntr-o instruciune SQL nu se poate face referire la atributul unui cursor.
Metoda cea mai uzual de a procesa mai multe linii dintr-un cursor este de a utiliza o bucl
pentru a extrage cte o linie la fiecare iteraie. Dup procesarea ultimei linii, un nou FETCH va
determina evaluarea atributului %NOTFOUND la valoarea TRUE. Astfel, valoarea acestui atribut
ar trebui utilizat pentru prsirea buclei, ntruct nu mai exist alte linii de procesat. Modul de
utilizare a atributelor %NOTFOUND i %ROWCOUNT pentru specificarea condiiei de ieire din
bucl este ilustrat n urmtorul exemplu:
DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
i
NUMBER := 1;
CURSOR c1 IS
SELECT empno, ename
FROM emp;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO v_empno, v_ename;
EXIT WHEN c1%ROWCOUNT > 10 OR c1%NOTFOUND;

END LOOP;
CLOSE c1;
END;
/

Cursori i nregistrri
Am vzut cum datele returnate de o interogare pot fi stocate, linie cu linie, n variabile PL/SQL.
Se poate defini o variabil nregistrare pe baza coloanelor dintr-un cursor explicit i apoi utiliza

pentru memorarea unei linii din cursor. Avantajul const n aceea c valorile fiecrei linii vor fi
ncrcate direct n cmpurile corespunztoare din nregistrare.
Exemplul urmtor declar cursorul c1 i nregistrarea inreg_emp, avnd structura unei linii
din cursor.
...

CURSOR c1 IS
SELECT empno, ename
FROM emp;
inreg_emp
c1%ROWTYPE; -- inregistrarea va avea doua
BEGIN
-- campuri: empno si ename
OPEN c1;
...
FETCH c1 INTO inreg_emp;
...

Bucla cursor FOR


O bucl cursor FOR proceseaz liniile unui cursor explicit, realiznd urmtoarele operaii:
-

cursorul este deschis automat;


este extras, automat, cte o linie la fiecare iteraie;
cursorul este nchis automat dup ce au fost procesate toate liniile;

Sintaxa pentru o astfel de bucl FOR este:


FOR nume_inreg IN nume_cursor LOOP
instructiune1
instructiune2
...
END LOOP;

unde: nume_inreg
nume_cursor

este numele unei nregistrri declarate implicit;


este identificatorul cursorului.

DECLARE
CURSOR c1 IS
SELECT empno, ename
FROM emp;
BEGIN
FOR inreg_emp IN c1 LOOP
-- deschidere implicita i FETCH implicit
IF inreg_emp.empno = 7839 THEN
...
END IF;
END LOOP; -- inchidere automata cursor
END;
/

Not: Se poate nlocui cursorul c1 din exemplul de mai sus cu o subinterogare SQL.
Dezavantajul acestei variante const n imposibilitatea de a mai testa atributele cursorului,
cursorul nefiind declarat.
BEGIN
-- deschidere implicita i FETCH implicit
FOR inreg_emp IN (SELECT empno, ename
FROM emp) LOOP

IF inreg_emp.empno = 7839 THEN

END LOOP; -- inchidere automata cursor


END;
/

Cursori explicii cu parametri


PL/SQL permite declararea unui tip de cursor, numit cursor cu parametri, care returneaz diferite
mulimi active n funcie de valorile parametrilor. Parametrii permit pasarea de valori unui cursor
atunci cnd acesta este deschis, valori ce vor fi utilizate n execuia interogrii asociate.
Sintaxa ce permite declararea unui cursor explicit cu parametri este urmtoarea:
CURSOR nume_cursor
[(nume_parametru tip_date, )]
IS
instructiuneSQL

unde: nume_cursor
nume_parametru

este un identificator PL/SQL


este numele parametrului. Sintaxa asociat unui parametru
este urmtoarea:

nume_parametru [IN] nume_tip [<:= | DEFAULT> expr]


tip_date
instructiuneSQL

este un tip scalar de date


este o instruciune SELECT fr clauz INTO

Observaii:
- fiecrui parametru formal din declaraia cursorului trebuie s-i corespund un parametru
actual n instruciunea OPEN.
- tipurile de date ale parametrilor sunt aceleai ca n cazul variabilelor scalare, dar fr a
preciza dimensiunea.
- numele parametrilor sunt utilizate pentru referiri n interogarea asociat cursorului.
n exemplul urmtor este ilustrat modul de declarare a unui cursor cu doi parametri.
DECLARE
CURSOR c1
(v_deptno NUMBER, v_job VARCHAR2) IS
SELECT empno, ename
FROM emp
WHERE deptno = v_deptno
AND job = v_job;
BEGIN
OPEN c1(10, 'CLERK');
...
END;

Valorile pasate parametrilor unui cursor pot proveni i de la variabile PL/SQL sau variabile ale
mediului gazd.
DECLARE
job_emp emp.job%TYPE := 'CLERK';
v_ename emp.ename%TYPE;
CURSOR c1

(v_deptno NUMBER, v_job VARCHAR2) IS


SELECT empno, ename
FROM emp
WHERE deptno = v_deptno
AND job = v_job;
BEGIN
job_emp := ANALYST;
OPEN c1(10, job_emp);

END;

De asemenea se pot pasa parametri unui cursor utilizat n bucl cursor FOR:
DECLARE
CURSOR c1
(v_deptno NUMBER, v_job VARCHAR2) IS
SELECT ...
BEGIN
FOR inreg_emp IN c1(10, CLERK) LOOP
...
END LOOP;
...
FOR inreg_emp IN c1(20, ANALYST) LOOP
...
END LOOP;
END;

Variabila inreg_emp va baleia dou mulimi active diferite: mulimea angajailor ce lucreaz
n departamentul 10 i au funcia CLERK (corespunztoare primei bucle cursor FOR), respectiv
mulimea angajailor ce lucreaz n departamentul 20 i au funcia ANALYST (corespunztoare
celei de a doua bucle cursor FOR).

Clauza FOR UPDATE


Utilizarea clauzei FOR UPDATE n instruciunea SQL asociat unui cursor va avea ca efect
blocarea liniilor ce urmeaz a fi actualizate sau terse.
SELECT
FROM
FOR UPDATE [OF referinta_coloana] [NOWAIT]

unde: referinta_coloana
NOWAIT

este o coloan din tabelul supus interogrii. Se poate utiliza


i o list de coloane.
returneaz o eroare Oracle dac liniile sunt blocate de o alt
sesiune

Dac interogarea implic o jonciune ntre mai multe tabele, se pot bloca linii dintr-un anumit
tabel doar dac FOR UPDATE face referire la o coloan din acel tabel.
Clauza FOR UPDATE se va plasa la sfritul instruciunii SELECT, chiar i dup clauza ORDER
BY, dac aceasta exist.
DECLARE
CURSOR c1 IS
SELECT empno, ename
FROM emp
FOR UPDATE NOWAIT;

Exemplul anterior utilizeaz opiunea NOWAIT pentru a preveni situaia n care ar trebui s
ateptm un timp nedefinit dac liniile sunt deja blocate de alt sesiune. Pentru astfel de situaii
este indicat utilizarea opiunii NOWAIT n instruciunea SELECT FOR UPDATE i testarea,
ntr-o bucl, a codului de eroare returnat de ncercarea nereuit de a bloca liniile.

Clauza WHERE CURRENT OF


n cazul n care se dorete referirea liniei curente dintr-un cursor explicit se va utiliza clauza
WHERE CURRENT OF. Instruciunile UPDATE i DELETE ce conin aceast clauz fac referire
la ultima linie procesat de instruciunea FETCH.
WHERE CURRENT OF nume_cursor
DECLARE
CURSOR c1 IS
SELECT
FROM emp
FOR UPDATE NOWAIT;
BEGIN

FOR inreg_emp IN c1 LOOP


UPDATE
WHERE CURRENT OF c1;
END LOOP;
COMMIT;
END;

n exemplul de mai sus, instruciunea SQL UPDATE va opera asupra ultimei linii extrase din
cursor. Observai prezena clauzei FOR UPDATE n instruciunea SELECT asociat cursorului.
(se blocheaz liniile tabelului emp ce vor fi actualizate cu scopul de a elimina posibilitatea ca alt
utilizator s opereze simultan pe tabelul emp)
Probleme
1. Implementai un bloc PL/SQL ce realizeaz un top al angajailor din tabelul emp n raport cu salariile
lor.
a) cerei utilizatorului introducerea unui numr n de la tastatur;
b) extragei numele i salariile primelor n persoane din tabelul emp avnd cele mai mari salarii;
c) se presupune c nu exist doi angajai cu acelai salariu;
d) informaiile vor fi inserate n tabelul TOP_SAL;
e) testai blocul scris pentru diverse valori ale lui n: n = 0, n > nr_total_angajati.
Introduceti numarul de angajati din top: 5
PL/SQL procedure successfully completed
Nume
Salariu
--------- -------KING
5000
SCOTT
3000
FORD
3000
JONES
2975
BLAKE
2850
2. Aceeai problem ca la punctul 1, dar considernd cazul n care mai muli angajai au acelai salariu.
Dac n TOP_SAL apare o persoan, atunci trebuie s apar toate persoanele avnd acelai salariu. De

exemplu, dac n = 2 atunci n TOP_SAL trebuie s apar KING, SCOTT i FORD, iar dac n = 3
atunci trebuie s participe la top persoanele KING, SCOTT, FORD i JONES.
Introduceti numarul de angajati din top: 2
PL/SQL procedure successfully completed
Nume
Salariu
--------- -------KING
5000
SCOTT
3000
FORD
3000

3. Scriei un bloc PL/SQL pentru a extrage din baza de date toate departamentele mpreun cu angajaii
din fiecare departament. Rezultatele vor fi inserate n tabelul MESAJE. Utilizai un cursor pentru a
extrage numrul fiecrui departament i pasai fiecare numr de departament altui cursor care va
extrage angajaii din departamentul respectiv.
REZULTAT
-------------------------KING - Departament 10
CLARK - Departament 10
MILLER - Departament 10
JONES - Departament 20
FORD - Departament 20
SMITH - Departament 20
SCOTT - Departament 20
ADAMS - Departament 20
BLAKE - Departament 30
MARTIN - Departament 30
ALLEN - Departament 30
TURNER - Departament 30
JAMES - Departament 30
WARD - Departament 30
14 rows selected

Seciune opional
Tratarea excepiilor n PL/SQL
O excepie corespunde acelor evenimente nedorite ce pot apare n timpul execuiei unei aplicaii. Astfel de
evenimente pot apare din cauza cderilor sistemului sau reelei sau din cauza erorilor de programare. n mod normal,
la apariia unei erori, blocul PL/SQL i termin execuia, iar sarcina de lucru rmne neterminat. Pentru a preveni
astfel de situaii, PL/SQL pune la dispoziie un mecanism de tratare a excepiilor, astfel nct programul s-i poat
continua execuia i n prezena erorilor.
Exist dou metode de generare a unei excepii:
-

atunci cnd apare o eroare Oracle, excepia asociat este generat automat. De exemplu, dac apare eroarea
ORA-01403 n cazul n care o instruciune SELECT nu returneaz nici o linie, PL/SQL ridic excepia
NO_DATA_FOUND.

utilizatorul poate ridica explicit o excepie cu ajutorul instruciunii RAISE. Excepia poate fi definit de
utilizator sau predefinit.

Dac excepia este ridicat n seciunea executabil a blocului, motorul PL/SQL va cuta handlerul asociat din
seciunea EXCEPTION. Tratarea cu succes a excepiei va mpiedica propagarea excepiei n blocul extern sau
mediul gazd. n acest caz, execuia blocului se termin cu succes. Dac excepia este ridicat n seciunea
executabil a blocului i nu are asociat un handler, excepia va fi propagat mai departe, execuia blocului
terminndu-se cu eroare.
Exist trei tipuri de excepii:
- excepii predefinite ale serverului Oracle
- nu trebuie declarate;
- sunt generate implicit de server.
-

excepii ale serverului Oracle ce nu sunt predefinite


- trebuie declarate n seciunea declarativ;
- sunt generate implicit de server.

excepii definite de utilizator


- trebuie declarate n seciunea declarativ;
- trebuie generate explicit de utilizator.

Tratarea excepiilor
Tratarea unei excepii se realizeaz prin includerea unei rutine n seciunea de tratare a excepiilor.
EXCEPTION
WHEN exceptie1 [OR exceptie2 ] THEN
instructiune1;
instructiune2;
[WHEN exceptie3 [OR exceptie4 ] THEN
instructiune1;
instructiune2;]
[WHEN OTHERS THEN
instructiune1;
instructiune2;]
unde: exceptie
instructiune
OTHERS

este numele standard al unei excepii predefinite sau numele


unei excepii utilizator declarat n seciunea DECLARE;
este o instruciune SQL sau PL/SQL;
este o clauz opional al crei scop este de a trata excepiile nespecificate

Fiecare handler este format dintr-o clauz WHEN (care specific excepia), urmat de o secven de instruciuni ce
vor fi executate n cazul apariiei respectivei excepii. Vor fi tratate doar excepiile specificate n seciunea
EXCEPTION, iar orice alt excepie va fi tratat doar dac este inclus clauza OTHERS. Clauza OTHERS va trata
orice excepie care nu a fost tratat i din aceast cauz trebuie s fie ultima clauz n seciune. O clauz WHEN poate
trata dou sau mai multe excepii, caz n care trebuie specificate numele excepiilor conectate prin operatorul logic
OR.

Reguli de tratare a excepiilor:


- seciunea de tratare a excepiilor ncepe cu cuvntul cheie EXCEPTION;
- se definesc mai multe handlere, fiecare dispunnd de un set propriu de aciuni;
- n momentul apariiei unei excepii PL/SQL va procesa un singur handler, dup care se va termina execuia
blocului;
- clauza OTHERS se va plasa dup toate celelalte handlere;
-

poate exista cel mult o clauz OTHERS;


excepiile nu pot apare n instruciuni de atribuire sau instruciuni SQL.

Tratarea excepiilor predefinite


PL/SQL va ridica implicit o excepie predefinit ori de cte ori un program ncalc o regul Oracle. Excepiile
predefinite sunt declarate (i.e. sunt denumite) n pachetul STANDARD, deci utilizatorul nu trebuie s le atribuie
nume cu ajutorul directivei de compilare EXCEPTION_INIT (dup cum se va vedea la excepiile nedefinite).
Tratarea unei excepii predefinite se face prin specificarea numelui excepiei n rutina corespunztoare de tratare din
seciunea EXCEPTION. Tabelul urmtor conine numele ctorva erori predefinite, mpreun cu descrierea
condiiilor ce conduc la generarea erorii.
Nume excepie
ACCESS_INTO_NULL
COLLECTION_IS_NULL

CURSOR_ALREADY_OPEN
DUP_VAL_ON_INDEX
INVALID_CURSOR
INVALID_NUMBER
LOGIN_DENIED
NO_DATA_FOUND
NOT_LOGGED_ON
PROGRAM_ERROR
STORAGE_ERROR
SUBSCRIPT_BEYOND_COUNT

SUBSCRIPT_OUTSIDE_LIMIT

TIMEOUT_ON_RESOURCE
TOO_MANY_ROWS
VALUE_ERROR
ZERO_DIVIDE

Numr
Descriere
eroare
ORA-06530 ncercare de a asigna valori atributelor unui obiect ce nu
a fost iniializat
ORA-06531 ncercare de a aplica alte metode orientate pe colecii
dect EXISTS unui tabel imbricat sau varray
neiniializat
ORA-06511 ncercare de deschidere a unui cursor deja deschis
ORA-00001 ncercare de inserare a unei valori duplicat intr-o
coloana cu constrngere UNIQUE
ORA-01001 operaie ilegal asupra cursorului
ORA-01722 conversie euat de la tipul ir de caractere la numr
ORA-01017 login cu nume i/sau parol invalida
ORA-01403 SELECT single-row nu a returnat nici o linie
ORA-01012 programul PL/SQL genereaz un apel la baza de date
fr a fi conectat la ea
ORA-06501 PL/SQL are o problem intern
ORA-06500 PL/SQL nu mai are memorie sau memoria este corupt
ORA-06533 referire la un element dintr-un tabel imbricat sau
varray prin intermediul unui index ce este mai mare
dect numrul elementelor din colecie
ORA-06532 referire la un element dintr-un tabel imbricat sau
varray prin intermediul unui index ce este n afara
limitei legale (e.g. -1)
ORA-00051 expirare timp de ateptare pentru ctigarea controlului
asupra unei resurse
ORA-01422 SELECT single-row returneaz mai mult de o linie
ORA-06502 eroare aritmetic, de conversie, trunchiere
ORA-01476 ncercare de mprire prin 0

Exemplu de tratare a unor excepii predefinite:


BEGIN
SELECT ...
...
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
instructiune1;
instructiune2;
WHEN TOO_MANY_ROWS THEN
instructiune3;
WHEN OTHERS THEN

--tratare exceptie NO_DATA_FOUND


--tratare exceptie TOO_MANY_ROWS
--tratare alte exceptii

END;
/

instructiune4;
instructiune5;

Exemplul urmtor extrage din tabelul emp numele angajailor ce au ca salariu valoarea introdus de la tastatur.
Dac instruciunea SELECT nu returneaz nici o linie, Oracle va ridica excepia NO_DATA_FOUND, iar dac
SELECT returneaz mai mult de o linie va fi generat excepia TOO_MANY_ROWS. Tratarea celor doua excepii
const n afiarea pe ecran a unui mesaj de avertizare.
ACCEPT salar PROMPT 'Introduceti salariul: '
SET VERIFY OFF
DECLARE
v_ename emp.ename%TYPE;
BEGIN
SELECT ename
INTO v_ename
FROM emp
WHERE sal = &salar;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('SELECT nu a returnat nici o linie.');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('SELECT a returnat mai multe linii.');
END;
/
SET VERIFY ON
Pentru a testa blocul anterior se va introduce valoarea 1250 pentru variabila de substituie salar. Deoarece exist
mai muli angajai cu acest salar, se va genera excepia TOO_MANY_ROWS.
Introduceti salariul: 1250
SELECT a returnat mai multe linii.
PL/SQL procedure successfully completed.

Tratarea excepiilor nedefinite


O excepie nedefinit este o excepie ridicat implicit de server, dar care, spre deosebire de o excepie predefinit nu
are nume (nu este declarat n pachetul STANDARD). Tratarea unei astfel de excepii se realizeaz declarnd mai
nti excepia sau apelnd la handlerul OTHERS. n PL/SQL, directiva de compilare (pragma) EXCEPTION_INIT
instruiete compilatorul s asocieze un nume de excepie cu numrul unei erori Oracle. Astfel, vom putea face
referire la orice excepie intern prin intermediul numelui ei i vom putea scrie un handler corespunztor.
Modul de tratare a unei erori nedefinite este ilustrat n diagrama urmtoare:

Asociere

Declarare
seciunea declarativ
- denumire excepie

- asociere nume excepie


cu o eroare Oracle

Declararea unui nume de excepie se face cu sintaxa:


nume_exceptie EXCEPTION;

Asociere nume excepie cu o eroare nedefinit Oracle:

Referire
seciunea de tratare a
excepiilor
- tratare excepie

PRAGMA EXCEPTION_INIT(nume_exceptie, numar_eroare)


unde: nume_exceptie este numele unei excepii declarate anterior;
numar_eroare
este un numr standard de eroare Oracle.
referirea excepiei declarate n cadrul rutinei de tratare corespunztoare (din seciunea EXCEPTION).
Exemplul urmtor ilustreaz modul de tratare a erorii nedefinite -2291 (nclcare constrngere de integritate la
nivelul tabelului copil). Dac se utilizeaz o valoare pentru deptno ce nu exist n tabelul dept se va termina
execuia i se va afia un mesaj corespunztor. Acest exemplu presupune existena unei constrngeri de referin
(constrngere FOREIGN KEY) ntre atributul deptno din tabelul emp i atributul deptno din tabelul dept.
DECLARE
e_invalid_deptno EXCEPTION;
PRAGMA EXCEPTION_INIT(e_invalid_deptno, -2291);
BEGIN
INSERT INTO emp(empno,ename,deptno)
VALUES (8000, 'TOM', 50);
EXCEPTION
WHEN e_invalid_deptno THEN
DBMS_OUTPUT.PUT_LINE('EROARE! Numar departament invalid.');
END;
/
SQL> START test3
EROARE! Numar departament invalid.
PL/SQL procedure successfully completed.

Tratarea excepiilor utilizator


PL/SQL permite utilizatorului s defineasc excepii specifice aplicaiei. Spre deosebire de tipurile anterioare de
excepii, o excepie utilizator trebuie declarata i ridicata explicit.
O excepie utilizator poate fi tratat conform urmtoarei diagrame:

Declarare

Generare

Referire

seciunea declarativ

seciunea executabil

seciunea de tratare a
excepiilor

- denumire excepie

- generare explicit
cu ajutorul instruciunii
RAISE

- tratare excepie

Declarare excepie
O excepie utilizator poate fi declarat doar n seciunea declarativ a unui bloc PL/SQL, subprogram (procedur sau
funcie) sau pachet cu ajutorul urmtoarei sintaxe:
nume_exceptie EXCEPTION;
Exist o anumit similaritate ntre excepii i variabile din punct de vedere al regulilor privind domeniul de
existen.

a)

O excepie nu poate fi declarat de dou ori n acelai bloc, dar se poate declara o aceeai excepie n dou
blocuri diferite.
b) Excepiile declarate ntr-un bloc sunt considerate locale pentru acel bloc i globale pentru toate sub-blocurile.
Prin urmare, un bloc va putea referi o excepie local, n timp ce blocurile externe nu pot referi excepiile
declarate n sub-blocuri.
c) Dac o excepie global este redeclarat ntr-un sub-bloc, va avea ctig de cauz declaraia local.
Exemplul urmtor ilustreaz regulile enumerate mai sus:
DECLARE
past_due EXCEPTION;
acct_num NUMBER;
BEGIN
DECLARE
---- inceput sub-bloc
past_due EXCEPTION; -- aceasta declaratie
-- are castig de cauza
acct_num NUMBER;
BEGIN
...
IF ... THEN
RAISE past_due; -- exceptia locala nu este tratata
END IF;
END; ------------- sfarsit sub-bloc
EXCEPTION
WHEN past_due THEN -- nu trateaza exceptia ridicata in sub-bloc
...
END;
Blocul extern nu trateaz excepia ridicat deoarece declaraia excepiei past_due din sub-bloc are ctig de
cauz. Dei cele dou excepii au acelai nume, ele sunt diferite. Pentru ca excepia past_due s fie tratat n
blocul extern avem dou alternative: s eliminm declaraia din sub-bloc sau s definim un handler OTHERS n
blocul extern.

Utilizarea instruciune RAISE pentru generarea excepiei utilizator


O excepie utilizator trebuie ridicat explicit n momentul apariiei unei erori ce mpiedic terminarea cu succes a
operaiilor aferente programului. Acest lucru se face cu ajutorul instruciunii RAISE.
RAISE nume_exceptie;
Tratare excepie n seciunea EXCEPTION
n urmtorul exemplu se va genera o excepie utilizator dac se ncearc inserarea unei noi nregistrri n tabelul
emp, valoarea comisionului fiind diferit de NULL dei funcia angajatului nu este 'SALESMAN' (considerm
valabil regula conform creia numai angajaii cu funcia 'SALESMAN' pot avea comision).
ACCEPT comision PROMPT 'Valoare comision: ' DEFAULT NULL
ACCEPT functie PROMPT 'Introduceti functia: '
SET VERIFY OFF
DECLARE
e_invalid_comm EXCEPTION;
v_comm emp.comm%TYPE;
v_job emp.job%TYPE;
BEGIN
v_job := UPPER('&functie');
v_comm := &comision;
IF v_job <> 'SALESMAN' AND v_comm IS NOT NULL THEN
RAISE e_invalid_comm;
END IF;
INSERT INTO emp
VALUES(8001,'FROST',2500,v_job,v_comm,20);
EXCEPTION

WHEN e_invalid_comm THEN


DBMS_OUTPUT.PUT_LINE('EROARE! Valoare invalida comision.');
END;
/
SET VERIFY ON
Valoare comision: 100
Introduceti functia: ANALYST
EROARE! Valoare invalida comision.
PL/SQL procedure successfully completed.
n momentul apariiei unei excepii putem identifica codul de eroare i mesajul asociat utiliznd funciile SQLCODE
i SQLERRM.
Funcia SQLCODE returneaz valoarea numeric asociat erorii:
- 0 : nu a fost generat nici o excepie;
- 1 : excepie utilizator;
- +100 : excepie NO_DATA_FOUND;
- - ### (valoare negativ) : alte erori Oracle.
Funcia SQLERRM returneaz mesajul asociat erorii.
Urmtorul exemplu va insera n tabelul erori informaii (cod eroare i mesaj) despre ultima eroare tratat.

DECLARE
v_cod_err NUMBER;
v_mesaj_err VARCHAR2(255);
BEGIN
DELETE FROM myemp
WHERE empno = 'sal'; -- se va genera o exceptie deoarece
-- sal nu este numar
EXCEPTION
WHEN OTHERS THEN
v_cod_err := SQLCODE;
v_mesaj_err := SUBSTR(SQLERRM,1,255);
INSERT INTO erori
VALUES(TO_CHAR(v_cod_err) || ' : ' || v_mesaj_err);
END;
/
SQL> select * from erori;
ERR
--------------------------------------1722 : ORA-01722: invalid number
Observaii:
1.Funciile SQLCODE i SQLERRM nu pot fi utilizate direct n instruciuni SQL. Valorile celor dou funcii trebuie
memorate n variabile locale ce pot fi apoi utilizate cu instruciuni SQL.
2.Funcia SUBSTR a fost utilizat deoarece dimensiunea maxim a irului SQLERR este de 512 caractere. Aceast
trunchiere este necesar pentru a putea stoca mesajul asociat erorii n variabila v_mesaj_err.

Propagarea excepiilor n sub-blocuri


n cazul n care un sub-bloc trateaz o excepie, execuia sa se va termina normal i controlul este redat urmtoarei
instruciuni din blocul extern. Dac, totui, PL/SQL ridic o excepie i blocul curent nu deine un handler pentru
acea excepie, aceasta se va reproduce succesiv n blocurile externe pn cnd va gsi un handler. Dac nici un bloc
din lan nu trateaz excepia, ea se va propaga pn la mediul gazd (e.g. SQL*Plus).
DECLARE
e_zero_linii
...

EXCEPTION;

BEGIN
FOR inreg_c IN cursor_emp LOOP
BEGIN
SELECT ...
IF SQL%NOTFOUND THEN
RAISE e_zero_linii;
END IF;
EXCEPTION
WHEN e_zero_linii THEN ... -- exceptie generata de SELECT
END;
END LOOP;
EXCEPTION
WHEN TOO_MANY_ROWS THEN ... se trateaza exceptia
END;
-- generata de SELECT din sub-bloc
/
Propagarea unei excepii dintr-un sub-bloc ntr-unul aflat pe un nivel superior atrage dup sine srirea instruciunilor
ce au mai rmas de executat n sub-bloc. Un avantaj al acestei comportri const n aceea c putem separa
instruciunile ce necesit un mod exclusiv de tratare a erorilor ntr-un bloc propriu, tratnd erorile cu caracter general
n blocul extern.

Procedura raise_application_error
Procedura raise_application_error permite generarea unor mesaje de eroare definite de utilizator din
subprograme (proceduri sau funcii). Astfel, subprogramul poate raporta erori aplicaiei apelante. Sintaxa de apel a
procedurii mai sus menionate este:
raise_application_error(cod_err, mesaj [, {TRUE | FALSE}]);
unde: cod_err este un numr negativ n gama -20000 .. -20999
mesaj
este un ir de caractere de dimensiune maxim 2048 octei
TRUE
indic plasarea erorii n stiva de erori
FALSE
eroarea nlocuiete toate erorile anterioare (este opiunea implicit)
La apelul procedurii raise_application_error subprogramul i va termina execuia i va returna un numr
de eroare utilizator i un mesaj de eroare aplicaiei apelante.
CREATE PROCEDURE mareste_sal(emp_id NUMBER, suma NUMBER) IS
salariu NUMBER;
BEGIN
SELECT sal INTO salariu
FROM emp WHERE empno = emp_id;
IF salariu IS NULL THEN /* genereaza eroare utilizator */
raise_application_error(-20101, 'Lipseste salariu');
ELSE
UPDATE emp
SET sal = salariu + suma
WHERE empno = emp_id;
END IF;
END;
Programul PL/SQL ce apeleaz procedura mareste_sal poate capta i trata excepia ridicat de procedur.
DECLARE
sal_null EXCEPTION;
PRAGMA EXCEPTION_INIT(sal_null, -20101);
BEGIN
...
mareste_sal(:id, :suma); -- id si suma sunt variabile
-- declarate si initializate in
-- mediul SQL*Plus
...
EXCEPTION
WHEN sal_null THEN
...
END;
/

Probleme
4. Creai un bloc PL/SQL pentru a selecta numele unui angajat pe baza salariului furnizat de la tastatur.
a) dac salariul introdus are ca efect returnarea mai multor linii se va trata aceast excepie prin inserarea n
tabelul MESAJE a mesajului 'Exista mai multi angajati cu salariul de <salariu>'
(<salariu> este valoarea introdus de la tastatur);
b) dac nu este returnat nici o linie se va trata excepia prin inserarea n tabelul MESAJE a mesajului 'Nu
exista angajat cu salariul de <salariu>';
c)

dac este returnat o singura linie se va insera n tabelul MESAJE numele angajatului i salariul su;

d) orice alt excepie va fi tratat prin inserarea mesajului 'Au aparut alte erori.' n tabelul MESAJE;
e) testai programul pentru diverse situaii.
REZULTAT
-----------------------------------------------SMITH - 800
Exista mai multi angajati cu salariul de 3000
Nu exista angajat cu salariul de 6000
5.Scriei un bloc PL/SQL ce afieaz numrul angajailor ce au salariul cuprins ntre
sal 100, unde sal este o valoare furnizat de la tastatur.
a) dac nu exist nici un angajat care satisface condiia de mai sus, afiai un mesaj corespunztor pe ecran.
Utilizai o excepie pentru acest caz.
b) dac exist unul sau mai muli angajai care respect condiia, mesajul afiat trebuie s indice numrul lor.
c) tratai orice alt excepie prin afiarea unui mesaj ce indic faptul c au aprut alte erori.
Introduceti salariul: 800
PL/SQL procedure successfully completed.
Exista 1 angajat(i) cu salariul intre 790 si 810
Introduceti salariul: 3000
PL/SQL procedure successfully completed.
Exista 3 angajat(i) cu salariul intre 2900 si 3100
Introduceti salariul: 6000
PL/SQL procedure successfully completed.
Nu exista nici un angajat cu salariul intre 5900 si 6100

Subprograme i pachete PL/SQL

Subprograme PL/SQL
Subprogramele sunt blocuri PL/SQL care au nume, accept parametri i pot fi apelate din alte
blocuri PL/SQL. Subprogramele pot fi declarate ca proceduri sau funcii, n funcie de operaiile
efectuate: o procedur execut o aciune, iar o funcie calculeaz o valoare. Subprogramele se
pot stoca la nivelul bazei de date sau la nivelul aplicaiilor.
Tip bloc
Bloc anonim

Descriere
Bloc PL/SQL fr nume, inclus n aplicaie sau lansat
interactiv.
Procedur i funcie Blocuri PL/SQL cu nume ce sunt stocate n baza de date,
stocat
pot accepta parametri i pot fi apelate pe baza numelui.
Procedur i funcie Blocuri PL/SQL cu nume care sunt stocate fie n
stocat n aplicaie
aplicaiile dezvoltate cu Developer/2000, fie n biblioteci
i care pot fi apelate pe baza numelui.
Pachet
Modul PL/SQL care grupeaz proceduri, funcii sau
identificatori.
Declanator stocat
Bloc PL/SQL asociat cu un tabel al bazei de date i care
n baza de date
se execut la fiecare apel al unei instruciuni LMD.
Declanator stocat
Bloc PL/SQL asociat cu un eveniment al aplicaiei i care
n aplicaie
este lansat automat n momentul apariiei respectivului
eveniment.

Disponibilitate
n toate mediile
PL/SQL
Server Oracle
Modulele
Developer/2000
Server Oracle,
Developer/2000
Server Oracle
Developer/2000

Utilizarea subprogramelor ofer o serie de avantaje, cum ar fi:

extensibilitate orice set de instruciuni PL/SQL poate fi organizat sub forma unui
subprogram al crui scop este de a deservi scopurilor utilizatorului;
modularizare un program poate fi segmentat n uniti logice de cod (module) uor de
gestionat
reutilizare - un subprogram validat poate fi utilizat n diverse aplicaii. Deoarece schimbarea
definiiei sale afecteaz doar subprogramul (nu i aplicaiile apelante), este
facilitat operaia de gestiune.
abstractizare utilizarea unui subprogram presupune ca utilizatorul s tie ce face acel
subprogram, fr a fi necesar cunoaterea detaliilor de implementare.

Asemenea blocurilor PL/SQL anonime, subprogramele sunt structurate n 3 pri:


1. seciunea declarativ (opional) conine declaraii de tipuri utilizator, cursori, constante,
variabile, excepii i subprograme
2. seciunea executabil (obligatorie) conine instruciuni SQL i PL/SQL
3. seciunea de tratare a excepiilor (opional) conine codul aferent tratrii excepiilor
generate pe parcursul execuiei subprogramului

Proceduri PL/SQL
O procedur este un subprogram ce execut o anumit aciune i este definit cu ajutorul
urmtoarei sintaxe:
[CREATE [OR REPLACE]]
PROCEDURE nume_procedura[(parametru[, parametru]...)]
{IS | AS}
[declaratii locale]
BEGIN
instructiuni
[EXCEPTION
handler-e de exceptii]
END [nume_procedura];
unde:
- parametru respect sintaxa
nume_parametru mod tip_date [{:= | DEFAULT} expresie]

cuvntul cheie opional CREATE permite crearea unei proceduri stocate n baza de date
mod poate avea una din valorile: IN, OUT sau IN OUT. Aceste trei tipuri de parametru formal
sunt discutate ntr-un subcapitol separat.

O procedur este format din dou pri:


1. specificaia procedurii definete numele i parametrii acesteia; este cuprins ntre cuvntul
cheie PROCEDURE i numele procedurii sau lista de parametri;
2. corpul procedurii conine blocul PL/SQL care este executat n momentul lansrii n
execuie a procedurii; este cuprins ntre cuvintele cheie IS / AS i END.
Seciunea declarativ a unei proceduri este cuprins ntre cuvintele cheie IS i BEGIN. Spre
deosebire de blocurile anonime, din aceast seciune lipsete cuvntul cheie DECLARE.
PROCEDURE marire_sal (emp_id INTEGER, suma REAL) IS
-- sectiunea declarativa a procedurii
-- de remarcat absenta din sintaxa a cuvintului cheie DECLARE
sal_curent REAL;
sal_null EXCEPTION;
-- sectiunea executabila
BEGIN
SELECT sal INTO sal_curent
FROM emp
WHERE empno = emp_id;
IF sal_curent IS NULL THEN
RAISE sal_null;
ELSE
UPDATE emp SET sal = sal + suma
WHERE empno = emp_id;
END IF;
-- sectiunea de tratare a exceptiilor
EXCEPTION
WHEN NO_DATA_FOUND THEN daca SELECT nu returneaza nimic
DBMS_OUTPUT.PUT_LINE(Nu exista angajatul cu nr. || emp_id);
WHEN sal_null THEN -- daca sal=NULL se afiseaza un mesaj pe ecran
DBMS_OUTPUT.PUT_LINE(Salariul este NULL!);
END marire_sal;

n momentul apelrii, procedura marire_sal accept ca argument un numr de angajat i o


valoare reprezentnd mrirea salarial. Numrul angajatului este utilizat pentru a selecta salariul
curent din tabelul emp. Dac nu este gsit angajatul sau dac salariul su este NULL se va genera
o excepie ce este tratat n seciunea EXCEPTION. n caz contrar se actualizeaz salariul.
Procedura declarat mai sus poate fi apelat dintr-un alt bloc PL/SQL astfel:
DECLARE
...
BEGIN
...
marire_sal(emp_id, sal); ---...
-END;

apel procedura
emp_id si sal sunt variabile
declarate in sectiunea DECLARE
si initializate

Eliminarea unei proceduri stocate (creat cu instruciunea CREATE PROCEDURE) se face cu


ajutorul instruciunii
DROP PROCEDURE nume_procedura_stocata.

Funcii PL/SQL
Funciile sunt subprograme PL/SQL utilizate, n general, pentru a calcula o valoare. Structura
unei funcii este asemntoare structurii unei proceduri, singura diferen constnd n faptul c o
funcie trebuie s conin o instruciune RETURN. Sintaxa ce permite crearea unei funcii este
urmtoarea:
[CREATE [OR REPLACE]]
FUNCTION nume_func[(parametru[, parametru]...)] RETURN tip_data
{IS | AS}
[declaratii locale]
BEGIN
instructiuni PL/SQL
[EXCEPTION
handler-e de exceptii]
END [nume_func];

Clauza opional CREATE permite crearea unei funcii stocate n baza de date, caz n care
instruciunea poate fi executat i de la promptul SQL*Plus.
Exemplu: Urmtoarea funcie primete ca argumente un cod angajat, un salariu minim i unul
maxim. Pe baza codului este selectat salariul angajatului, iar dac salariul se afl ntre cele dou
limite (min_sal i max_sal) atunci funcia returneaz TRUE. Altfel returneaz FALSE.

FUNCTION check_sal
(emp_id NUMBER,
min_sal REAL,
max_sal REAL) RETURN boolean
IS
--v_sal REAL;
-|
BEGIN
--SELECT sal INTO v_sal
-|
FROM emp
-|
WHERE empno = emp_id;
-|
RETURN (v_sal >= min_sal) AND (v_sal <= max_sal);-|
END;
---

sectiunea
declarativa
sectiunea
executabila

Eliminarea unei proceduri stocate din baza de date se face cu instruciunea


DROP FUNCTION nume_functie.

Declararea subprogramelor
Un subprogram poate fi declarat n orice bloc anonim, subprogram sau pachet. Singura
constrngere este ca subprogramul s fie declarat dup toate variabilele blocului printe.
Datorit faptului c PL/SQL cere ca un identificator s fie declarat nainte de utilizare, urmtorul
bloc PL/SQL va genera eroare n momentul execuiei deoarece procedura p1 apeleaz procedura
p2, care nu a fost nc declarat.
DECLARE
...
PROCEDURE p1(...) IS
BEGIN
...
p2(...);
...
END;
PROCEDURE p2(...) IS
BEGIN
...
p1(...);
...
END;
BEGIN
...
END;
Problema nu se rezolv dac inversm declaraia procedurii p1 cu cea a procedurii p2, deoarece
p2 apeleaz la rndul ei procedura p1. Soluia const n declararea n avans a procedurii p2
(specificaia), urmnd ca ulterior s fie declarat complet (specificaie + corp).

DECLARE
...
PROCEDURE p2(...);
PROCEDURE p1(...) IS
...
PROCEDURE p2(...) IS
...
...

-- declaratia in avans a procedurii p2


-- contine doar specificatia procedurii

Notaia poziional i notaia prin nume


Numele parametrilor din declaraia unui subprogram (procedur sau funcie) sunt parametri
formali, n timp ce variabilele plasate n lista de parametri a apelului unui subprogram sunt
parametri actuali. La apelul unui subprogram, asocierea ntre parametrii actuali i cei formali
poate fi indicat prin utilizarea notaiei poziionale sau a notaiei prin nume.
Notaia poziional realizeaz corespondena ntre un parametru actual i parametrul formal
corespunztor prin poziia acestuia din urm n lista de parametri din specificaia
subprogramului. Pentru exemplificare s considerm urmtoarea procedur stocat:
CREATE OR REPLACE PROCEDURE test
(dept_no IN NUMBER DEFAULT NULL,
out_str OUT VARCHAR2,
run_date IN DATE DEFAULT SYSDATE) IS
BEGIN
out_str := dept_no || , || run_date;
END;
Apelul test(12, v_mgr) utilizeaz notaia poziional, n sensul c valoarea 12 este
asociat parametrului de intrare dept_no, variabila v_mgr este asociat parametrului de ieire
out_str, iar pentru parametrul run_date nu se specific o valoare (n acest caz se va utiliza
pentru parametrul run_date valoarea implicit SYSDATE data curent a sistemului).
Notaia prin nume permite stabilirea explicit a corespondenei ntre parametrul actual i cel
formal. Astfel, apelul test(out_str => v_mgr, dept_no => 12) pune n
coresponden parametrul out_str cu variabila v_mgr i parametrul dept_no cu valoarea
12. De notat c parametrii actuali pot apare n orice ordine n apelul subprogramului dac se
utilizeaz notaia prin nume. Avantajul acestei notaii const n aceea c programatorul poate
specifica doar o list parial de parametri, omind parametrii ce au valori implicite.
Oracle permite i o notaie combinat, singura regul ce trebuie respectat este ca notaia
poziional s o precead pe cea prin nume. Astfel, apelul test(out_str => v_mgr, 12)
va genera eroare.

Tipuri de parametri formali


Un parametru de tip IN permite pasarea de valori ctre subprogramul apelat. Deoarece un
parametru IN se comport ca o constant este interzis atribuirea unei valori parametrului
respectiv. De exemplu, urmtoarea atribuirea genereaz eroare de compilare:

PROCEDURE cont_debit(id_cont IN INTEGER, suma IN REAL) IS


suma_min CONSTANT REAL DEFAULT 10.0;
comision CONSTANT REAL DEFAULT 0.50;
BEGIN
IF suma < suma_min THEN
suma := suma + comision; -- se genereaz eroare de
-- compilare deoarece tipul
END IF;
-- param. suma este IN
...
END cont_debit;
Parametrul actual corespunztor unui parametru formal IN poate fi o constant, un literal, o
variabil iniializat sau o expresie. Pentru un parametru IN se poate specifica o valoare
implicit.
Un parametru de tip OUT permite returnarea de valori ctre programul apelant i se comport
asemeni unei variabile locale. Se poate modifica valoarea unui parametru OUT sau se poate referi
parametrul n orice mod, aa cum se observ i din exemplul urmtor:
PROCEDURE calc_bonus (emp_id IN INTEGER, bonus OUT REAL) IS
data_ang DATE;
bonus_lipsa EXCEPTION;
BEGIN
SELECT sal * 0.10, hiredate INTO bonus, data_ang
FROM emp
WHERE empno = emp_id;
IF bonus IS NULL THEN
RAISE bonus_lipsa;
END IF;
IF MONTHS_BETWEEN(SYSDATE, data_ang) > 60 THEN
bonus := bonus + 500;
END IF;
...
EXCEPTION
WHEN bonus_lipsa THEN
...
END calc_bonus;
Parametrul actual corespunztor unui parametru formal OUT trebuie s fie o variabil; dac este
o constant sau o expresie se genereaz eroare.
nainte de prsirea subprogramului trebuie asignate explicit valori tuturor parametrilor OUT, n
caz contrar acetia vor avea valori NULL.
Un parametru IN OUT permite pasarea de valori ctre subprogram i returnarea de valori ctre
programul apelant. Parametrul actual corespunztor unui parametru IN OUT trebuie s fie o
variabil; dac este o constant sau o expresie se genereaz eroare.

Proceduri i funcii stocate


Procedurile stocate sunt create cu instruciunea CREATE PROCEDURE, iar funciile stocate cu
instruciunea CREATE FUNCTION. Utilizarea instruciunii CREATE OR REPLACE are ca
efect tergerea subprogramului (dac exist deja) i recrearea lui n baza de date. Ambele tipuri
de subprograme permit aplicaiilor s execute o parte din funcii pe server, ceea ce conduce la
mbuntirea considerabil a performanelor.
Diferena dintre un subprogram stocat i un subprogram declarat ntr-un bloc PL/SQL
(subprogram local) este c subprogramul stocat poate fi apelat din orice aplicaie, n timp ce un
subprogram local poate fi apelat doar in blocul printe. Funciile i procedurile trebuie folosite
ntotdeauna pentru a crete modularitatea codului scris. Dac exist o poriune de cod care se
repet n interiorul unui bloc PL/SQL trebuie avut n vedere posibilitatea includerii lui ntr-o
funcie sau procedur local. Dac aceasta trebuie s fie accesibil altor aplicaii trebuie creat n
baza de date o procedur, respectiv funcie stocat.

Pachete
Un pachet este o colecie de obiecte corelate logic ce sunt stocate n baza de date i partajeaz
variabile comune, precum i proceduri sau funcii locale.
Un pachet este alctuit din dou componente:
1. specificaia pachetului conine informaii despre coninutul acestuia (definiii de constante,
variabile, cursori, subprograme); definiiile ce apar n specificaia unui pachet sunt publice,
ele fiind vizibile altor aplicaii.
2. corpul pachetului - definete cursorii i subprogramele definite n specificaia pachetului,
coninnd detalii de implementare i declaraii private ce nu pot fi accesate de alte aplicaii.
Corpul pachetului este opional dac n specificaie nu sunt declarate subprograme sau
cursori. Obiectele care nu sunt declarate n specificaie sunt locale pachetului (obiecte
private). Dup seciunea declarativ poate exista o seciunea executabil, ce conine cod de
iniializare care este executat cnd pachetul este referit pentru prima dat ntr-o sesiune.
Specificaia i corpul pachetului sunt compilate separat i sunt stocate ca dou obiecte distincte
n dicionarul de date.
Sintaxa pentru crearea unui pachet este urmtoarea:
CREATE [OR REPLACE] PACKAGE nume_pachet
{IS | AS}
[def_tip_colectie ...]
[def_tip_inregistrare ...]
[declaratie_colectie ...]
[declaratie_constanta ...]
[declaratie_exceptie ...]
[declaratie_inregistrare ...]
[declaratie_variabila ...]
[specificatie_cursor ...]
[specificatie_functie ...]
[specificatie_procedura ...]
END [nume_pachet];

[CREATE [OR REPLACE] PACKAGE BODY nume_pachet {IS | AS}


[def_tip_colectie ...]
[def_tip_Inregistrare ...]
[declaratie_colectie ...]
[declaratie_constanta ...]
[declaratie_exceptie ...]
[declaratie_inregistrare ...]
[declaratie_variabila ...]
[corp_cursor ...]
[corp_functie ...]
[corp_procedura ...]
[BEGIN
instructiuni]
END [nume_pachet];]
Prima instruciune creeaz specificaia pachetului, iar a doua corpul pachetului.
Exemplul urmtor creeaz pachetul my_pack.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

CREATE OR REPLACE PACKAGE my_pack IS


PROCEDURE p(x NUMBER);
FUNCTION f RETURN VARCHAR2;
var1 NUMBER;
var2 VARCHAR2(20);
END my_pack;
/
CREATE OR REPLACE PACKAGE BODY my_pack IS
PROCEDURE p(x NUMBER) IS
BEGIN
var1 := x;
END p;
FUNCTION f RETURN VARCHAR2 IS
BEGIN
var2 := HELLO;
RETURN var2 || || TO_CHAR(var1);
END f;
BEGIN
DBMS_OUTPUT.PUT_LINE(Pachetul my_pack a fost referit!);
END my_pack;
/

Liniile 1 6 creeaz specificaia pachetului, iar liniile 8 20 corpul pachetului. Deoarece n


specificaia pachetului sunt declarate dou subprograme (procedura p i funcia f) i dou
variabile (var1 i var2), aceste componente sunt accesibile altor programe. Procedurile i
funciile declarate n specificaie (liniile 2 i 3) trebuie s apar n corpul pachetului (liniile 912,
1317), n caz contrar se genereaz eroare. Linia 19 conine codul ce va fi executat atunci cnd
se va referi pentru prima dat pachetul my_pack.

Un apel la un pachet va fi executat de server n trei pai:


1. se verific dreptul de acces al utilizatorului se confirm c utilizatorul are dreptul s
execute subprogramul;
2. se verific validitatea subprogramului apelat se verific n dicionarul de date dac
subprogramul este valid sau nu. Dac obiectul este invalid, el este automat recompilat nainte
de a fi executat;
3. se execut subprogramul.
Pentru a face referire la subprogramele i obiectele dintr-un pachet se utilizeaz notaia cu punct:
nume_pachet.nume_variabila
nume_pachet.nume_subprogram
n exemplul urmtor este ilustrat modul de utilizare a pachetului my_pack:
BEGIN
my_pack.p(1);
DBMS_OUTPUT.PUT_LINE(my_pack.f);
END;
/
Pachetul my_pack a fost referit!
HELLO 1
PL/SQL procedure successfully completed
Pentru a recompila un pachet se utilizeaz comanda ALTER PACKAGE mpreun cu cuvntul
cheie COMPILE. Aceast cerere explicit de recompilare elimin necesitatea recompilrii
implicite n timpul execuiei i previne apariia oricrei erori de compilare asociate execuiei,
precum i scderea performanelor. Prin recompilarea unui pachet se recompileaz toate
obiectele definite n cadrul su. Urmtoarele dou comenzi recompileaz corpul pachetului
my_pack, respectiv ntregul pachet.
ALTER PACKAGE my_pack COMPILE BODY;
ALTER PACKAGE my_pack COMPILE PACKAGE;
Un pachet/subprogram se consider invalid dac, de la ultima compilare a pachetului, respectiv
subprogramului:
unul sau mai multe obiecte referite n subprogram/pachet (tabel, vedere, subprogram) au fost
modificate sau eliminate;
utilizatorului proprietar i-a fost revocat un privilegiu necesar pachetului/subprogramului;
Un pachet/subprogram este valid dac nu a fost invalidat de una din operaiile menionate mai
sus. La apelul unui subprogram valid, de sine stttor sau mpachetat, se execut codul compilat.
Dac subprogramul este invalid, nainte de execuie va fi recompilat automat.

Afiarea informaiilor referitoare la obiectele din baza de date


Pentru a obine informaii despre subprogramele/pachetele create de un utilizator se pot interoga
urmtoarele vederi din dicionarul de date: USER_OBJECTS, USER_OBJECT_SIZE,
USER_SOURCE. Coloana STATUS din vederea USER_OBJECTS precizeaz dac un anumit

obiect este valid sau invalid. Pentru a vizualiza toate obiectele stocate n schema utilizatorului
curent, precum i mrimea acestora se interogheaz vederea USER_OBJECT_SIZE. Coloana
TEXT din vederea USER_SOURCE conine un rnd pentru fiecare linie de cod surs din obiectul
stocat, iar coloana LINE reprezint numrul liniei.
Vederea USER_ERRORS poate fi interogat pentru a gsi informaii despre obiectele stocate a
cror compilare a euat. O alternativ la interogarea acestei vederi const n utilizarea comenzii
show errors, care va afia erorile generate la compilare.
n toate vederile menionate anterior (cu excepia vederii USER_OBJECTS), coloana NAME
reprezint numele obiectului, iar coloana TYPE tipul su (procedur, funcie, specificaie pachet,
corp pachet). n vederea USER_OBJECTS coloanele corespondente sunt denumite
OBJECT_NAME, respectiv OBJECT_TYPE.
Urmtoarea interogare afieaz numele, tipul i starea obiectelor stocate de tip procedur, funcie
i pachet.
SQL> SELECT object_name, object_type, status
2 FROM user_objects
3 WHERE object_type IN ('PROCEDURE','FUNCTION','PACKAGE',
'PACKAGE BODY');

OBJECT_NAME
---------------TEST
CHECK_SAL
MY_PACK
MY_PACK
MARIRE_SAL

OBJECT_TYPE
--------------PROCEDURE
FUNCTION
PACKAGE
PACKAGE BODY
PROCEDURE

STATUS
------VALID
VALID
VALID
VALID
VALID

Probleme
1. Creai tabelul vid employee, avnd aceeai structur ca tabelul scott.emp.
2. Scriei un bloc PL/SQL anonim care s insereze n tabelul employee o nregistrare, valorile
atributelor fiind introduse de la tastatur. Operaia de inserare n tabel va fi efectuat de o
procedur local.
3. Scriei un bloc PL/SQL anonim care s afieze numrul de angajai din tabelul scott.emp
ce lucreaz ntr-un anumit departament, numrul departamentului fiind introdus de la
tastatur. Va fi utilizat o funcie local care, primind un numr de departament, returneaz
numrul de angajai din acel departament.
4. tergei tabelul employee creat la punctul 1. Creai un nou tabel employee ce conine
aceleai nregistrri ca tabelul scott.emp. Creai tabelul jurnal ce va conine numr
angajat, nume angajat, salariu vechi, salariu nou i data modificrii salariului. Se vor alege
nume i tipuri de date convenabile pentru cele cinci atribute.
5. Scriei o procedur stocat care mrete cu 20% salariile angajailor din tabelul employee
ce lucreaz n departamentul furnizat ca parametru. Pentru fiecare nregistrare modificat
inserai n tabelul jurnal o nregistrare ce conine numrul i numele angajatului, salariul
vechi, salariul nou i data modificrii salariului (cu ajutorul funciei SYSDATE). Testai
procedura scris.

6. Scriei o funcie stocat care, primind ca parametru un numr de departament i o sum,


returneaz numrul de angajai din departament ce au comisionul mai mare dect valoarea
pasat ca parametru. Se vor utiliza datele din tabelul employee.
7. Implementai pachetul my_pack care conine urmtoarele componente:
o procedur care afieaz numele angajailor din tabelul employee avnd o anumit
funcie, funcia fiind dat de parametrul procedurii. Dac nu este gsit nici un angajat se
va afia un mesaj corespunztor.
o procedur care terge o nregistrare din tabelul employee, mpreun cu nregistrarea
corespunztoare (dac aceasta exist) din tabelul jurnal. tergerea se face pe baza
numrului de nregistrare furnizat ca parametru. Dac nu exist angajatul precizat se va
afia un mesaj de eroare.
o funcie care s returneze numerele departamentelor din tabelul employee i salariile
medii pe fiecare departament;
o variabil care memoreaz numrul de apelri ale celor trei subprograme de mai sus.
8. Testai pachetul de la punctul 7.

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