Documente Academic
Documente Profesional
Documente Cultură
Florin Ostafi
Baze de date
- ndrumar de laborator -
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
SQL*Plus
Scop
Mediu
Formatare
Manipulri de fiiere
Execuie
Editare
Interaciune
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.
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
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;
DEPTNO
-----10
20
30
40
LOC
---------NEW YORK
DALLAS
CHICAGO
BOSTON
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
NAME
SALARY
---- -------
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.
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)
A[PPEND] text
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;
ENAME
KING
BLAKE
CLARK
JONES
JOB
PRESIDENT
MANAGER
MANAGER
MANAGER
DEPTNO
10
30
10
20
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.
unde:
WHERE
conditie
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
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
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%;
10
Simbol
Descriere
%
_ (underscore)
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;
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
-----
Comentariu
AND
OR
NOT
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
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
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
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
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.
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
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.
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
LOC
------NEW YORK
CHICAGO
NEW YORK
DALLAS
14 rows selected.
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.
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
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
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
unde:
tabel1.coloana1 =
tabel2.coloana2(+)
ENAME
-----KING
CLARK
DEPTNO
-----10
10
DNAME
--------ACCOUNTING
ACCOUNTING
40 OPERATIONS
15 rows selected
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.
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".
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})
MAX([DISTINCT|ALL]expr)
MIN([DISTINCT|ALL] expr)
STDDEV([DISTINCT|ALL] n)
SUM([DISTINCT|ALL] n)
VARIANCE([DISTINCT|ALL] n)
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
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:
-
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
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
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
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.
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
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.
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
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
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
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
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 ).
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 :
ENAME
-----KING
6 rows selected.
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.
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
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;
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;
DEPTNO
------20
20
SAL*12
------36000
36000
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.
Enter
old
new
old
new
EMPNO ENAME
------ ------7839 KING
7782 CLARK
7934 MILLER
........
14 rows selected
JOB
---------PRESIDENT
MANAGER
CLERK
DEPTNO
-----10
10
10
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.
unde:
variabila
tip_date
FOR[MAT]
format
PROMPT
text
HIDE
DNAME
-------SALES
LOC
--------CHICAGO
unde:
tabel
coloana
valoare
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.
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.
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.
unde:
date_char
fmt
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.
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.
unde:
tabel
coloana
valoare
conditie
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;
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.
2 row updated.
unde: tabel
conditie
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.
6 rows deleted.
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.
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
O tranzacie ncepe cnd este ntlnit prima instruciune SQL executabil i se termin n momentul apariiei
unuia din urmtoarele evenimentele:
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.
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.
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.
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.
1 row updated.
Commit complete.
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.
1 row deleted.
No rows selected.
Commit complete.
Savepoint created.
SQL> INSERT
SQL> ROLLBACK TO update_done;
Rollback complete.
Consistena la citire
Utilizatorii unei baze iniiaz dou tipuri de acces la baza de date:
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.
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:
Descriere
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
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
BTI[TLE]
unde: text
multe
Comanda TTITLE este utilizat pentru a formata header-ul paginii, iar comanda BTITLE pentru footers.
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
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.
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
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
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.
Null?
Type
------------- ----------NOT NULL
NUMBER(4)
VARCHAR(10)
NUMBER
DATE
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.
numele tabelului;
numele coloanei din tabel;
textul comentariului, ncadrat de apostrofuri ( ).
[constrangere_tabel]);
unde:
schema
tabel
DEFAULT expr
coloana
tip_date
constrangere_coloana
constrangere_tabel
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
unde:
nume_constrangere
tip_constrangere
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
JOB
PRESIDENT
MANAGER
MANAGER
MANAGER
COMM
DEPTNO
10
30
10
20
Constrngere 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
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
Permis
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
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
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
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
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.
-
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
CONSTRAINT_NAME
---------------SYS_C00674
SYS_C00675
EMP_EMPNO_PK
C
C
C
P
SEARCH_CONDITION
---------------EMPNO IS NOT NULL
DEPTNO IS NOT NULL
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
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
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
Vederi complexe
1 sau mai multe
Da
Da
Nu ntotdeauna
unde:
OR REPLACE
FORCE
NOFORCE
nume_vedere
alias
subinterogare
WITH CHECK OPTION
nume_constr
WITH READ ONLY
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:
-
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
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
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
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.
-
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
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
INCREMENT BY n
START WITH n
MAXVALUE n
NOMAXVALUE
MINVALUE n
NOMINVALUE
CYCLE | NOCYCLE
CACHE n | NOCACHE
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
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;
MAX_VALUE
---------1.000E+27
100
1.000E+27
1.000E+27
INCREMENT_BY
-----------1
1
1
1
LAST_NUMBER
----------109
91
622
200381
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:
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
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.
Blocuri anonime
Un bloc anonim PL/SQL este format din trei seciuni:
-
seciunea executabil (obligatorie) conine instruciuni SQL pentru manipularea datelor din baza
de date i instruciuni PL/SQL pentru manipularea datelor din cadrul blocului;
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
unde:
identificator
expr
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;
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;
/
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;
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
x REAL;
BEGIN
DECLARE
y NUMBER;
BEGIN
END;
END;
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
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:
-
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
/
Valoarea variabilei v_sum este 8750
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.
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.
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;
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;
unde:
conditie
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;
/
END LOOP;
unde:
contor
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.
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
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
referinta
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)
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])]
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
Tip date
VARCHAR2 (lungime_maxima)
CHAR [(lungime_maxima)]
NUMBER[(precizie,[scala])]
BINARY_INTEGER
PLS_INTEGER
DATE
BOOLEAN
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.
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.
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
unde: nume_cursor
instructiune_SELECT
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;
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
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:
-
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;
/
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
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;
...
unde: nume_inreg
nume_cursor
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
unde: nume_cursor
nume_parametru
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
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).
unde: referinta_coloana
NOWAIT
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.
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.
-
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
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.
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
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.
Asociere
Declarare
seciunea declarativ
- denumire excepie