Sunteți pe pagina 1din 305

Cuprins

Avertisment: Copyright-ul traducerii apartine Catedrei de Calculatoare, Facultatea de


Automatica si Calculatoare, Universitatea "Politehnica" din Bucuresti.
Orice folosire a acestei traduceri se poate face doar cu acordul posesorului copyrightului manualului si a posesorului copyright-ului traducerii, in conditiile legii romane in
materie de drepturi de autor
CAPITOLUL 1 - Introducere in Oracle
Ce este Oracle
Produsele Oracle
SQL, SQL*PLUS si PL/SQL
Abordarea relationala
CAPITOLUL 2 - Introducere in SQL
Privire de ansamblu asupra SQL
Trasaturi caracteristice SQL
Setul de comenzi SQL
Blocul de interogare de baza
Operatorii logici
Operatori SQL
Negarea expresiilor
Interogarea datelor cu conditii multiple
Tipuri de date caracter si conditii
SELECT - Sumar
SQL*PLUS
Exercitii
Solutii
CAPITOLUL 3 - Rularea cererilor standard cu variabile substituite
Variabile in SQL*PLUS
Comanda DEFINE
Comanda ACCEPT
Exercitii
Solutii
CAPITOLUL 4 - Functii
Introducere
Functii numerice si pe caracter
Functii imbricate
Functii numerice
Exercitii
Solutii
CAPITOLUL 5 - Alte functii singulare aplicate liniilor unei baze de date
Functiile de tip data calendaristica
Formate pentru date calendaristice

Formatul de date RR ( Oracle 7 )


Functii care accepta orice tip de data la intrare
Functii imbricate revizitate
Exercitii
Solutii
CAPITOLUL 6 - Functii de grup
Lista functiilor de grup
Folosirea functiilor de grup
Solutii
CAPITOLUL 7 - Extragerea datelor din mai mult de o tabela
Join
Equi-join
Non-Equi-join
Reguli pentru join-ul tabelelor
Exercitii
Solutii
CAPITOLUL 8 - Alte metode de join
Join extern
Join-ul unei tabele cu ea insasi
Operatori de multimi
Reguli pentru folosirea operatorilor de multimi
Exercitii
Solutii
CAPITOLUL 9 - Subcereri
Subcereri ascunse
Reguli de scriere a cererilor
Subcereri corelate
Operatori
Exercitii
Solutii
CAPITOLUL 10 - SQL*PLUS si REPORTING
Comenzi SQL si SQL*PLUS
Comenzi SET
COLUMN - Optiuni
Comenzile TTITLE si BTITLE
Eliminarea valorilor duplicate si spargerea unui raport in sectiuni
Fisierul de comenzi SQL*PLUS
Exercitii
Solutii
CAPITOLUL 11 - Traversarea arborilor
Traversarea arborilor
Parcurgerea arborilor
Terminologie
Chirurgia arborelui

CAPITOLUL 12 - Crearea si definirea de structuri tabelare


Structuri de date Oracle
Limbajul de definire a datelor ( LDD )
Crearea unei tabele
Exercitii
Solutii
CAPITOLUL 13 - Managementul de tabela si dictionarul de date
Modificarea unei tabele
Alte comenzi LDD - eliminarea unei tabele
Dictionarul de date Oracle
Tabelele si vederile dictionarului de date
Folosirea lui SQL pentru a genera SQL
Exercitii
Solutii
CAPITOLUL 14 - Limbajul de manipulare a datelor
Inserarea de noi linii intr-o tabela
Inserarea informatiilor de data si timp
Copierea de linii din alta tabela
Actualizarea liniilor
Tranzactii
Exercitii
Solutii
CAPITOLUL 15 - Concurenta si blocarea: o vedere generala
Blocari
CAPITOLUL 16 - Imagini ( VIEWS )
Ce este o imagine ?
Utilizarea unei imagini cu operatii DML
Modificarea datelor prin imagini
Exercitii
Solutii
CAPITOLUL 17 - Utilizatorii si securitatea
Privilegiile si functiile sistemului
Roluri
Comanda GRANT
Privilegiile unui obiect
Comanda REVOKE
CAPITOLUL 18 - Obiecte in bazele de date: secventiale si indexate
Generatorul de numere de secventa
Indexarea
Reguli de folosire a unui index
Indexare si imbinare
Exercitii
Solutii

CAPITOLUL 19 - Introducere in PL/SQL


Ce este PL/SQL
Avantaje ale PL/SQL
Structura PL/SQL
Facilitati PL/SQL
CAPITOLUL 20 - Reprezentarea datelor
Sintaxa de baza a PL/SQL
Domeniul obiectelor
Reguli de vizibilitate
Accesarea variabilelor NON PL/SQL
Precedenta operatorilor
Folosirea PL/SQL in SQL*PLUS
Exercitii
Solutii
CAPITOLUL 21 - Interactiunea cu Oracle
Comenzi SQL in PL/SQL
Controlul tranzactiilor
Introducere in tratarea exceptiilor
Identificatori exceptie
Functii pentru prinderea erorii
Cum se propaga exceptiile?
Exercitii
Solutii
CAPITOLUL 22 - Structuri de control
Introducere in expresiile de control ale PL/SQL
Instructiunea IF
Cicluri si salturi in PL/SQL
Instructiunea EXIT
Utilizarea ciclurilor FOR pentru controlul iteratiilor
Utilizarea ciclurilor WHILE pentru controlul iteratiilor
Controlul ciclurilor imbricate
Folosirea GOTO si a etichetelor
Exercitii
Solutii
CAPITOLUL 23 - Tipuri de date compuse
Inregistrari in PL/SQL
Atributul %ROWTYPE
Inregistrari definite de utilizatori
CAPITOLUL 24 - Viata secreta a cursoarelor
Ce e un cursor?
Controlul explicit al cursorului - pasii separati
Atribute explicite pentru cursoare
Cursoarele si inregistrarile
Cursoare cu parametri

Citeva cuvinte despre eficienta


Exercitii
Solutii
CAPITOLUL 25 - Mai multe despre exceptii
Cind sunt generate exceptiile?
Exceptii definite de utilizator
Declararea numelor pentru exceptii interne
Mai multe despre tratarea exceptiilor
Exercitii
Solutii
ANEXA A - Pseudo-coloane SQL
ANEXA B - Cuvinte rezervate SQL
Cuvinte cheie
Cuvinte rezervate PL/SQL
ANEXA C - Vedere generala asupra Oracle versiunea 6
ANEXA D - Ordinea de comparatie
ANEXA E - Crearea obiectelor unie baze da date
DB2
Sintaxa declaratiei SELECT
Crearea obiectelor bazei de date
Vax Rdb/VMS
ANEXA F - Editare
ANEXA G - Exportarea continutului unei tabele intr-un fisier
Crearea tabelelor
ANEXA H - Facilitati ale PL/SQL, versiunea 2
Introducere
Subprograme PL/SQL
Declararea variabilelor si constantelor
Tipuri scalare
Date booleene
Cuvintul cheie DEFAULT
Tipuri noi de date compuse
Inregistrari definite de utilizatori
Tabele PL/SQL
ANEXA
Autorii traducerii

CAPITO LUL1
<

INTRODUCERE IN ORACLE
Acest capitol introductiv scoate in evidenta facilitatile oferite de Oracle si de produsele sale
punandu-le in contextul instrumentelor si tehnologiilor pe care le veti invata in acest
curs.Acest capitol explica de asemenea principiile de baza ale bazelor de date relationale.

CE ESTE ORACLE?
Oracle consta dintr-un set complet de constructori de aplicatii si produse pentru
utilizatori,cautand sa asigure solutii complete in tehnologia informatiei.
Aplicatiile Oracle sunt portabile peste un numar mare de statii de lucru si sisteme de operare,
de la calculatoare personale la procesoare paralele.
Oracle este inzestrat cu un flexibil Sistem de Management al Bazelor de Date(DBMS)Serverul Oracle-pentru stocarea si managementul informatiei utilizate de aplicatii.
Ultimul server Oracle ,ORACLE 7,conduce o baza de date cu toate avantajele unei structuri
relationale,avand in plus capacitatea de a stoca si executa obiecte de tip baza de date precum
proceduri si mecanisme de siguranta.

Despre Serverul ORACLE


Serverul Oracle cuprinde un DBMS care controleaza:

Stocarea de date in sfera bazelor de date dedicate


Recuperarea de date pentru aplicatii utilizand tehnici de optimizare adecvate
Securitatea bazelor de date si a taskurilor permise pentru anumiti utilizatori
Consistenta si protectia datelor,incluzand arhivarea taskurilor si mecanisme de cautare
Comunicarea si integritatea informatiilor,cand bazele de date sunt distribuite intr-o
retea.

Aplicatiile Oracle trebuie rulate pe acelasi computer la fel ca si Serverul Oracle.


Alternativ,aplicatiile si utilitarele utilizate de ele pot sa fie rulate pe un sistem local pentru
utilizator (sistemul 'client'),in timp ce Oracle DBMS ruleaza pe un altul (sistemul 'server').
In acest mediu 'client-server',un numar mare de resurse de calcul pot fi rulate.De exemplu,o
aplicatie 'Oracle Forms' poate rula pe un computer personal client,in timp ce accesarea
datelor este condusa conventional de un Server Oracle pe un computer central.

PRODUSELE ORACLE
Instrum. CDE
==========================
|| ------------------ ||
|| | Rapoarte Oracle| ||
|| ------------------ ||
Oracle Card
|| ------------------ ||
|| | Grafice Oracle | ||
Oracle Case
|| ------------------ ||
|| ------------------ ||
SQL*Plus
|| | Forme Oracle
| ||
|| ------------------ ||
Pro*Oracle
|| ------------------ ||
|| | Cart Oracl
| ||
Text Retrieval
|| -----------------| ||
==========================
Alte produse
^
^
|
|
|
|
|
|
--------------------------------------------------------------|
|
|
|
|
ORACLE7 SERVER
|
|
|
|
|
--------------------------------------------------------------|
|
|
|
|
-----------------------------|
|
|
Hard Disk
|
|
|
------------------------------

Optiuni Oracle Server


In plus fata de 'Standard Oracle7' care dispune de o multime comprehensiva de facilitati
asupra bazelor de date,mai sunt cateva facilitati suplimentare.
Acestea includ:
Optiunea procedurala
Asigura un "motor" PL/SQL versiunea 2 in interiorul serverului Oracle,care are
bilitatea de a stoca proceduri b.d.,functii si mecanism de siguranta pentru utilizarea
de catre aplicatii .
Optiunea distribuita
Suporta tranzactii care actualizeaza informatia din mai multe baze de date dintr-o
retea de baze de date distribuita,utilizand executia in doua faze.
Paralel Server Option
Suporta sisteme cuplate liber.
Oracle de incredere ("Trusted Oracle")

Pune la dispozitie o multime de facilitati aditionale de inalta securitate.

Produsele Oracle
Printre multele dezvoltari de aplicatii si produse pentru utilizatori accesibile in familia
Oracle,exista o posibilitate comuna pentru a accesa baza de date.
Daca direct sau indirect,aceasta este realizata prin Limbajul cu Structura de
Interogare(SQL),va fi un subiect pe care noi il vom trata in acest curs.
Produsele Oracle contin:
Oracle TextRetrieval
O tehnologie care adauga capabilitati de refacere completa a textului intr-o baza de
date Oracle.
Pro*Oracle
O serie de precomilatoare care permit accesul bazelor de date Oracle la limbajele de
programare C, Cobol,Fortran,PL/1,Pascal si Ada.
Oracle Card
O interfata utilizator pentru producerea aplicatiilor cu baze de date usor de folosit ce
incorporeaza grafice si facilitati multimedia.
Oracle CASE
O familie de instrumente care ajuta la analiza , designul si generarea aplicatiilor
Oracle.
SQL*Plus
Un instrument care permite o utilizare directa si interactiva a limbajului SQL pentru a
accesa serverul Oracle,utilizand comenzi ad-hoc sau prin rularea fisierelor de
comanda.

Mediul de dezvoltare auxiliar(CDE)


Instrumentul de dezvoltare a aplicatiilor principale formeaza un set inchis integrat numit
'Mediul de Dezvoltare Auxiliar'.Elementele de baza ale CDE includ limbajul procedural al lui
Oracle,PL/SQL,facilitati grafice si comunicare intre produse.
Principalele instrumente CDE sunt:
Oracle Forms V4
Permite ca aplicatii sofisticate bazate pe utilizarea ecranului sa fie construite repede si
usor si permite utilizatorului sa ceara si sa manipuleze date intr-o structura cu forma
convenabila ,la fel de bine ca afisarea imaginilor vizuale,si facilitati de accesare
prevazute de alte produse CDE.
Oracle Reports V2
Un puternic instrument de scriere a rapoartelor pentru constructia si executia
rapoartelor sofisticate cu fonturi de text si imagini multiple.
Oracle Graphics V2
Permite construirea si afisarea aplicatiilor vizuale, incluzand harti,grafice,imagini si
desene.
Oracle Book V1

Prevede abilitatea de a crea si vizualiza documente care includ hipertexte,sunete


digitale si videoclipuri.

SQL,SQL*PLUS si PL/SQL
SQL,SQL*PLUS si PL/SQL sunt facilitatile Oracle care vor fi discutate in acest curs.Este
important de inteles in fiecare caz diferentele lor,rolul si locul lor in familia Oracle.
*SQL

este limbajul utilizat pentru a accesa o baza de date relationala, inclusiv Oracle.
poate fi utilizat de fiecare instrument Oracle,cand accesul la baza de date este necesar.

*PL/SQL

este limbajul Procedural al lui Oracle pentru scrierea aplicatiilor si pentru manipularea
datelor in afara bazei de date.
poate include un subset al comenzilor SQL,cand accesul la baza de date este cerut
este accesibil in fiecare din produsele CDE.De asemenea in insusi serverul
Oracle(daca optiunea procedurala este instalata).

*SQL*Plus

este un produs Oracle in care limbajele SQL si PL/SQL pot fi utilizate.


de asemenea are propriul limbaj de comanda pentru controlul comportarii produsului
si pentru formatarea rezultatelor interogarilor SQL.

In concluzie,SQL si PL/SQL sunt limbaje care sunt utilizate intr-un numar de produse Oracle
.SQL*PluS este unul din produsele pe care acestea se afla.
Noi vom discuta acum principiile de baza ale bazelor de date relationale, pentru care Oracle
este un exemplu.

ABORDAREA RELATIONALA
-------------------------------------------------|
S#
SNAME
STATUS
CITY |
|------------------------------------------------|
|
S1
SMITH
20
LONDON |
|
S2
JONES
10
PARIS
|
|
S3
BLAKE
30
PARIS
|
-------------------------------------------------PARTI
--------------------------------------------------------|
P#
PNAME
COLOUR
WEIGHT
CITY
|
|-------------------------------------------------------|
|
P1
NUT
RED
12
LONDON
|
|
P2
BOLT
GREEN
17
PARIS
|
|
P3
SCREW
BLUE
17
ROME
|

|
P4
SCREW
RED
14
LONDON
|
--------------------------------------------------------^
coloana

ORDINI
------------------| S#
P#
QTY
|
|-----------------|
| S1
P1
300
|
| S1
P2
200
|
rand--------->| S1
P3
400
|
| S2
P1
300
|
| S2
P2
400 --|----camp
| S3
P3
200
|
-------------------

Abordarea relationala
Principiile modelului relational au fost pentru prima data expuse de Dr. E. F.Codd,care in
iunie 1970 a publicat un articol numit 'Un model relational de date pentru marile banci de
date'.In acest articol Dr. Codd a propus modelul 'relational' pentru sistemele de baze de date.
Baza de date relationala este perceputa de utilizatorii sai ca o colectie de tabele
bidimensionale care sunt usor de inteles.Sunt doar patru concepte de inteles:

tabele
coloane
randuri
campuri

Modelul relational imita procesele unei ramuri a algebrei cunoscuts sub numele de 'Algebra
relationala'. Aceste procese implica:

o colectie de obiecte cunoscute sub numele de RELATII


o multime de operatori ce actioneza asupra relatiilor pentru a produce noi relatii.

O Relatie poate fi inteleasa ca o Tabela.Modificarea datelor este reali- zata prin operatiile
relationale aplicate asupre tabelelor.
RESTRICTIE

------------------------------------------|
|
|
|
|
|
|#########################################|
|
|
|
|
|
|
|#########################################|
|
|
|#########################################|
|
|
|
|
-------------------------------------------

10

PROIECTIE

------------------------------------------|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
|
###
########
|
-------------------------------------------

Operatori relationali
Operatorii relationali sunt definiti mai jos:
Relatia Descrierea
Restrictia
este o operatie care preia si afiseaza datele din relatie.Este posibil sa se afiseze toate
randurile sau doar randurile care indeplinesc o conditie sau mai multe conditii
.Aceasta este de multe ori numita 'submultime orizontala'
Proiectia
este operatia care afiseaza anumite coloane din relatie si de aceea este numita
'submultime verticala'.
Produs
este rezultatul obtinut cand randurile a doua multimi de date sunt concatenate conform
conditiilor specificate.
Join
este rezultatul obtinut cand randurile a doua multimi de date sunt concatenate conform
conditiilor specificate.
Reuniunea
afiseaza toate randurile care apar in una ,in cealalta sau in ambele din cele doua relatii.
Intersectia
afiseaza toate randurile care apar in ambele din cele doua relatii.
Diferenta
afiseaza randurile care apar numai intr-o singura relatie (SQL utilizeaza operatorul
minus ).

11

PRODUS
-------------------------------------| SMITH |
| CLERK |
| SMITH | CLERK
|
| JONES | produs | MANAGER|------>| SMITH | MANAGER |
| ADAMS |
---------|
|
|
----------| JONES | CLERK
|
| JONES | MANAGER |
|
|
|
| ADAMS | CLERK
|
| ADAMS | MANAGER |
------------------JOIN
--------------------------------| CLARK | 10 |
| 10 | ACCOUNTING |
| MILLER | 10 | J | 20 | RESEARCH
|
| SMITH | 20 |-->| 30 | SALEH
|
| TURNER | 30 |
| 40 | OPERATIONHS|
---------------------------------

------------------------------| CLARK | 10 | 10 | ACCOUNTING|


| MILLER| 10 | 10 | ACCOUNTING|
| SMITH | 20 | 20 | RESEARCH |
| TURNER| 30 | 30 | SALES
|
-------------------------------

Proprietati ale bazelor de date relationale

O baza de date relationala apare ca o colectie de relatii(tabele) catre utilizator.


Formatul coloanei/randului este familiar si usor pentru vizualizarea datelor .
Exista o multime de operatori pentru partitionarea si combinarea
relatiilor(selectia,proiectia,produsul,joinul,uniunea, intersectia, diferenta).
Nu sunt pointeri expliciti;conexiunile sunt facute numai pe baza datelor.
Limbajul utilizat pentru interogarea bazei de date este non-procedural si similar limbii
engleze.
Utilizatorul nu specifica calea de acces si nu are nevoie sa stie cum este informatia
aranjata fizic.
Comenzile pentru refacerea datelor si acelea pentru realizarea schimbarilor in baza de
date sunt incluse intr-un singur limbaj SQL.
Exista o independenta totala a datelor.

Proprietatile relatiilor tabelare


O singura tabela are urmatoarele proprietati:

Nu exista randuri duplicate


Nu exista nume de coloana duplicate
Ordinea randurilor este neimportanta
Ordinea coloanalor este neimportanta
Valorile sunt atomice(nedecompozabile).

12

CAPITO LUL2
INTRODUCERE IN SQL
Acest capitol realizeaza o introducere in limbajul de interogare utilizat pentru a accesa o baza
de date Oracle. Multimea comenzilor SQL sunt conturate ca blocuri de interogare de baza.In
particular, noi discutam declaratiile SQL folosite la:

executia calculelor
specificarea alternativa a capetelor de coloana
concatenarea coloanelor
sortarea rindurilor
introducerea criteriilor de cautare.

Privire de ansamblu asupra SQL


Un sistem de management al bazei de date necesita un limbaj de interogare pentru a permite
utilizatorului sa acceseze datele.SQL (limbaj de interogare structurata) este limbajul utilizat
de majoritatea sistemelor de baza de date relational.
Limbajul SQL a fost dezvoltat intr-un prototip de sistem de management a bazelor de date
relationale - System R -de IBM la mijlocul anilor 1970.In 1979, Corporatia Oracle introduce
prima implementare a SQL in varianta comerciala.

Trasaturi caracteristice SQL

SQL este prezentat in limba engleza. Foloseste cuvintele select, insert,delete ca parti
ale setului de comenzi.
SQL este un limbaj neprocedural :specifica ce informatii doresti,nu cum sa le obtii.Cu
alte cuvinte SQL nu iti cere sa specifici metoda de acces la date.Toate cererile SQL
folosesc optimizarea cererilor- o parte a RDBMS- pentru a determina rapid
remedierea datelor specifi- cate.Aceste trasaturi usureaza obtinerea rezultatelor dorite.
Procesarea SQL asupra inregistrarilor nu se poate face decit asupra unei singure
inregistrari la un moment dat.Cea mai comuna forma a unui set de inregistrari este un
tabel.
SQL poate fi folosit de un sir de utilizatori incluzand DBA, programatori de aplicatii
,personal de management si multe alte tipuri de utilizatori.
SQL pune la dispozitie comenzi pentru o varietate de tascuri incluzand:
o date interogate
o inserarea,extragerea si stergerea rindurilor intr-un tabel.
o crearea,modificarea si stergerea obiectelor de tip baza de date
o controlul accesului la baza de date si la obiectele de tip baza de date.
o garantarea consistentei bazei de date

La inceput sistemele de management a bazei de date a utilizat un limbaj separat pentru fiecare
categorie in parte.SQL le-a unificat pe toate acestea intr-un singur limbaj.

13

SQL a devenit un limbaj standard industrial pentru bazele de date relatio- nale . Institutul
National American de Standarde(ANSI) a adoptat SQL ca limbaj standard pentru RDBMS in
anul 1986.Organizatia Internationala de Standarde (ISO) a adoptat deasemenea SQL ca
limbaj standard pentru RDBMS.Toate RDBMS-urile suporta unele forme de SQL si toti
vinzatorii de RDBMS intentioneaza sa se alinieze la standardele ANSI.

Setul de comenzi SQL


Comanda + Descriere:
SELECT
este comanda cea mai utilizata ; este folosita pentru obtinerea datelor din bazele de
date
INSERT
aceste trei comenzi sunt utilizate pentru a introduce noi
UPDATE
rinduri,pentru a schimba rindurile existente si stergerea
DELETE
rindurilor nedorite din tabelele bazelor de date respective. (Ele sunt cunoscute in
ansamblu ca DML sau comenzi ale limbajului de manipulare a datelor.)
CREATE
aceste trei comenzi sunt utilizate dinamic pentru a crea ,
ALTER
utiliza si sterge orice structura de date,de exemplu,tabele,
DROP
expuneri ,indecsi.(Ele sunt cunoscute sub numele colectiv DDL sau comenzi ale
limbajelor de definire a datelor).
GRANT
aceste doua comenzi sunt utilizate pentru a da sau a lua
REVOKE
drepturile de acces pentru bazele de date si structurile din Oracle.
N.B. Acestea sunt o parte a comenzilor SQL. Pentru o lista mai completa de comenzi se
recomanda - Manualul de Referinta a Limbajului SQL- .

Scrierea comenzilor SQL


Cand scriem comenzi SQL ,este important sa ne reamintim cateva reguli simple pentru
construirea unor declaratii valide care sunt si usor de citit si de editat:

Comenzile SQL pot fi pe una sau mai multe linii.


Clauzele sunt uzual plasate pe linii separate.
Tabelarea poate fi folosita.
Cuvintele de comanda nu pot fi separate pe mai multe linii.
Comenzile SQL nu sunt 'case sensitive'.
O comanda SQL este introdusa la promptul SQL si liniile subsecventelor sunt
numarate.
O singura declaratie poate fi considerata curenta cat timp ea este in buffer si poate fi
rulata intr-un numar de moduri :
o plasand un punct si virgula(;) la sfarsitul ultimei clauze.
14

o
o
o

plasand un punct si virgula /slash la ultima linie in buffer.


plasand un slash(/) la promptul SQL.
scriind un R[UN] (comanda SQL) la promptul SQL.

Fiecare din urmatoarele declaratii sunt valide:


SELECT * FROM EMP;
SELECT
*
FROM
EMP
;
SELECT *
FROM EMP;
In acest manual comenzile SQL sunt sparte in clauze pentru claritate.

Blocul de interogare de baza


Declaratia SELECT regaseste informatia din baza de date implementand toti operatorii din
algebra relationala .
In cele mai simple forme trebuie sa contina:
1. O clauza SELECT ,care listeaza coloanele pentru afisare astfel incat este esentiala o
Proiectie.
2. O clauza FROM care specifica tabela implicata.
Pentru a lista toate numerele departamentelor,numele angajatilor si
numarul managerilor in tabela EMP introduceti urmatoarele:
SELECT
FROM
DEPTNO
-----20
30
30
20
30
30
10
20
10
30
20
30
20
10

DEPTNO,ENAME,MGR
EMP;
ENAME
---------SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER

MGR
----7902
7698
7698
7839
7698
7839
7839
7566
7698
7788
7698
7566
7782

15

De remarcat ca numele coloanelor sunt separate prin spatiu.


Este posibil sa selectam toate coloanele din tabela prin specificarea
unui asterix ('*') dupa cuvantul SELECT .
SELECT
FROM
EMPNO
----7369
7499
7521
7566
7654
7698
7782
7788
7839
7844
7876
7900
7902

*
EMP;

ENAME
------SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD

JOB
MGR
------- ---CLERK
7902
SALESMAN 7698
SALESMAN 7698
MANAGER 7839
SALESMAN 7698
MANAGER 7839
MANAGER 7839
ANALYST 7566
PRESIDENT
SALESMAN 7698
CLERK
7788
CLERK
7698
ANALYST 7566

HIREDATE
SAL
--------- --------13-JUL-83
800.00
15-AUG-83 1,600.00
26-MAR-84 1,250.00
31-OCT-83 2,975.00
05-DEC-83 1,250.00
11-JUN-84 2,850.00
14-MAY-84 2,450.00
05-MAR-84 3,000.00
09-JUL-84 5,000.00
04-JUN-84 1,500.00
04-JUN-84 1,100.00
23-JUL-84
950.00
05-DEC-83 3,000.00

COMM DEPTNO
------- -----20
300.00
30
500.00
30
20
1.400.00
30
30
10
20
10
.00
30
20
30
20

Alte elemente in clauza SELECT


Este posibil sa se includa si alte elemente in clauza SELECT.

Expresii aritmetice
Alias-uri de coloane
Coloane concatenate
Literali

Toate aceste optiuni ajuta utilizatorul sa ceara date si sa le manipuleze in functie de scopurile
interogarii ; de exemplu,executia calculelor,legarea coloanelor impreuna,sau afisarea sirurilor
de litere din text.

Expresii aritmetice
O expresie este o combinatie de una sau mai multe valori,operatori si functii care sa
evalueaza la o valoare.
Expresiile aritmetice pot contine nume de coloane ,valori numerice constante si operatori
aritmetici:
Operatori
--------+
*
/

SELECT
FROM

Descriere
--------adunare
scadere
inmultire
impartire

ENAME, SAL*12, COMM


EMP;

16

Daca expresia aritmetica contine mai mult decat un operator, prioritatile sunt *,/,la
inceput,apoi +,- (de la stanga la dreapta pentru operatorii de aceeasi prioritate).
In urmatorul exemplu,inmultirea (250*12) este evaluata prima;apoi valoarea salariului este
adunata la rezultatul multiplicarii(3000). Astfel pentru randul lui SMITH avem
:800+3000=3800.
SELECT ENAME,SAL + 250 * 12
FROM
EMP;

Parantezele pot fi utilizate pntru specificarea ordinii de executie a operatorilor ,daca,de


exemplu ,adunarea e dorita inainte de inmultire:
SELECT
FROM

ENAME,(SAL + 250) * 12
EMP;

Aliasuri de coloana
Cand se afiseaza rezultatul unei interogari,SQL*Plus in mod normal utilizeaza numele
coloanelor selectate ca titlu.In multe cazuri acest nume poate fi criptic sau fara inteles.
Puteti schimba un titlu de coloana utilizand un 'ALIAS'.
Un alias de coloana da unei coloane un nume de titlu alternativ la iesire.
Specificati aliasul dupa coloana in lista selectata.Prin default, titlurile alias vor fi fortate la
litere mari si nu pot contine blankuri,numai daca aliasul este inclus intre ghilimele(" ").
Pentru a afisa titlul de coloana ANNSAL pentru salariul anual insemnand SAL*12,utilizati
un alias de coloana:
SELECT
FROM

ENAME,SAL*12 ANNSAL,COMM
EMP;

Odata definit ,un alias poate fi utilizat de comenzile SQL care sunt tratate in capitolele 10 si
11.
Nota:
Intr-o declaratie SQL ,un alis de coloana poate fi utilizat numai in clauza SELECT.

Operatorul de concatenare
Operatorul de concatenare (||) permite coloanelor sa fie legate cu alte coloane,expresiilor
aritmetice sau valorilor constante sa creeze o expresie de caractere.
Coloanele din cealalta parte a operatorului sunt combinate pentru a obtine o singura coloana.

17

Pentru a combina EMPNO si ENAME si sa se dea aliasul EMPLOYEE expresiei, introduceti:


SELECT
FROM

EMPNO||ENAME
EMP;

EMPLOYEE

EMPLOYEE
------------------------------------------------------7369SMITH
7499ALLEN
7521WARD
7566JONES
7654MARTIN
7698BLAKE
7782CLARK
7788SCOTT
7839KING
7844TURNER
7876ADAMS
7900JAMES
7902FORD
7934MILLER

Literali
Un literal este orice caracter ,expresie ,numar inclus in lista lui SELECT care nu este un
nume de coloana sau un alias de coloana.
Un literal in lista lui SELECT este reprezentat de fiecare rand returnat la iesire.Sirurile de
literali dintr-un text cu un format oarecare pot fi incluse in rezultatul interogarii si sunt tratate
ca o coloana lista selectata.
Literalii de tip data calendaristica si caracter pot fi inchisi intre ghilimele simple(');literlalii de
tip numar nu au nevoie de ghilimele simple(').
Urmatoarea declaratie contine literali selectati prin concatenare si printr-un alias de coloana:
SELECT

FROM

EMPNO||'-'||ENAME EMPLOYEE,
'WORKS IN DEPARTMENT',
DEPTNO
EMP;

EMPLOYEE
'WORKS IN DEPARTMENT'
------------------ -------------------7369-SMITH
WORKS IN DEPARTMENT
7499-ALLEN
WORKS IN DEPARTMENT
7521-WARD
WORKS IN DEPARTMENT
7566-JONES
WORKS IN DEPARTMENT
7654-MARTIN
WORKS IN DEPARTMENT
7698-BLAKE
WORKS IN DEPARTMENT
7782-CLARK
WORKS IN DEPARTMENT
7788-SCOTT
WORKS IN DEPARTMENT
7839-KING
WORKS IN DEPARTMENT
7844-TURNER
WORKS IN DEPARTMENT
7876-ADAMS
WORKS IN DEPARTMENT

18

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

7900-JAMES
7902-FORD
7934-MILLER

WORKS IN DEPARTMENT
WORKS IN DEPARTMENT
WORKS IN DEPARTMENT

30
20
10

Tratarea valorilor nule


Daca unui rand ii lipseste o valoare pentru o anumita coloana ,despre acea valoare se spune
ca este nula.
O valoare nula este o valoare care este sau incorecta,sau necunoscuta,sau inaplicabila.O
valoare nula nu este la fel ca 'zero'.Zero este un numar.Valoarea nula ocupa un octet in
reprezentarea interna.
Valoarea nula este tratata corect de catre SQL.
Daca orice valoare de coloana intr-o expresie este nula atunci rezultatul este nul.In
urmatoarea declaratie numai Salesman are un rezultat al salariului:
SELECT
FROM

ENAME,SAL*12 + COMM ANNUAL_SAL


EMP;

ENAME
ANNUAL_SAL
--------- ---------SMITH
ALLEN
19500
WARD
15500
JONES
MARTIN
16400
BLAKE
CLARK
SCOTT
KING
TURNER
18000
ADAMS
JAMES
FORD
MILLER

Daca dorim sa obtinem un rezultat pentru toti angajatii,este necesar sa convertim valoarea
nula la un numar . Noi folosim functia NVL pentru a converti o valoare nula la o valoare
nenula.
Folositi functia NVL pentru a converti valoarea nula de la declaratia precedenta la 0.
SELECT
FROM

ENAME, SAL*12+NVL(COMM,0) ANNUAL_SAL


EMP;

ENAME
ANNUAL_SAL
--------- ---------SMITH
9600

19

ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER

19500
15500
35700
16400
34200
29400
36000
60000
18000
13200
11400
36000
15600

NVL asteapta doua argumente:


1. o expresie
2. o valoare nenula
De notat ca puteti folosi functia NVL pentru a converti un numar nul , data calendaristica sau
sir de caractere la un alt numar , data calendaristica sau sir de caractere de acceasi lungime si
de acelasi tip de date asteptate.
NVL(DATECOLUMN,'01-JAN-88')
NVL(NUMBERCOLUMN,9)
NVL(CHARCOLUMN,'STRING')

Prevenirea selectiei rindurilor duplicate


Daca nu se indica altfel, SQL*Plus afiseaza rezultatul unei interogari fara eliminarea
intrarilor duplicate .
Pentru a lista toate numerele de departament din tabela EMP, introduceti:
SELECT
FROM

DEPTNO
EMP;

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

20

10

Clauza DISTINCT
Pentru eliminarea valorilor duplicate din rezultat, includeti restrictia DISTINCT in comanda
SELECT.
Pentru a elimina valorile duplicate afisate in exemplul urmator introduceti:
SELECT
FROM

DISTINCT
EMP;

DEPTNO

DEPTNO
-----10
20
30

Coloane multiple pot fi specificate dupa restrictia DISTINCT si restrictia DISTINCt


afecteaza toate coloanele selectate.
Pentru a afisa valorile distincte ale lui DEPTNO si JOB,introduceti:
SELECT
FROM
DEPTNO
-----10
10
10
20
20
20
30
30
30

DISTINCT DEPTNO,JOB
EMP;
JOB
--------CLERK
MANAGER
PRESIDENT
ANALYST
CLERK
MANAGER
CLERK
MANAGER
SALESMAN

Aceasta afiseaza o lista a tuturor combinatiilor diferite de ocupatie si numere de


departamente.
De notat ca restrictia DISTINCT poate sa fie referita numai o singura data si trebuie sa
urmeze imediat dupa cuvantul de comanda SELECT.

Clauza ORDER BY
In mod normal ordinea rindurilor intoarse in rezultatul unei cereri este nedefinita .Clauza
ORDER BY poate fi utilizata pentru a sorta rindurile.
Daca o folosim, clauza ORDEY BY trebuie sa fie intotdeauna ultima in declaratia SELECT.

21

Pentru a sorta dupa ENAME, introduceti:


SELECT
FROM
ORDER BY

ENAME,JOB,SAL*12,DEPTNO
EMP
ENAME;

ENAME
--------ADAMS
ALLEN
BLAKE
CLARK
FORD
JAMES
JONES
KING
MARTIN
MILLER
SCOTT
SMITH
TURNER
WARD

JOB
SAL*12 DEPTNO
------- -------- -----CLERK
13200
20
SALESMAN
19200
30
MANAGER
34200
30
MANAGER
29400
10
ANALYST
36000
20
CLERK
11400
30
MANAGER
35700
20
PRESIDENT 60000
10
SALESMAN
15000
30
CLERK
15600
10
ANALYST
36000
20
CLERK
9600
20
SALESMAN
18000
30
SALESMAN
15000
30

Ordonarea de default a datelor


Ordinea sortarii de default este ascendenta:

Valorile numerice cele mai mici primele


Valorile de tip date calendaristice cele mai mici primele.
Valorile de tip caracter in ordinea alfabetica.

Inversarea ordinii de default


Pentru a inversa aceasta ordine cuvintul de comanda DESC este specificat dupa numele
coloanei in clauza ORDER BY.
Pentru a inversa ordinea coloanei HIREDATE, deci datele cele mai tirzii sa fie afisate
primele,introduceti:
SELECT
FROM
ORDER BY

ENAME,JOB,HIREDATE
EMP
HIREDATE DESC;

ENAME
--------JAMES
KING
BLAKE
TURNER
ADAMS
CLARK
WARD
SCOTT
MARTIN
FORD

JOB
--------CLERK
PRESIDENT
MANAGER
SALESMAN
CLERK
MANAGER
SALESMAN
ANALYST
SALESMAN
ANALYST

HIREDATE
--------23-JUL-84
09-JUL-84
11-JUN-84
04-JUN-84
04-JUN-84
14-MAY-84
26-MAR-84
05-MAR-84
05-DEC-83
05-DEC-83

22

MILLER
JONES
ALLEN
SMITH

CLERK
MANAGER
SALESMAN
CLERK

21-NOV-83
31-OCT-83
15-AUG-83
13-JUN-83

Ordonarea dupa mai multe coloane


Este posibil sa se ordoneze dupa mai multe coloane.Limita este numarul de coloane din
tabela.In clauza ORDER BY se specifica coloanele pentru ordonat separate prin virgula.Daca
una sau toate coloanele trebuie sa fie inversate specificati DESC dupa fiecare coloana.
Pentru a ordona dupa doua coloane si afisa in ordinea inversa a salariului, introduceti:
SELECT
FROM
ORDER BY

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

DEPTNO,JOB,ENAME
EMP
DEPTNO,SAL DESC;

JOB
-----------PRESIDENT
MANAGER
CLERK
ANALYST
ANALYST
MANAGER
CLERK
CLERK
MANAGER
SALESMAN
SALESMAN
SALESMAN
SALESMAN
CLERK

ENAME
------KING
CLARK
MILLER
SCOTT
FORD
JONES
ADAMS
SMITH
BLAKE
ALLEN
TURNER
WARD
MARTIN
JAMES

Pentru a ordona dupa o coloana nu este necesar sa o avem SELECT-ata.

ORDER BY si valorile nule


In Oracle7,valorile nule sunt afisate ultimele pentru secventele ascendente si sint raportate
primele cind rindurile sunt sortate in ordine descendenta.
Atentie:
Clauza ORDER BY este utilizata intr-o interogare cind se doreste sa se afiseze rindurile intro ordine specifica .Fara clauza ORDER BY randurile sunt returnate intr-o ordine convenita
de ORACLE si va trebui sa ne bazam pe el- ordinea determinata fiind consistenta de la cerere
la cerere.De notat ca ordinea de afisare a rindurilor nu influenteaza ordinea interna a
rindurilor asa cum sunt stocate in tabela.

Clauza WHERE
Clauza WHERE corespunde operatorului 'Restrictie' din algebra relationala.

23

Contine o conditie pe care rindurile trebuie sa o indeplineasca in ordinea afisarii lor.


Clauza WHERE ,daca este folosita , trebuie sa urmeze clauzei FROM :
SELECT
FROM
WHERE

coloane
tabela
anumite conditii sunt intilnite

Clauza WHERE poate compara valori in coloana ,valori literale,expresii aritmetice sau
functii.
Clauza WHERE asteapta trei elemente:
1. Un nume de coloana
2. Un operator de comparatie
3. Un nume de coloana, constanta sau lista de valori.
Operatorii de comparatie sunt utilizati in clauza WHERE si pot fi impartiti in doua categorii:
logici si SQL.

Operatorii logici
Acesti operatori verifica urmatoarele conditii:
Operator
-------=
>
>=
<
<=

Semnificatie
-----------egal cu
mai mare decit
mai mare sau egal
mai mic decit
mai mic sau egal

Sirurile de caractere si datele calendaristice in clauza WHERE


Coloanele din ORACLE pot avea urmatoarele tipuri:caracter,numar sau data calendaristica.
Sirurile de caractere si datele calendaristice din clauza WHERE trebuie sa fie inchise in
ghilimele simple('). Sirurile de caractere trebuie sa se supra- puna cu valoarea coloanei daca
nu, trebuie modificate de o functie. Utilizati "Functii pe Caractere" din capitolul 4.
Pentru a afisa numele,numerele,ocupatia si departamentele tuturor functionarilor, introduceti:
SELECT
FROM
WHERE

ENAME, EMPNO, JOB, DEPTNO


EMP
JOB = 'CLERK';

ENAME
EMPNO
--------- ----SMITH
7369
ADAMS
7876
JAMES
7900
MILLER
7934

JOB
DEPTNO
------- -----CLERK
20
CLERK
20
CLERK
30
CLERK
10

24

Pentru a gasi toate numele de departamente cu numerele de departament mai mare ca 20


,introduceti:
SELECT
FROM
WHERE

DNAME, DEPTNO
DEPT
DEPTNO >20;

DNAME
---------SALES
OPERATIONS

DEPTNO
-----30
40

Compararea unei coloane cu alta in cadrul aceluiasi rand


Puteti compara o coloana cu o alta coloana in acelasi rand,la fel ca si cu o valoare constanta.
De exemplu ,presupunem ca dorim sa obtinem acei angajati al caror comision est mai mare
decat salariul lor:
SELECT
FROM
WHERE
ENAME
-----MARTIN

ENAME, SAL, COMM


EMP
COMM> SAL;
SAL
-------1,250.00

COMM
-------1,400.00

Operatori SQL
Sint patru operatori SQL care opereaza pe toate tipuril de date:
Operatori SQL
Operator
-------BETWEEN..AND...
IN(list)
LIKE
IS NULL

Semnificatie
-----------intre doua valori(inclusiv)
compara cu o lista de valori
compara cu un model de tip caracter
est o valoare nula

Operatorul BETWEEN
Realizeaza teste pentru valori intre,si inclusiv,o valoare minima si o valoare maxima.
Presupunind ca dorim sa vedem angajatii ai caror salariu este intre 1000 si 2000:
SELECT
FROM
WHERE

ENAME,SAL
EMP
SAL BETWEEN 1000 AND 2000;

25

ENAME
SAL
------- ---------ALLEN
1,600.00
WARD
1,250.00
MARTIN
1,250.00
TURNER
1,500.00
ADAMS
1,100.00
MILLER
1,300.00

De notat ca valorile specificate sunt inclusive si ca limita minima trebuie specificata prima.

Operatorul IN
Testeaza valorile dintr-o lista specificata.
Presupunem ca dorim sa gasim angajatii care au unul din cele trei numere de marca(MGR):
SELECT
FROM
WHERE
EMPNO
----7369
7788
7876
7902

ENAME
----SMITH
SCOTT
ADAMS
FORD

EMPNO, ENAME, SAL, MGR


EMP
MGR IN (7902,7566,7788);
SAL
MGR
--------- ----800.00 7902
3,000.00 7566
1,100.00 7788
3,000.00 7566

Daca, caracterele sau datele calendaristice sunt utilizate,ele trebuie introduse intre ghilimele('
').

Operatorul LIKE
Uneori nu se cunosc valorile exacte pe care le cautam.Utilizand operatorul LIKE este posibil
sa selectam randurile care se potrivesc cu un model specificat de caractere.Operatia de pettermatching a caracterelor poate fi asemanata cu o cautare 'wild-card'.Doi simboli se pot utiliza
la construirea sirului de cautare.
Simbol
-----%
-

Reprezentare
-----------orice secventa de zero sau mai multe caractere
un singur caracter oarecare

Pentru a lista toti angajatii al caror nume incepe cu un S,introduceti:


SELECT
FROM
WHERE

ENAME
EMP
ENAME LIKE 'S%';

ENAME
-------SMITH
SCOTT

Caracterul '_' poate fi utilizat pentru cautarea unui anumit numar de carac- tere.
De exemplu pentru a lista toti angajatii care au un nume exact de patru caractere lungime:

26

SELECT
FROM
WHERE

ENAME
EMP
ENAME LIKE '____';

ENAME
----WARD
KING
FORD

Semnele '%' si '_'pot fi utilizate in orice combinatie de caractere.

Operatorul IS NULL
Operatorul IS NULL face teste specifice pentru valorile care sunt NULL.
SELECT
FROM
WHERE
ENAME
-----KING

ENAME,MGR
EMP
MGR IS NULL;
MGR
----

Negarea expresiilor
Urmatorii operatori fac teste de negatie:
Operator
--------!=
^=
<>
NOT NUMECOL=
NOT NUMECOL>

Descriere
---------diferit de(VAX,UNIX,PC)
diferit de(IBM)
diferit de(toate o/s)
diferit de
mai mic sau egal

Operatori SQL
Operator
-------NOT BETWEEN
NOT IN
NOT LIKE
IS NOT NULL

Descriere
--------nu se afla intre doua valori date
nu se afla intr-o lista data de valori
diferit de sirul
nu este o valoare nula

Pentru a gasi angajatii ai caror salariu nu este intr-un interval,introdu- ceti:


SELECT
FROM
WHERE

ENAME,SAL
EMP
SAL NOT BETWEEN 1000 AND 2000;

ENAME
--------SMITH
JONES
BLAKE
CLARK
SCOTT
KING
JAMES
FORD

SAL
-------800.00
2,975.00
2,850.00
2,450.00
3,000.00
5,000.00
950.00
3,000.00

27

Pentru a afla acei angajati a caror meserie nu incepe cu M,introduceti:

SELECT
FROM
WHERE
ENAME
-------SMITH
ALLEN
WARD
MARTIN
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER

ENAME,JOB
EMP
JOB NOT LIKE 'M%';
JOB
-------CLERK
SALESMAN
SALESMAN
SALESMAN
ANALYST
PRESIDENT
SALESMAN
CLERK
CLERK
ANALYST
CLERK

Pentru a afla toti angajatii care au un manager(MGR),introduceti:


SELECT
FROM
WHERE

ENAME,MGR
EMP
MGR IS NOT NULL;

ENAME
MGR
------- ----SMITH
7902
ALLEN
7698
WARD
7698
JONES
7839
MARTIN
7698
BLAKE
7839
CLARK
7839
SCOTT
7566
TURNER
7698
ADAMS
7788
JAMES
7698
FORD
7566
MILLER
7782

Nota:
Daca o valoare NULL este utilizata intr-o comparatie ,atunci operatorul de comparatie
trebuie sa fie IS sau IS NOT NULL. Daca acesti operatori nu sunt uti lizati si valoarea
NULL este comparata,atunci rezultatul este intotdeauna FALSE
De exemplu, COMM!=NULL este intotdeauna falsa.Rezultatul este fals deoarece o
valoare NULL poate sa nu fie egala sau diferita cu orice alta valoare alta decat NULL.
De notat ca o astfel de eroare nu este semnalata,rezultatul fiind intotdea- una fals.

Interogarea datelor cu conditii multiple


Operatorii AND sau OR pot fi utilizati pentru a compune expresii logice.
28

Predicatul AND este adevarat numai daca ambele conditii sunt 'adevarate'; predicatul OR este
adevarat daca cel putin una din conditii este 'adevarata'.
In urmatoarele doua exemple,conditiile sunt aceleasi,dar predicatele difera Priviti cum
rezultatul este dramatic modificat.
Pentru a gasi toti functionarii care castiga intre
1000 si 2000,introduceti:
SELECT
FROM
WHERE
AND

EMPNO,ENAME,JOB,SAL
EMP
SAL BETWEEN 1000 AND 2000
JOB = 'CLERK';

EMPNO ENAME
JOB
---------- -------7876 ADAMS
CLERK
7934 MILLER
CLERK

SAL
-------1,100.00
1,300.00

Pentru a afla toti angajatii care sunt si functionari si/sau


functionari care castiga intre 1000 si 2000,introduceti:
SELECT
FROM
WHERE
OR
EMPNO
----7369
7499
7521
7654
7844
7876
7900
7934

EMPNO,ENAME,JOB,SAL
EMP
SAL BETWEEN 1000 AND 2000
JOB = 'CLERK';

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

JOB
------CLERK
SALESMAN
SALESMAN
SALESMAN
SALESMAN
CLERK
CLERK
CLERK

SAL
-------800.00
1,600.00
1,250.00
1,250.00
1,500.00
1,100.00
950.00
1,300.00

Puteti combina AND sau OR in acceasi expresie logica. Cand AND sau OR apar in aceeasi
clauza WHERE, toti operatorii AND sunt evaluati mai intai si apoi toti operatorii OR. Vom
spune ca operatorii AND au o precedenta mai mare decat OR.
Deoarece AND are o precedenta mai mare decat OR urmatoarea declaratie SQL intoarce toti
managerii cu salarii peste 1500$ si toti vanzatorii.
SELECT
FROM
WHERE
AND
OR
EMPNO
----7499
7521
7566

EMPNO,ENAME,JOB,SAL,DEPTNO
EMP
SAL> 1500
JOB = 'MANAGER'
JOB = 'SALESMAN';

ENAME
------ALLEN
WARD
JONES

JOB
-------SALESMAN
SALESMAN
MANAGER

SAL DEPTNO
-------- -----1,600.00
30
1,250.00
30
2,975.00
20

29

7654
7698
7782
7844

MARTIN
BLAKE
CLARK
TURNER

SALESMAN
MANAGER
MANAGER
SALESMAN

1,250.00
2,850.00
2,450.00
1,500.00

30
30
10
30

Daca doriti sa selectati toti managerii si vanzatorii


cu salarii peste 1500$ puteti introduce:
SELECT
FROM
WHERE
AND
OR
EMPNO
----7499
7566
7698
7782

EMPNO,ENAME,JOB,SAL,DEPTNO
EMP
SAL >1500
(JOB = 'MANAGER'
JOB = 'SALESMAN');
ENAME
-----ALLEN
JONES
BLAKE
CLARK

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

SAL DEPTNO
-------- -----1,600.00
30
2,975.00
20
2,850.00
30
2,450.00
10

Parantezele specifica ordinea in care operatorii vor fi evaluati. In al doilea exemplu


operatorul OR este evaluat inaintea operatorului AND.

TIPURI DE DATE CARACTER SI CONDITII


ENAME
(VARCHAR2)
___________
|
|
| SCOTT V V|
|
___|
| SCOTT|____
|
|
| MILLER
|
|
|
~~~~ ~~ ~~~

WHERE ENAME = 'SCOTT'

Oracle nu face umplerea cu blancuri la compararea


cu coloanele VARCHAR2

ENAME
(CHAR)
-----------|
|
| SCOTT V V|
|
....|
| SCOTT|V V|
|
|. |
| MILLER| V|
~~~~ ~~~~ ~~

WHERE ENAME = 'SCOTT'

Oracle face umplerea cu blancuri la compararea


cu coloanele CHAR.

30

Tipurile de date caracter si conditii


Tipurile de baza ale datelor stocate intr-o tabela oracle sunt:caracter, valoare numerica sau
data calendaristica.Vom discuta toate variantele in detaliu mai tarziu.De cate ori rezultatele
unei conditii implica date de tip caracter, acestea pot varia in functie de tipul
coloanei;ORACLE inzestreaza coloanela cu tipul CHAR pentru valori de lungime fixa si cu
tipul VARCHAR2 pentru valori de lungime variabila.
Pentru coloanele cu tipul VARCHAR2 ,Oracle nu umple sirul de comparare si de aceea va
face o potrivire exacta.In primul exemplu,doar un singur rand este intors pentru conditia:
WHERE ENAME = 'SCOTT'

cand un alt rand stocat in coloana ENAMe are mai multe caractere decat sirul de comparat.
Pentru coloanele cu tipul CHAR ,oricum,Oracl face umplere cand valorile coloanelor sunt
initial stocate,facandu-le pe toate de aceeasi lungime.
Aceeasi conditie va intoarce ambele randuri pentru SCOTT ,indiferent de cate spatii de sfarsit
au fost adaugate cand valorile au fost stocate in tabela.
Oracle umple cu blancuri sirul de comparat in cel deal doilea caz si de aceea spatiile stocate
sunt nesemnificative.

Precedenta operatorilor
Toti operatorii sunt aranjati intr-o ierarhie ceea ce le determina precedenta .Intr-o expresie
operatiile sunt executate in ordinea precedentei lor de la mare la mica.
Cand operatorii au precedenta egala atunci ei se evalueaza de la stanga la dreapta.
1. Toti operatorii de comparatie si SQL au precedenta egala:
=,!=,<,>,<=,>=,BETWEEN...AND,IN,LIKE,IS NULL.
2. NOT(pentru a inversa rezultatul unei expresii logice.De ex: WHERE not(sal>2000))
3. AND
4. OR.
De fiecare data cand sunteti in dubiu despre care dintre doua operatii vor fi executate mai
intai cand o expresie este evaluata, sunteti liberi sa utilizati parantezele pentru a clarifica
semnificatia dorita si pentru a va asigura ca SQL*Plus face ceea ce doriti.
Sa presupunem ca doriti sa gasiti toti managerii, din orice departament,si toti functionarii din
departamentul 10:
SELECT *
FROM
EMP
WHERE JOB='MANAGER' OR (JOB = 'CLERK' AND DEPTNO = 10);

31

Parantezele de deasupra sunt necesare, AND are o precedenta mai mare decat OR ,dar ele
clarifica semnificatia expresiei.

SELECT-Sumar
Urmatoarele clauze sunt inchise in comanda SELECT:
SELECT
FROM
WHERE
ORDER BY

[DISTINCT] [*,coloana alias],...]


tabela
conditie(ii)
[coloana,expr] [ASC/DESC];

SELECT
selecteaza cel putin o coloana
Alias
poate fi folosit pentru coloanele din lista selectata
*
desemneza toate coloanele
DISTINCT
poate fi utilizat pentru eliminarea duplicatelor
FROM Tabela
desemneaza tabela din care provin coloanele
WHERE
restrictioneaza cererea la randurile care indeplinesc o conditie.Poate contine valori de
coloane,expresii si literali
AND/OR
poate fi utilizat intr-o clauza WHERE pentru a construi conditii mai complexe. AND
are prioritate peste OR.
()
pot fi utilizate pentru a forta prioritatea
ORDER BY
intotdeauna apare la sfarsit .Specifica ordinea de sortare.Una sau mai multe coloane
pot fi specificate aici.
ASC
ordinea ascendenta este ordinea de sortar ( implicita) si nu trebuie specificat.
DESC
inverseaza ordinea de sortare de default si trebuie specificat dupa un nume de coloana.
Clauzele pot fi introduse pe linii separate in buffer si tabelarea este utilizata pentru claritate si
in editare.

Logarea la SQL*Plus
Aceasta sectiune explica cum sa ne logam la SQL*Plus si liniile de iesire ale tipurilor de
comenzi ce pot rezulta in cadrul sau.

32

SQL*Plus
SQL*Plus este un program scris de Corporatia Oracle,ce produce un mediu pentru comenzile
SQL ce pot fi tastate direct sau rulate dintr-un fisier de comanda.In plus ,comenzile SQL pot
fi derivate.Ele sunt folosite pentru:

formatarea rezultatelor
setarea optiunilor
editarea si stocarea declaratiilor SQL

Odata ce v-ati logat la sistemul vostru de operare,sunt 3 moduri pentru a va loga la


SQL*Plus:
1. SQLPLUS
o Veti vedea dupa aceasta un mesaj ca acesta:
o SQL*Plus: Version 3.1.1 Production on Mon Oct 4 1993 Copyright (c)
1992,Oracle Corporation,California,USA. All rights reserved. Enter
Username:
o Introduceti numele vostru de user si apasati RETURN: SQL*Plus va afisa
promptul :"Enter Password:". Introduceti parola voastra si apasati din nou
RETURN.
o Pentru protectia voastra ,parola nu va apare pe ecran. SQL*Plus va afisa
promptul sau: SQL>
o Aceasta indica linia de comanda .Acolo sunt doua feluri de comenzi si puteti
introduce pe acesta linie de comanda:comenzi SQL sau comenzi SQL*Plus.
2. SQLPLUS username
o Veti fi indemnati sa va dati parola.
3. SQLPLUS username/password
o Veti fi logati la SQL*Plus.In acest caz parolz v a fi afisata.
Alegeti metoda pe care o preferati.

Editarea declaratiilor SQL utilizand comenzi SQL*Plus


1. Cand veti introduce o comanda SQL,aceasta este stocata intr-o zona de memorie
utilizata de buferul SQL si ramane acolo pana ce veti introduce o noua comanda.
2. Daca apasati [RETURN] inainte de a completa o comanda,SQL*Plus va afisa un
numar de linie.
3. Terminatorul pentru declaratiile SQL este un ';'.
4. Cat timp declaratia SQL este in bufer,sunt cateva operatii de editare directe care pot fi
executate utilizand comenzi SQL*Plus:

Comanda
Abrevierea
ROL
---------------------------------------------------------------------APPEND text
A text
adauga 'text' la sfarsitul liniei curente.
CHANGE
C/old/new
schimba vechiul text cu noul text in linia
curenta.

33

CHANGE
CLEAR BUFFER
DEL
INPUT
INPUT

C/text/
CL BUFF
I
I text

sterge 'text'-ul din linia curenta


sterge toate liniile din buferul SQL.
sterge linia curenta.
insereaza un numar nedefinit de linii.
insereaza o linie constituita din 'text'-

LIST
LIST n
LIST m, n
RUN

L
Ln
L m n
R

respectiv
listeaza toate liniile din buferul SQL.
listeaza o linie (specificata de n)
listeaza un numar de linii(de la m la n).
afiseaza si executa comanda SQL curenta

ul

din
buffer.
executa

comanda

SQL care

este curenta

in
bufer.

Diversitatea comenzilor SQL*Plus


Comenzile SQL (precum SELECT) sunt mijloace de acces la date prin kernelul
Oracle.Comenzile SQL sunt utilizate in special pentru controlul mediului, formatarea
rezultatelor interogarilor si controlul fisierelor.Comenzile identificate aici sunt amestecate si
trebuie sa le folositi in urmatoarele exercitii.
Comenzile SQL sunt introduse la promptul SQL> pe o linie ,ele nu vor deschide un buffer.
Comanda + Descriere
SAVE numefis
permite salvarea intr-un fisier a continutului buferului SQL.
GET numefis
incarca continutul unui fisier salvat in prealabil in buffer.
START numefis
ruleaza un fisier de comanda salvat in prealabil. Fisierele de comanda sunt tratate in
capitolul 10.
ED numefis
utilizeaza un editor de default pentru a edita continutul unui fisier salvat.
EXIT
paraseste SQL*Plus.

Capitolul 2 Exercitii-Introducere in SQL


Aceste exercitii intentioneaza sa dezvaluie toate subiectele neobservate la o lectura
anterioara.Daca aveti timp incercati intrebarea 13.
Workshop
1.

Selectati toate informatiile din tabela SALGRADE.


GRADE
-----

LOSAL
-----

HISAL
-----

34

1
2
3
4
5

2.
EMPNO
----7369
7499
7521
7566
7654
7698
7782
7788
7839
7844
7876
7900
7902
7934

700
1201
1401
2001
3001

1200
1400
2000
3000
9999

Selectati toate informatiile din tabela EMP.


ENAME
----SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER

JOB
------CLERK
SALESMAN
SALESMAN
MANAGER
SALESMAN
MANAGER
MANAGER
ANALYST
PRESIDENT
SALESMAN
CLERK
CLERK
ANALYST
CLERK

MGR
---7902
7698
7698
7839
7698
7839
7839
7566
7698
7788
7698
7566
7782

HIREDATE
-------13-JUN-83
15-AUG-83
26-MAR-84
31-OCT-83
05-DEC-83
11-JUL-84
14-MAY-84
05-MAR-84
09-JUL-84
04-JUN-84
04-JUN-84
23-JUL-84
05-DEC-83
21-NOV-83

SAL
COMM DEPTNO
-------- ------- -----800.00
20
1,600.00
300.00
30
1,250.00
500.00
30
2,975.00
20
1,250.00 1,400.00
30
2,850.00
30
2,450.00
10
3,000.00
20
5,000.00
10
1,500.00
.00
30
1,100.00
20
950.00
30
3,000.00
20
1,300.00
10

14 inregistrari selectate.
3.

Listati toti angajatii care au salariul intre 1000 si 2000.

ENAME DEPTNO
----- -----ALLEN
30
WARD
30
MARTIN
30
TURNER
30
ADAMS
20
MILLER
10

SAL
-------1,600.00
1,250.00
1,250.00
1,500.00
1,100.00
1,300.00
6 inregistrari selectate.

4.Listati numerele de departament si numele in ordinea numelor


departamentelor.
DEPTNO
-----10
40
20
30
5.

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

Afisati toate tipurile diferite de job-uri.

JOB
--------ANALYST
CLERK
MANAGER
PRESIDENT
SALESMAN
6.

Listati detaliile angajatilor din departamentele 10 si 20 in

35

ordinea alfabetica a numelui.


EMPNO
----7876
7782
7902
7566
7839
7934
7788
7369

ENAME
----ADAMS
CLARK
FORD
JONES
KING
MILLER
SCOTT
SMITH

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

MGR
---7788
7839
7566
7839

HIREDATE
--------04-JUN-84
14-MAY-84
05-DEC-83
31-OCT-83
09-JUL-84
7782 21-NOV-83
7566 05-MAR-84
7902 13-JUN-83

SAL
-------1,100.00
2,450.00
3,000.00
2,975.00
5,000.00
1,300.00
3,000.00
800.00

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

8 inregistrari selectate.
7.Listati numele si ocupatiile tuturor functionarilor
in departamentul 20.
ENAME
-----SMITH
ADAMS
8.

JOB
----CLERK
CLERK

Afisati toti angajatii ai caror nume contine TH sau LL


in interior.

ENAME
-----SMITH
ALLEN
MILLER
9.

Listati urmatoarele detalii pentru toti angajatii care


au un manager.

ENAME
-----SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
TURNER
ADAMS
JAMES
FORD
MILLER

JOB
-------CLERK
SALESMAN
SALESMAN
MANAGER
SALESMAN
MANAGER
MANAGER
ANALYST
SALESMAN
CLERK
CLERK
ANALYST
CLERK

SAY
-------800.00
1,600.00
1,250.00
2,975.00
1,250.00
2,850.00
2,450.00
3,000.00
1,500.00
1,100.00
950.00
3,000.00
1,300.00
13 inregistrari selectate.

10.

Afiseaza numele si totalul remuneratiei pentru toti angajatii.

ENAME
REMUNERATION
------- -----------SMITH
9600
ALLEN
19500
WARD
15500
JONES
35700

36

MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER

16400
34200
29400
36000
60000
18000
13200
11400
36000
15600

14 inregistari selectate.
11.

Afiseaza toti salariatii care au fost angajati in anul 1983.

ENAME
------SMITH
ALLEN
JONES
MARTIN
FORD
MILLER

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

HIREDATE
--------13-JUN-83
15-AUG-83
31-OCT-83
05-DEC-83
05-DEC-83
21-NOV-830
6 inregistrari selectate.

12. Afisati numele,salariul anual si comisionul pentru toti vanzatorii


ai caror salariu lunar este mai mare decat comisionul lor.Iesirea va
fi
ordonata

dupa salariu , cele m ai mari primele. Daca doi sau mai

multi
angajati au acelasi salariu trebuie

sortati dupa nume in odinea

celor
mai mari salarii.
ENAME
-----ALLEN
TURNER
WARD

ANNUAL_SAL
COMM
---------- -------19200
300.00
18000
.00
15000
500.00

Incercati-va aptitudinile cu acesta.


13.

Selectati informatiile dupa cum sunt selectate.

Cine,cand si cum
-------------------------------------------------------------------SMITH HAS HELD THE POSITION OF CLERK
IN DEPT 20 SINCE 13-JUN-83
ALLEN HAS HELD THE POSITION OF SALESMAN IN DEPT 30 SINCE 15-AUG-83
WARD
HAS HELD THE POSITION OF SALESMAN IN DEPT 30 SINCE 26-MAR-84
JONES HAS HELD THE POSITION OF MANAGER
IN DEPT 20 SINCE 31-OCT-83
MARTIN HAS HELD THE POSITION OF SALESMAN IN DEPT 30 SINCE 05-DEC-83
BLAKE HAS HELD THE POSITION OF MANAGER
IN DEPT 30 SINCE 11-JUN-84
CLARK HAS HELD THE POSITION OF MANAGER
IN DEPT 10 SINCE 14-MAY-84
SCOTT HAS HELD THE POSITION OF ANALYST
IN DEPT 20 SINCE 05-MAR-84
KING
HAS HELD THE POSITION OF PRESIDENT IN DEPT 10 SINCE 09-JUL-84
TURNER HAS HELD THE POSITION OF SALESMAN IN DEPT 30 SINCE 04-JUN-84
ADAMS HAS HELD THE POSITION OF CLERK
IN DEPT 20 SINCE 04-JUN-84
JAMES HAS HELD THE POSITION OF CLERK
IN DEPT 30 SINCE 23-JUL-84
FORD
HAS HELD THE POSITION OF ANALYST
IN DEPT 20 SINCE 05-DEC-83
MILLER HAS HELD THE POSITION OF CLERK
IN DEPT 10 SINCE 21-NOV-83

37

14 inregistrari selectate.

Capitolul 2 - Rezolvari
1.

SELECT
FROM

*
SALGRADE;

2.

SELECT
FROM

*
EMP;

3.

SELECT
FROM
WHERE

ENAME, DEPTNO, SAL


EMP
SAl BETWEEN 1000 AND 2000;

4.

SELECT
FROM
ORDER BY

DEPTNO, DNAME
DEPT
DNAME;

5.

SELECT
FROM

DISTINCT JOB
EMP;

6.

SELECT
FROM
WHERE
ORDER BY

*
EMP
DEPTNO IN (10,20)
ENAME;

7.

SELECT
FROM
WHERE
AND

ENAME,JOB
EMP
JOB = 'CLERK'
DEPTNO = 20;

8.

SELECT
FROM
WHERE
OR

ENAME
EMP
ENAME LIKE '%TH%'
ENAME LIKE '%LL%';

9.

SELECT
FROM
WHERE

ENAME, JOB, SAL


EMP
MGR IS NOT NULL;

10.

SELECT
FROM

ENAME, SAL*12+NVL(COMM,0) REMUNERATION


EMP;

11.

SELECT
FROM
WHERE

ENAME, DEPTNO, HIREDATE


EMP
HIREDATE LIKE '%83';

12.

SELECT
FROM
WHERE
AND JOB
ORDER BY

ENAME, SAL*12 ANNUAL SAL, COMM


EMP
SAL >COMM
= 'SALESMAN'
SAL DESC, ENAME;

13.

SELECT

ENAME||
' HAS HELD THE POSITION OF '||
JOB||
' IN DEPT '||

38

FROM

DEPTNO||
' SINCE '||
HIREDATE "Who, what and when"
EMP;

39

CAPITO LUL3
Rularea cererilor standard cu variabile substituite.
In acest capitol sunt descrise variabilele substituite.Variabilele substituite sunt folosite in
declaratiile SQL si permite utilizarea valorilor specificate la rulare.

Variabile in SQL *Plus


In plus fata de variabilele pe care le vom vedea in limbajul PL/SQL, SQL*Plus este inzestrat
cu doua tipuri de variabile ale sale:
Variabile legate
Utilizate pentru stocarea valorilor individuale ce pot fi asignate si citite in timpul
rularii(vor fi discutate mai tarziu in acest curs).
Variabile substituite
Utilizate pentru stocarea partilor de text de comanda ,care sunt "editate" in comenzi
inainte de executia lor.

Variabile substituite cu un singur ampersand.


Puteti utiliza 'variabile substituite' intr-un fisier de comanda sau intr-o declaratie SQL pentru
a reprezenta valori ce vor fi aflate la executie.
O variabila poate fi vazuta ca un container in care valoarea este stocata temporar.
O variabila substituita este prefixata de un singur ampersand(&) si o valoare care ii este
asignata.
Urmatoarea declaratie obliga utilizatorul sa dea un numar de departament la executie:

SELECT
FROM
WHERE

EMPNO,ENAME,SAL
EMP
DEPTNO = &DEPARTAMENT_NUMBER;

Enter value for department_number:


EMPNO
----7782
7839
7934

10

ENAME
SAL
--------- ----------CLARK
2,450.00
KING
5,000.00
MILLER
1,300.00

Exemplul anterior utilizeaza conditia WHERE DEPTNO=10.

40

Cu un singur ampersand utilizatorul este obligat sa dea o valoare de fiecare data cand
comanda este executata,deoarece variabila nu este definita si de fiacare data valoarea
introdusa nu este salvata .
O valoare de tip caracter sau data are nevoie sa fie inchisa in ghilimele simple cand sunt
introduse la cerere.Pentru a evita ghilimelele simple ce tre- buie sa fie introduse la executie
,puteti pune variabilele in ghilimele simple.
In urmatoarea declaratie ,variabila este pusa intre ghilimele simple, asa ca ghilimele nu mai
sunt necesare la introducerea valorii respective:

SELECT
FROM
WHERE

ENAME,DEPTNO,SAL*12
EMP
JOB = ' <JOB_TITLE';

Enter value for job_title:MANAGER


ENAME
----JONES
BLAKE
CLARK

DEPTNO
SAL*12
------ -------20
35700
30
34200
10
29400

Cat timp variabila este variabila 'nedefinita' ,valoarea va fi ceruta de fiecare data cand
declaratia este executata.
Este posibil sa fie cerut numele unei coloane sau chiar numele unei tabele in timpul executiei.
In urmatorul exemplu vi se cere o expresie aritmetica:

SELECT
FROM

DEPTNO, <ARITHMETIC_EXPRESION
EMP;

Enter value for arithmetic_expression:sal/12


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

SAL/12
------66.6667
133.333
104.167
247.917
104.167
237.5
204.167
250
416.667
125
91.6667
79.1667
250
108.333

41

Variabile substituite cu dublu ampersand.


Daca variabila este prefixata de dublu ampersand(&&),SQL*Plus va cere valoarea pentru
variabila doar o singura data .SQL*Plus stocheaza prima valoare furnizata si o foloseste din
nou de fiecare data cand declaratia SQL este rulata
SELECT
FROM
WHERE

ENAME,DEPTNO,JOB
EMP
DEPTNO = &&DEPTNO_PLEASE;

Enter value for deptno_please: 10


ENAME
----CLARK
KING
MILLER

DEPTNO
-----10
10
10

JOB
-------MANAGER
PRESIDENT
CLERK

Puteti folosi comanda SQL*Plus DEFINE pentru a determina daca variabila este deja
definita.Daca variabila este deja definita se afiseaza valoarea asignata.

SQL> DEFINE
DEFINE DEPTNO_PLEASE = "10" (CHAR)

Comanda DEFINE este de asemenea folosita pentru a crea o variabila utilizator.

Substitutia datelor ca o comanda text


Cand informatia dintr-o comanda substituita este introdusa intr-o comanda inaintea executiei sale,variabila poate fi folosita pentru a inzestra
orice parte a structurii comenzii exceptand numele insusi al comenzii.De
exemplu:
SELECT
WHERE

* FROM
&CONDITION

SALGRADE

Enter value for CONDITION: losal>2000

Variabila CONDITION ,de mai sus,trece intreaga conditie a clauzei WHERE


intr-o comanda.Mai departe intregul cod al comenzii(incepand cu cuvantul
SELECT) poate fi trecut intr-o variabila.

42

SELECT

&THE_REST;

Comanda DEFINE

O valoare poate fi asignata unei variabile folosind comanda DEF[INE] a lui


SQL*PLUS.Valoarea definita trebuie referita intr-o construc- tie SELECT
sau un fisier de comenzi , prefixind numele variabilei cu &. Variabilele pot fi
golite folosind UNDEF[INE].
In urmatorul exemplu , o variabila a fost definita folosind o expresie
aritmetica ce calculeaza remuneratia. In urmatoarele constructii, variabila
REM e referita de un numar de ori. Variabila e apoi golita fo- losind
UNDEFINE.

SQL> DEFINE
SQL>SELECT
SQL>FROM
SQL>ORDER BY

REM ='SAL*12+NVL(COMM,0)'
ENAME, JOB, <REM
EMP
<REM;

SQL >undefine

REM

ENAME
JOB
SAL*12+NUL(COMM,0)
-----------------------------------------------SMITH
CLERK
9600
JAMES
CLERK
11400
ADAMS
CLERK
13200
WARD
SALESMAN
15500
MILLER
CLERK
15600
MARTIN
SALESMAN
16400
TURNER
SALESMAN
18000
ALLEN
SALESMAN
19500
CLARK
MANAGER
29400
BLAKE
MANAGER
34200
JONES
MANAGER
35700
SCOTT
ANALYST
36000
FORD
ANALYST
36000
KING
PRESIDENT
60000

'' de la expresii sunt optionale , daca expresia nu contine spatii. Ghilimelele


pot fi deasemenea folosite si sunt optionale dar folositoare daca expresia
contine blancuri sau apostrofi.
Pornirea unui fisier cu comenzi care contine substitutii de variabile
Presupunind ca doriti o serie de rapoarte care sa listeze angajatii cu functii
diferite - de exemplu , una pentru SALESMEN , una pentru CLERKS, una

43

pentru MANAGERS si tot asa.Cunoasteti cum sa folositi substitutia de


variabile pentru a obtine aceste rapoarte dintr-o singura constructie
SELECT.
Cu toate acestea , exista o tehnica alternativa pe care s-o folositi si anume sa
scrieti constructia SELECT intr-un fisier si apoi folosind comanda START sal executati.
Aceasta tehnica impune folosirea unor substitutii speciale de variabile. Exista
9 asemenea variabile si ele au intregii de la 1 la 9 ca nume. Pentru folosirea
acestor variabile , puneti un '&' urmat de un intreg (1-9) in comanda
SQL.Aceste variabile pot fi folosite de ori de cite ori doriti si in orice ordine .
De fiecare data cind comanda e rulata, fiecare '&1' din comanda e inlocuit de
primul parametru dupa START fisier, fiecare '&2' e inlo- cuit de al doilea
parametru s.a.m.d.
Pentru a crea un fisier de comenzi care ia un parametru specificind functia
care trebuie afisata , introduceti:

SELECT EMPNO,ENAME,SAL
FROM EMP
WHERE JOB = ' <1' ;
SQL>SAVE JOB1
SQL*PLUS

intoarce mesajul:

Created file job1


Apoi rulati comanda cu parametrul 'CLERK'.
SQL*PLUS inlocuieste variabila cu valoarea parametrului.
SQL>

START JOB1

EMPNO
----7369
7876
7900

ENAME
----SMITH
ADAMS
JAMES

CLERK
SAL
--800
1100
950

Observati ca nu se pot folosi variabile cind executati o comanda cu RUN.


Trebuie sa introduceti comanda in fisier si sa o rulati cu START comanda.
Comanda ACCEPT
Comanda ACCEPT permite unei variabile sa fie create si unei valori , care e introdusa sa fie
memorata in ea. Aceasta variabila poate fi apoi referita in constructia SQL. ACCEPT este
folosita deseori intr-un fisier de comenzi . Sunt citeva avantaje rezultate din folosirea lui
ACCEPT pentru definirea substitutiei de variabile:
44

Tipurile de date pot fi verificate


Prompturile pot fi mai explicative
Valorile de raspuns pot fi ascunse

Sintaxa comenzii este:


ACC[EPT] variabila [ NUMBER/CHAR]

[PROMPT/NOPROMPT 'text'][HIDE]

Sintaxa + Descrierea
NUMBER/CHAR
determina tipul variabilei.Daca valoarea introdusa este nevalida , va fi afisat un mesaj.
PROMPT 'text'
afiseaza daca text e specificat
NOPROMPT
face ACCEPT sa sara o linie asteptind intrarea
HIDE
suprima raspunsul utilizatorului. folositor pentru parole

Exemple

SQL> ACCEPT SALARY NUMBER PROMPT 'Salary figure :'


Salary figure : 30000
SQL>ACCEPT PASSWORD CHAR PROMPT 'Password :' HIDE
Password :
SQL>ACCEPT COMM NUMBER NOPROMPT
500
SQL>DEFINE
DEFINE SALARY
=30000(NUMBER)
DEFINE PASSWORD ="FREEBIES(CHAR)
DEFINE COMM
=500(NUMBER)

Rezumat
Cind SQL*Plus intilneste &variabila:
1. Daca &variabila este deja definita, definitia deja existenta e folosita.
2. Daca & variabila nu e definita:
o Utilizatorul e gata pentru definitie
o Definitia furnizata de utilizator e apoi folosita
o Definitia furnizata de utilizator e apoi pierduta
Cind SQL Plus intilneste &&variabila :

45

La fel ca pasii 1 si 2 de deasupra cu exceptia faptului ca valoarea variabilei e salvata.


Observatie: &1 parametru e tratat ca &&.
Pentru a afla daca o variabila e deja definita, folositi comanda
DEF[INE]:
DEF DEPARTAMENT
daca e definit, da definitia lui DEPARTAMENT daca nu specifica 'nedefinit'
Pentru a defini o variabila , se poate folosi deasemenea comanda
DEF[INE].
DEF COMM =
Ghilimelele nu sunt necesare , dar ajuta daca "NVL (COMM,0)" expresia contine
blancuri imbricate sau apostrofi.
Cit timp ramin variabilele definite? Pina cind le UNDEF[ine] sau le redefinim sau pina iesim
din SQL*PLUS.
Alte 2 modalitati de definire a unei variabile:
SQL>ACCEPT variabila [tip] [PROMPT text][HIDE]
SQL>COL[UMN] nume coloana /alias NEW_VALUE variabila (tratata in
capitolul 11)

Cap.3 Exercitii -Rulind cereri cu parametrii.


Acest exercitiu va ofera oportunitatea sa creati fisiere care pot fi rulate interactiv , si care
folosesc substitutii de variabile pentru crearea unor criterii de selectie.

TEME
1. Generati o constructie prin care sa afisati angajatii cu date de
angajare intre 2 date date. Rulati de 2 ori cererea.
Modificati cererea pentru a folosi &&variabila .Rulati-o de
citeva
ori. Observati diferenta.
2. Obtineti o cerere care sa accepte o functie data. Pentru
testare executati cererea de citeva ori.
ENAME
JOB
SAL
MGR DEPTINO
---------------------------------------------SCOTT
ANALYST
3,000.00 7566
20
FORD
ANALYST
3,000.00 7566
20
3. Definiti o variabila reprezentind expresia folosita pentru
calculul remuneratiei anuale a angajatilor.Folositi variabile
intr-o constructie
care gaseste toti angajatii care cistiga
30.000 $ pe an sau mai mult.

46

ENAME
SAL*12+NUL(COMM,0)
---------------------------------JONES
35700
BLAKE
34200
SCOTT
36000
KING
60000
FORD
36000

Cap.3 Solutii
1.

SELECT
FROM
WHERE

ENAME,HIREDATE
EMP
HIREDATE BETWEEN'&FIRST_DATE'AND'&LAST_DATE';

2.

SELECT
FROM
WHERE

ENAME,JOB,SAL,MGR,DEPTNO
EMP
JOB ='&JOB';

3.

SELECT
FROM
WHERE

ENAME,&REM
EMP
&REM >30000;

47

CAPITO LUL4
FUNCTII
In acest capitol, sunt introduse functiile.Functiile fac ca cererile de baza sa devina mai
puternice si sint folosite pentru manipularea valorilor.Acest capitol acopera functiile
numerice si pe caracter. Functiile de conversie si care opereaza pe tipuri de date sunt tratate
in cap.5. In final functiile de grup sunt tratate in cap.6.

INTRODUCERE
Functiile sint folosite pentru manipularea datelor.Ele accepta unul sau mai multe argumente
si intorc o valoare.Un argument este o constanta , variabila sau o referire de coloana.Formatul
pentru functie este urmatorul: function_name(arg1,arg2,...)
Functiile pot fi folosite pentru:

a calcula
a modifica datele individuale
a manipula iesirea pentru grupuri de siruri
a schimba formatul datelor pentru afisare
a converti tipurile de date

Exista diferite tipuri de functii:

CHARACTER
NUMBER
DATE
CONVERSION
FUNCTION THAT ACCEPT ANY DATA TYPE AS INPUT
GROUP

Unele functii opereaza pe un singur sir , altele pe grupuri de siruri.


Cele mai folosite functii sunt prezentate in acest manual. Puteti recurge la SQL*Plus
REFERENCE GUIDE pentru lista completa a functiilor.
Functiile care se aplica unui singur sir vor fi discutate in capitolul prezent si in cap.5.Functiile
de grup vor fi tratate in cap.6.
Functii care se aplica unui singur sir.

actioneaza asupra fiecarui sir returnat din cerere


intoarce un rezultat pentru fiecare sir
asteapta unul sau mai multe argumente
pot fi imbricate
pot fi folosite acolo unde se folosesc variabile , coloane sau expresii , de exemplu , in
constructiile :SELECT,WHERE,ORDER BY.

48

Explicatia notatiei:
Notatie + Semnificatie:
col
un nume de coloana dintr-o baza de date
value(valoare)
orice valoare literale(caracter/data/numar)
n
reprezinta un sir
'string'
reprezinta caracterul string
chars
reprezinta un numar de caractere specificate
date
reprezinta o coloana date sau o valoare date

Functii numerice si pe caracter


Acestea accepta la intrare un caracter si poate returna si caracter si valoare numerica.
Urmatoarele functii prezentate sunt:
LOWER(col/value)
forteaza caracterele alfa care sunt scrise cu litere mari sau mixte in caractere scrise cu
litere mici.
Pentru a afisa cu litere mici numele departamentului ca si sirul ' SQL COURSE' introduceti:
SELECT LOWER (DNAME),LOWER('SQL course')
FROM DEPT;
LOWER(DNAME)
LOWER(SQL COURSE)
-----------------------------------research
sql course
sales
sql course
operations
sql course
accounting
sql course

UPPER(col/value)
forteaza caracterele alfa care sunt scrise cu litere mici , sau o combinatie de litere mici
si mari in caractere scrise cu litere mari.
In urmatorul exemplu , functia UPPER e folosita pentru a forta intrarea utilizatorului la litere
mari.
SELECT ENAME
FROM EMP
WHERE ENAME =UPPER('&ENAME');

49

Enter value for ename :smith


ENAME
----SMITH

INITCAP(col/value)
forteaza prima litera a fiecarui cuvint in litera mare
Pentru afisarea numelor departamentelor si locatiile , introduceti:
SELECT
FROM

INITCAP(DNAME),
DEPT;

INITCAP(LOC)

INITCAP(DNAME) INITCAP(LOC)
---------------------------Accounting
New York
Research
Dallas
Sales
Chicago
Operations
Boston

CONCAT(char 1,char2)
intoarce char1 concatenat cu char2 (Alternativa a operatorului ||)
SELECT CONCAT (ename,job) "JOB"
FROM EMP
WHERE EMPNO =7900;
JOB
----------JAMESCLERK

Functiile LPAD si RPAD aduc sirurile de caractere la o lungime specificata.


LPAD(col/value,n,'string')
adauga la coloana sau la valoarea literala spre stinga pina la lungimea totala n.
Primele spatii sunt umplute cu 'string'. Daca 'string' e omis atunci sunt umplute cu
blancuri.
SELECT LPAD(DNAME,20,'*'),LPAD(DNAME,20),LPAD(DEPTNO,20,'.')
FROM DEPT;
LPAD(DNAME,20,'*') LPAD(DNAME,20)
LPAD(DEPTNO,20,'.')
-----------------------------------------------------------************RESEARCH
RESEARCH.....................20
***************SALES
SALES.....................30
**********OPERATIONS
OPERATIONS.....................40
**********ACCOUNTING
ACCOUNTING.....................10

50

Observati ca a doua coloana e completata in stinga cu spatii, implicit , si ca a treia coloana


este de tipul numar.
RPAD(col/value,n,'string')
adauga la coloana sau la valoarea literala spre dreapta pina la lungimea totala n.
Ultimele pozitii sunt umplute cu 'string' sau daca acesta e omis cu blancuri.
SELECT RPAD(DNAME,20,'*'),RPAD(DNAME,20),RPAD(DEPTNO,20,'.')
FROM DEPT;
RPAD (DNAME,20,'*') RPAD(DNAME,20)
RPAD(DEPTNO,20,'.')
-----------------------------------------------------------RESEARCH************ RESEARCH
20..................
SALES*************** SALES
30..................
OPERATIONS********** OPERATIONS
40..................
ACCOUNTING********** ACCOUNTING
10..................

In acest caz a doua coloana are in dreapta blancuri puse implicit.


Urmatoarele functii presupun ca caracterele din string sunt numerotate de la stinga la dreapta
, incepind cu 1.
SUBSTR(col/value,pos,n)
intoarce un string de n caractere lungime dintr-o coloana sau valoare literala ,
incepind de la pozitia pos. Daca n e omis, e extras sirul din pozitia pos la sfirsit.
Urmatorul exemplu afiseaza urmatoarele "substringuri":

4 caractere din literalul 'ORACLE' incepind de la al doilea caracter


continutul lui DNAME incepind cu al doilea caracter
5 caractere din DNAME incepind cu al treilea caracter
SELECT SUBSTR('ORACLE',2,4),SUBSTR(DNAME,2),
SUBSTR(DNAME,3,5)
FROM DEPT;

SUBSTR('ORACLE',2,4) SUBSTR(DNAME,2) SUBSTR(DNAME,3,5)


--------------------------------------------------------RACL
ESEARCH
SEARC
RACL
ALES
LES
RACL
PERATIONS
ERATI
RACL
CCOUNTING
COUNT

Observati ca valorile sint aliniate la stinga.Aceasta deoarece SQL*Plus intotdeauna afiseaza


de la stinga, implicit.
INSTR(col/value,'string')
gaseste pozitia caracterului in care apare prima data 'string'.
INSTR(col/value,'string',pos,n)

51

gaseste pozitia caracterului pentru a n-a aparitie a lui string in coloana sau valoarea
literala incepind din pozitia pos.
SELECT DNAME,INSTR(DNAME,'A'),
INSTR(DNAME,'ES'),INSTR(DNAME,'C',1,2)
FROM DEPT;
DNAME
INSTR(DNAME,'A') INSTR(DNAME,'ES')
INSTR(DNAME,'C',1,2)
-------------------------------------------------------------------ACCOUNTING
1
0
3
RESEARCH
5
2
0
SALES
2
4
0
OPERATIONS
5
0
0

O folosire obisnuita a lui INSTR este de a determina daca inceputul utilizatorului contine un
caracter particular sau mai multe. In exemplul anterior , de exemplu, expresia
INSTR(DNAME,'ES') e 0 pentru ACCOUNTING deoarece acesta nu contine sirul dat.
LTRIM si RTRIM sterg caracterele specificate din sir.
LTRIM (col/value,'char/s')
sterge de la stinga prima aparitie a caracterului specificat(sau o combinatie a
caracterelor specificate). Daca nu e specificat nici un caracter sterge toate blancurile
din stinga.
SELECT DNAME,LTRIM(DNAME,'A'),LTRIM(DNAME,'AS'),
LTRIM(DNAME,'ASOP')
FROM DEPT;
DNAME
LTRIM(DNAME,'A') LTRIM(DNAME,'AS') LTRIM(DNAME,'ASOP')
------------------------------------------------------------------RESEARCH
RESEARCH
RESEARCH
RESEARCH
SALES
SALES
LES
LES
OPERATIONS
OPERATIONS
OPERATIONS
ERATIONS
ACCOUNTING
CCOUNTING
CCOUNTING
CCOUTING

RTRIM (col/value,'char/s')
sterge de la dreapta, aparitiile lui char (sau combinatie de caractere spe- cificate)
.Daca nu e specificat 'char/s' atunci sterge blancurile.
SELECT DNAME, RTRIM(DNAME,'G'),RTRIM(DNAME,'GHS')
RTRIM(DNAME,'N')
FROM DEPT;
DNAME
RTRIM(DNAME,'G') RTRIM(DNAME,'GHS') RTRIM(DNAME,'N')
--------------------------------------------------------------RESEARCH RESEARCH
RESEARC
RESEARCH
SALES
SALES
SALE
SALES
OPERATIONS OPERATIONS
OPERATION
OPERATIONS
ACCOUNTING ACCOUNTIN
ACCOUNTIN
ACCOUNTING

52

RTRIM poate fi in mod particular folositor in a sterge blancurile de la sfirsit la coloane.De


exemplu , presupunind ca in transferul datelor la tabela 'emp' blancurile au fost adaugate
neintentionat dupa fiecare ENAME.Urmatoarea comanda va sterge toate blancurile finale:
UPDATE EMP
SET ENAME =RTRIM(ENAME);
Observatie: comanda

UPDATE e tratata

complet mai tirziu.

SOUNDEX(col/value)
intoarce un sir de caractere reprezentind pronuntia(sunetul) cuvintului pentru fiecare
coloana sau valoare literala.Aceasta functie intoarce o reprezentare fonetica a fiecarui
cuvint si ne permite sa comparam cuvinte care sunt scrise diferit, dar se
pronunta(suna) la fel.
SELECT
FROM
WHERE

ENAME, SOUNDEX(ENAME)
EMP
SOUNDEX(ENAME) = SOUNDEX('FRED');

ENAME
SOUNDEX(ENAME)
----------------------------FORD
F630

LENGTH(col/value)
intoarce numarul de caractere(sau digiti) din coloana sau din valoarea literala.
SELECT LENGTH('SQL COURSE'),LENGTH(DEPTNO),LENGTH(DNAME)
FROM DEPT;
LENGTH('SQLCOURSE') LENGTH(DEPTNO) LENGTH(DNAME)
------------------------------------------------10
2
8
10
2
5
10
2
10
10
2
10

Observati ca LENGTH la fel ca si functia INSTR intoarce o valoare numerica.


Functiile TRANSLATE si REPLACE sunt folosite pentru substitutia caracterelor.
TRANSLATE(col/value,from,to) translateaza la iesire caracterele 'from' la cele 'to'.Mai mult
de un caracter , se poate potrivi. Toate operatiile lui 'from' sunt inlocuite de corespondentul
din 'to'. Daca caracterul corespunzator din 'to'nu e rezervat , caracterul din 'from'e sters(vezi
functiile imbricate).
SELECT ,ENAME,TRANSLATE(ENAME,'C','P'),JOB
TRANSLATE(JOB,'AR','IT')

53

FROM EMP
WHERE DEPTNO=10;
ENAME
TRANSLATE(ENAME,'C','P') JOB TRANSLATE(JOB,'AR','IT')
----------------------------------------------------------------CLARK
PLARK
MANAGER
MINIGET
KING
KING
PRESIDENT PTESIDENT
MILLER
MILLER
CLERK
CLETK

REPLACE(col/value,string,replacement_string)
intoarce col/value cu orice aparitie a 'string-ului', inlocuita cu replacement_string.Daca 'replacement_string' e omis, toate operatiile lui 'string'sunt
sterse.Daca sunt emise si 'string' si 'replacement_string'atunci se semnaleaza eroare.
SELECT JOB , REPLACE(JOB,'SALESMAN','SALESPERSON'),
ENAME ,REPLACE(ENAME,'CO','PX')
FROM
EMP;

JOB REPLACE(JOB,'SALESMAN','SALESPERSON') ENAME


REPLACE(ENAME,'CO','PX')
------------------------------------------------------------------ANALYST
ANALYST
SALESMAN
SALESMAN
MANAGER

SCOTT
SALESPERSON
SALESPERSON
MANAGER

SPXTT
TURNER
ALLEN
CLARK

TURNER
ALLEN
CLARK

Functia REPLACE suplimenteaza functionalitatea furnizata de functia


TRANSLATE.TRANSLATE furnizeaza caractere singulare , unul cite unul , pentru
substitutie.REPLACE va permite sa substituiti un sir cu altul ca si sa stergeti un sir (daca nu
specificati 'replacement _string'). Observati ca 'string' si 'replacement_string' pot fi de orice
lungime. REPLACE poate sa faca si conversia caracter la caracter REPLACE('C', IP).

FUNCTII IMBRICATE
Functiile singulare aplicate liniilor(sirurilor) pot fi imbricate la orice adincime.Daca functiile
sunt imbricate, ele sunt evaluate din interior spre exterior.
Sa presupunem ca vreti sa aflati nr. de ori in care un caracter apare intr-un sir.Cum veti
proceda? Puteti imbrica functiile LENGHT si TRANSLATE pentru a obtine rezultatul dorit.
Urmatorul exemplu va permite sa numarati de cite ori apare S intr-un sir.

SELECT DNAME,LENGTH(DNAME),LENGTH(DNAME)
LENGTH(TRANSLATE(DNAME,'AS,'A'))
FROM DEPT;
DNAME
LENGTH(DNAME)LENGTH(DNAME)-LENGTH(TRANSLATE(DNAME,'AS','A'))
--------------------------------------------------------------------------

54

RESEARCH
SALES
OPERATIONS
ACCOUNTING

8
5
10
10

1
2
1
0

Pasii pentru a obtine rezultatul sunt:


1. Folositi LENGTH pentru a identifica nr. de caractere din sir.
2. Apoi folositi TRANSLATE pentru a lua fiecare aparitie a lui S din sir.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.

SELECT
TRANSLATE(DNAME,'AS','A')
FROM DEPT;
TRANSLATE(DNAME,'AS',A')
-----------------------REEARCH
ALE
OPERATION
ACCOUNTING

15. Observati ca A e inlocuit cu A si S nu are un caracter corespunzator cu care sa fie


inlocuit . S e inlocuit cu nimic - e sters din sir. A serveste de plasare ?
16. Acum, scadeti din lungimea initiala a sirului pe cea din care am scos toate aparitiile
lui S. LENGTH(DNAME)-LENGTH(TRANSLATE(DNAME,'AS','A'))
17. Rezultatul e o valoare reprezentind nr. de aparitii ale lui S in sir.
O tehnica alternativa este de a folosi functia REPLACE.
1. Folositi REPLACE pentru a sterge fiecare aparitie a lui S din sir. Valoarea intoarsa va
reprezenta nr. de caractere care au ramas dupa ce S a fost sters. Cu alte cuvinte , o
valoare minus nr. de operatii ale lui S in sir.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.

SELECT DNAME, LENGTH(DNAME), LENGTH(REPLACE(DNAME,'S'))


FROM DEPT;
DNAME
LENGTH(DNAME)
ENGTH(REPLACE(DNAME,'S'))
---------------------------------------------------ACCOUTING
10
10
RESEARCH
8
7
SALES
5
3
OPERATIONS
10
9

13. Apoi scadeti din lungimea totala , lungimea sirului fara S.


14.
15.
16.
17.
18.
19.

SELECT DNAME,LENGTH(DNAME), LENGTH(DNAME)


LENGTH(REPLACE(DNAME,'S'))
FROM DEPT;

DNAME
LENGTH(DNAME) LENGTH(DNAME)LENGTH(REPLACE(DNAME,'S'))
20.
-----------------------------------------------------------------21.
ACCOUTING
10
0

55

22.

RESEARCH

SALES

1
23.
2
24.

OPERATIONS

10

1
25.

26. Rezultatul e o valoare care reprezinta nr. de operatii ale lui S in sir .

FUNCTII NUMERICE
Acestea accepta intrare numerica si intorc ca rezultat un numar. Aceasta sectiune descrie
citeva din functiile numerice. ROUND(col/value,n) rotujeste coloana , expresie sau valoare la
n zecimale. Daca n e omis nu are zecimale , daca e negativ , numarul din stinga punctului
zecimal e rotunjit.
SELECT

ROUND(45.923,1),
ROUND(45.923),
ROUND(45.323,1),
ROUND(42.323,-1),
ROUND(SAL/32,2)

FROM EMP
WHERE DEPTNO =10;

ROUND(45.923,1)ROUND(45.923)ROUND(45.323,1)Round(42.323,-1)ROUND(SAL/32,2)
-----------------------------------------------------------------------45.9
46
45.3
40
76.56
45.9
46
45.3
40
156.23
45.9
46
45.3
40
40.63
TRUNC(col/value,n)

trunchiaza

coloana sau valoarea la n zecimale,

sau
daca nu
e om is , fara zecimale.Daca n e negativ , numarul din
stinga
punctului zecimal e trunchiat la zero.
SELECT

TRUNC(45.923,1),
TRUNC(45.923),
TRUNC(45.323,1),
TRUNC(42.323,-1),
TRUNC(SAL/32,2)

FROM EMP
WHERE DEPTNO= 10;
TRUNC(45.923,1)TRUNC(45.923)TRUNC(45.323,1)TRUNC(42.323,1)TRUNC(SAL/32,2)
--------------------------------------------------------------------------45.9
45
45.3
40
76.56
45.9
45
45.3
40
156.25
45.9
45
45.3
40
40.62
CEIL (col/value) gaseste cel mai mic
coloana,
expresie sau valoare.

56

intreg

mai mare sau egal cu

SELECT
FROM
WHERE

CEIL(SAL),CEIL(99.9),CEIL(101.76),CEIL(-11.1)
EMP
SAL BETWEEN 3000 AND 5000;

CEIL(SAL)
CEIL(99.9) CEIL(101.26) CEIL(-11.1)
------------------------------------------------3000
100
102
-11
5000
100
102
-11
3000
100
102
-11
FLOOR (col/value) gaseste cel mai mare intreg mai mic sau egal
coloana expresie sau valoare.

cu

SELECT FLOOR(SAL), FLOOR(99.9),FLOOR(101.76),FLOOR(-11.1)


FROM EMP
WHERE
FLOOR(SAL) BETWEEN 3000 AND 5000;
FLOOR (SAL) FLOOR(99.9) FLOOR(101.76) FLOOR(-11.1)
----------------------------------------------------3000
99
101
-12
5000
99
101
-12
3000
99
101
-12
POWER(col/value,n) ridica coloana, expresia sau valoarea la
puterea n. Poate fi negativa.
SELECT
FROM
WHERE

SAL,POWER(SAL,2), POWER(SAL,3), POWER(50,5)


EMP
DEPTNO=10;

SAL POWER(SAL,2)
POWER(SAL,3) POWER(50,5)
---------------------------------------------2450.00
6002500
14706125000 312500000
5000.00 25000000
125000000000 312500000
1300.00
1690000
2197000000 312500000
EXP(n)

SELECT
FROM

intoarce e ridicat la puterea n


e=2.71828183.
EXP(4)
DUAL;

EXP(4)
-----54.59815
SQRT(col/value)

gaseste radacina patrata a coloanei


Daca col/value e NULL sau negativ
intors rezultatul NULL.

SELECT SAL, SQRT(SAL),SQRT(40), SQRT(COMM)


FROM EMP
WHERE COMM>0;
SAL
SQRT(SAL)
SQRT(40)
SQRT(COMM)
----------------------------------------------1600.00
40 6.32455532
17.3205081
1250.00
35.3553391 6.32455532
22.3606798
1250.00
35.3553391 6.32455532
37.4165739

57

sau valorii.
atunci e

SIGN(col/value)

intoarce -1 daca e coloana, expresie sau valoare e


un nr. negativ , intoarce 0 daca e zero,+1 daca e
nr.pozitiv.

SELECT SAL -COMM,SIGN(SAL-COMM),COMM-SAL, SIGN(COMM-SAL)


FROM EMP
WHERE DEPTNO=30;
SAL-COMM
SIGN(SAL-COMM)
COMM-SAL SIGN(COMM-SAL)
--------------------------------------------------1300
1
-1300
-1
750
1
-750
-1
- 150
-1
150
1
1500
1
-1500
-1
Frecvent , functia SIGN este folosita pentru a testa daca o valoare
este mai mica ca , mai mare ca sau egala cu a doua valoare.
Urmatorul exemplu tipareste toti
mai mare decit comisionul lor.

angajatii al caror salariu este

SELECT ENAME ,SAL,COMM


FROM EMP
WHERE SIGN (SAL-COMM)=1;
ENAME
SAL
COMM
----------------------------ALLEN
1600
300
WARD
1250
500
TURNER
1500
0
ABS(col/value)

gaseste valoarea

absoluta a coloanei

sau valorii.

SELECT SAL,COMM,COMM-SAL,ABS(COMM-SAL),ABS(-35)
FROM EMP
WHERE DEPTNO =30;
SAL
COMM
COMM-SAL ABS(COMM-SAL)
ABS(-35)
------------------------------------------------------1600.00
300.00 -1300
1300
35
1250.00
500.00
-750
750
35
1250.00
1400.00
150
150
35
2850.00
35
1500.00
00
-1500
1500
35
950.00
35
MOD(value1,value2)
'value2'.
SELECT
FROM
WHERE
ORDER BY

gaseste restul impartirii lui 'value1'la

SAL , COMM ,
EMP
DEPTNO =30
COMM;

MOD(SAL,COMM), MOD(100,40)

SAL
COMM
MOD(SAL,COMM)
MOD(100,40)
-------------------------------------------------------2,850.00
20
950.00
20
1,600.00
300.00
100
20
1,250.00
500.00
250
20
1,250.00
1,400.00
1250
20

58

1,500.00

00

1500

20

Alte citeva functii matematice:


LOG(m,n)
intoarce logaritmul cu baza m si argument n.
SIN(n)
intoarce sinusul lui n
SINH(n)
intoarce sinusul hiperbolic al lui n
TAN(n)
intoarce tangenta lui n
TANH(n)
intoarce tangenta hiperbolica a lui n
COS(n)
cosinus de n
COSH(n)
cosinus hiperbolic al lui n

Exercitii-cap.4- Folosirea functiilor


Aceste exercitii acopera folosirea functiilor nu doar in constructiile SELECT dar si in
WHERE si ORDER BY. Daca sunt folosite aliasuri ale coloanelor in rezultat , folo- siti-le in
constructia SELECT a propozitiei SQL.

TEME
1. Listati pentru toti angajatii
15 % si exprimat ca un nr. de
DEPTNO
ENAME
PCTSAL
--------------------------20 SMITH
920
30 ALLEN
1840
30 WARD
1438
20 JONES
3421
30 MARTIN
1438
30 BLAKE
3278
10 CLARK
2818
20 SCOTT
3450
10 KING
5750
30 TURNER
1725
20 ADAMS
1265
30 JAMES
1093
20 FORD
3450
10 MILLER
1495
14 selectate.
2. Obtineti urmatoarea iesire:
EMPLOYEE_AND_JOB
---------------SMITH
CLERK
ALLEN SALESMAN

59

numele si salariul
dolari.

marit cu

WARD
SALESMAN
JONES
MANAGER
MARTIN SALESMAN
BLAKE
MANAGER
CLARK
MANAGER
SCOTT
ANALYST
KING PRESIDENT
TURNER SALESMAN
ADAMS
CLERK
JAMES
CLERK
FORD
ANALYST
MILLER
CLERK
3. Obtineti urmatoarea iesire
EMPLOYEE
-------SMITH(Clerk)
ALLEN(Salesman)
WARD(Salesman)
JONES(Manager)
MARTIN(Salesman)
BLAKE(Manager)
CLARK(Manager)
SCOTT(Analyst)
KING(President)
TURNER(SAlesman)
ADAMS(Clerk)
JAMES(Clerk)
FORD(Analyst)
MILLER(Clerk)
4.

Faceti o cautare pentru a obtine o lista


functia 'job' specificata de utilizator.

a angajatilor

cu

Enter value for job :clerk


EMPNO ENAME
JOB
MGR HIREDATE
SAL
COMM DEPTNO
----------------------------------------------------------7369 SMITH
CLERK 7902 17-DEC-80
1000
20
7876 ADAMS
CLERK 7788 12-JAN-83
1100
20
7900 JAMES
CLERK 7698 03-DEC-81 1092.5
30
7934 MILLER CLERK 7782 23-JAN-82
1300
10
5. S- a descoperit ca nu toti angajatii din departamentul 30
sunt barbati .Obtineti urmatoarea iesire:
ENAME
DEPTNO
JOB
---------------------------ALLEN
30
Salesperson
WARD
30
Salesperson
MARTIN
30
Salesperson
BLAKE
30
Manager
TURNER
30
Salesperson
JAMES
30
Clerk

SOLUTII Cap.4
1. SELECT

DEPTNO,ENAME, ROUND(SAL*1.15) PCTSAL


FROM
EMP;
2. SELECT RPAD(ENAME,10)||LPAD(JOB,10) EMPLOYEE_AND_JOB
FROM
EMP;

60

3. SELECT

ENAME ||'('||initcap(job)||')' EMPLOYEE


FROM
EMP;
4. SELECT
*
FROM
EMP
WHERE
UPPER(JOB)=UPPER('&JOB');
5. SELECT ENAME,DEPTNO,INITCAP
(REPLACE(JOB,'SALESMAN','SALESPERSON')) JOB
FROM
EMP
WHERE
DEPTNO =30;

61

Capitolul 5
Alte functii singulare aplicate liniilor unei baze de date
In acest capitol vom trata functiile (de tip) referitoare la date calendaristice 'DATE', functiile
de conversie si functii care accepta orice tip de data de intrare.

Functiile de tip data calendaristica


Aceste functii se aplica asupra datelor ORACLE.
Toate functiile de tip data calendaristica intorc valoarea tipului DATE cu exceptia lui
MONTHS_BETWEEN care intoarce o valoare numerica.

Stocarea datelor calendaristice ORACLE


ORACLE stocheaza datele calendaristice intr-un format numeric intern reprezentind:

Secolul
Anul
Luna
Ziua
Ora
Minutele
Secundele

Formatul implicit de afisare sau intrare pentru o data calendaristica e DD-MON-YY.Datele


calendaristice ORACLE pot varia intre 1 ian 4712 ien si 31 dec 4712 e.n

Sysdate
Sysdate intoarce data curenta si timpul.Puteti folosi SYSDATE la fel ca folosirea oricarui
nume de coloana. De exemplu , puteti afisa data curenta selectind SYSDATE dintr-o tabela.
Este obisnuit sa se selecteze SYSDATE dintr-o tabela 'dummy' numita DUAL.
Tabela DUAL apartine utilizatorului 'SYS' si poate fi accesata de toti utilizatorii.Contine o
singura coloana ,DUMMY si o linie cu valoarea 'x'.
Tabela DUAL e folositoare cind doriti sa obtineti o singura valoare-de exemplu , valoarea
unei constante , pseudo-coloane sau expresii care nu e derivata dintr-o tabela cu data 'user'.
Pentru a afisa date curenta:
SELECT SYSDATE
FROM SYS.DUAL;

62

Puteti selecta usor SYSDATE din EMP, dar 14 linii cu aceeasi SYSDATE vor fi intoarse ,
una pentru fiecare linie din tabela EMP.
DUAL e preferata pentru ca e suficienta o singura linie intoarsa.

Folosirea operatorilor aritmetici


Pornind de la faptul ca data calendaristica e memorata ca un numar , e posibil sa se faca
calcule cu date calendaristice, folosind operatori aritmetici ca + sau -.Puteti aduna sau scadea
constante numerice ca si date calendaristice.
Operatiile pe care le puteti face sunt:
data + numar
aduna un numar de zile la data, reintorcind o data calendaristica
data - numar
scade un numar de zile dintr-o data, producind o data calendaristica
date - date
scade o data dintr-o data , obtinind un nr. de zile.
date + numar/24
aduna un nr. de ore pentru a obtine o data calen- daristica.
SELECT
FROM
WHERE

HIREDATE,HIREDATE+7, HIREDATE-7,SYSDATE - HIREDATE


EMP
HIREDATE LIKE '%JUN%';

HIREDATE
HIREDATE+7
HIREDATE-7 SYSDATE-HIREDATE
------------------------------------------------------13-jun-83
20-jun-83
06-jun-83
1982.70628
11-jun-84
18-jun-84
04-jun-84
1618.70628
04-jun-84
11-jun-84
28-may-84
1625.70628
04-jun-84
11-jun-84
28-may-84
1625.70628

Scazind din SYSDATE ,HIREDATE din tabela EMP intoarce nr.de zile de la angajarea
fiecarui om.
MONTHS_BETWEEN(data1,data2)
gaseste nr. de luni intre data1 si data2. Rezultatul poate fi pozitiv sau negativ. Daca
data1 e mai tarzie decat data2 , REZULTATUL E POZITIV, daca data2 este mai
tirzie decit data1 , REZULTATUL E NEGATIV.
SELECT
FROM
WHERE

MONTHS_BETWEEN (SYSDATE,HIREDATE),
MONTHS_BETWEEN('01-jan-84','05-nov-88')
EMP
MONTHS_BETWEEN(SYSDATE,HIREDATE)>59;

MONTHS_BETWEEN(SYSDATE,HIREDATE) MONTHS_BETWEEN('01-jan-84','05-nov88')
----------------------------------------------------------------------65.0873622
-58.129032
63
-58.129032
60.5067171
-58.129032
59.3454267
-58.129032
59.3454267
-58.129032

63

59.8292977

-58.129032

6 records selected

Partea neintreaga a rezultatului reprezinta o portiune dintr-o luna.


ADD_MONTHS(data,n)
aduna n numar de luni calendaristice la 'data'. n trebuie sa fie intreg si poate fi si
negativ.
SELECT HIREDATE, ADD_MONTHS(HIREDATE,3),ADD_MONTHS(HIREDATE,-3)
FROM EMP
WHERE DEPTNO =20;
HIREDATE
ADD_MONTHS(HIREDATE,3)
ADD_MONTHS(HIREDATE,-3)
---------------------------------------------------------------13-jun-83
13-sep-83
13-mar-83
31-oct-83
31-jan-84
31-jul-83
05-mar-84
05-jun-84
05-dec-83
04-jun-84
04-sep-84
04-mar-84
05-dec-83
05-mar-84
05-sep-83

NEXT_DAY(data1,,char)
data urmatoarei zile a saptaminii(char) urmind data1. Char trebuie sa fie un numar
reprezentind o zi sau un caracter.
SELECT HIREDATE,NEXT_DAY(HIREDATE,'FRIDAY'),NEXT_DAY(HIREDATE,6)
FROM EMP
WHERE DEPTNO =10;
HIREDATE
NEXT_DAY(HIREDATE,'FRIDAY') NEXT_DAY(HIREDATE,6)
-----------------------------------------------------------------14-may-84
18-may-84
18-may-84
09-jul-84
13-jul-84
13-jul-84
21-nov-83
25-nov-83
25-nov-83

LAST_DAY(data1)
gaseste data reprezentind ultima zi a lunii care contine data 1.
SELECT SYSDATE,LAST_DAY(SYSDATE),HIREDATE,LAST_DAY(HIREDATE),
LAST_DAY('15-FEB-88')
FROM EMP
WHERE DEPTNO =20;
SYSDATE LAST_DAY(SYSDATE) HIREDATE LAST_DAY(HIREDATE) LAST_DAY('15-feb88')
--------------------------------------------------------------------------04-DEC-89 31-DEC-89
17-DEC-80
31-DEC-80
29-FEB-88
o4-dec-89 31-dec-89
02-apr-81
30-apr-81
29-feb-88
04-dec-89 31-dec-89
09-dec-82
31-dec-82
29-feb-88
04-dec-89 31-dec-89
12-jan-83
31-jan-83
29-feb-88
04-dec-89 31-dec-89
03-dec-81
31-dec-81
29-feb-88

Functia ROUND poate fi aplicata pe date calendaristice.


Round(data1)
intoarce data1 cu timpul setat la 12:00AM(noaptea). Aceasta e folositor cind
comparam date care au timpuri diferite.
ROUND (data1,'MONTH')

64

intoarce prima zi a lunii continind data1 daca data1 este in prima parte a lunii, altfel
intoarce prima zi a urmatoarei luni.
ROUND(data 1,' YEAR')
intoarce prima zi a anului continind data1, daca data1 este in prima jumatate a anului,
altfel intoarce prima zi a urmatorului an.
SELECT SYSDATE,ROUND(SYSDATE,'MONTH'),ROUND(SYSDATE,'YEAR')
FROM SYS.DUAL;
SYSDATE ROUND(SYSDATE,'MONTH') ROUND(SYSDATE,'YEAR')
---------------------------------------------------------04-dec-89 01-dec-89
01-jan-90

TRUNC(data1,'char')
gaseste prima zi a lunii care e continuta in data1, cind char='MONTH'.Daca char=
'YEAR', gaseste prima zi a anului care contine data1.
SELECT SYSDATE,TRUNC(SYSDATE,'MONTH'),TRUNC(SYSDATE,'YEAR')
FROM SYS.DUAL;
SYSDATE
TRUNC(SYSDATE,'MONTH') TRUNC(SYSDATE,'YEAR')
----------------------------------------------------------o4-dec-89 01-dec-89
01-jan-89

TRUNC e folositor cind vreti sa stergeti timpul dintr-o data. Timpul component al zilei este
sters implicit.

Functii de conversie
SQL furnizeaza un numar de functii care controleaza conversiile datelor calendaristice.Aceste
functii de conversie , convertesc o valoare de la un tip de data la alt tip.
TO_CHAR(numar/data,{'fmt'})
converteste numar sau data la caractere in format 'fmt'.
TO_NUMBER(char)
converteste 'char' care contine un numar in 'NUMBER'.
TO_DATE('char','fmt')
converteste valoarea 'char' reprezentind o data calendaristica, intr-o valoare data in
felul 'fmt' specificat. Daca fmt e omis , formatul e DD-MON-YY.

TO_CHAR
Functia TO_CHAR este folosita frecvent pentru a schimba un format de data de la cel
implicat la un format de afisare alternativ. TO_CHAR (data,'date picture') specifica ca data va
fi convertita la un nou format de iesire.
Pentru a converti date curente de la formatul implicit (DD-MON-YY) la un nou format 'date
picture':
SELECT TO_CHAR(SYSDATE,'DAY, DDTH MONTH YYYY')
FROM SYS.DUAL;
TO_CHAR (SYSDATE,'DAY,DDTHMONTHYYYY')
------------------------------------TUESDAY
,05TH SEPTEMBER 1989

65

Observati ca:

'Date picture', care trebuie incadrate de apostrofi poate contine orice format dintre cele
tratate mai jos.Coloana si 'date picture' trebuie separate de virgula.
DAY si MONTH la iesire sunt automat aduse la lungimea 9 adaugind blancuri.
Pentru a sterge blancurile adaugate folositi prefixul FM(FILL MODE).

SELECT TO_CHAR (SYSDATE,'fmDAY,ddth Month YYYY')


FROM SYS.DUAL;
TO_CHAR(SYSDATE,'FMDAY,DDTHMONTHYYYY')
-------------------------------------Tuesday , 5th September 1989

FM poate fi folosit pentru a sterge zerourile de la inceput din formatul ddth ex:05TH este
schimbat in 5th. Cazul in care 'date picture' este introdusa este cazul in care va fi afisata.
TO_CHAR poate fi deasemenea folosita pentru extragerea timpului din zi , si afisarea lui
intr-un format specificat.
Pentru afisarea timpului dintr-o zi:
SELECT TO_CHAR (SYSDATE.'HH:MI:SS')
FROM SYS.DUAL;
TO_CHAR(SYSDATE,'HH:MI:SS')
--------------------------08:16:24

Functia TO_CHAR este de asemenea folosita pentru conversia unei valori de tip data
numerica la o valoare de tip data caracter.
TO_CHAR(numar,'number picture')
SELECT TO_CHAR (SAL,'$9,999')
FROM EMP;
TO_CHAR(SAL,'$9,999')
-------------------$1,000
$1,600
$1,250
$2,975

Observati ca formatul este optional.Daca'date picture' e omis, data este convertita la o valoare
de tip caracter in format Oracle, implicit DD-MON-YY.
Daca 'number picture ' nu e specificat, numarul e convertit intr-o valoare de tip caracter.
Observati de asemenea ca formatele nu afecteaza actuala reprezentare interna a valorii
coloanei.Ele afecteaza doar cum valoarea coloanei este afisata cind e regasita cu o constructie
SELECT.

66

Formate pentru date calendaristice


Elementele unui format de data calendaristica sunt:
SCC or CC
Secol;Prefixul 'S'face ca datele i.e.n. sa fie prefixate de'-'.
YYYY or SYYYY
An;Prefixul 'S' face ca datele i.e.n. sa fie prefixate de '-'.
YYY or YY or Y
Ultimele 3,2,1 cifre din an
Y,YYY
An cu virgula in pozitie specificata.
SYEAR or YEAR
An in litere ;Prefixul 'S' face ca pt.anii i.e.n. sa se puna '-'.
BC or AD
Indicatorul BC/AD(pt.i.e.n. sau e.n.).
B.C.or A.D.
Indicatorul BC/AD cu puncte.
Q
Sfert de an.
MM
Luna.
MONTH
Numele lunii adaugind blancuri pina la lungimea 9.
MON
Numele lunii abreviat la 3 litere.
WW or W
Saptamina a anului sau a lunii.
DDD or DD or D
Zi a anului, lunii,saptaminii.
DAY
Numele zilei ,adaugind blancuri pina la lungimea de 9 caractere.
DY
Numarul zilei abreviat la 3 litere.
J
Nr.de zile din decembrie 31,4713 i.e.n.
AM or PM
Indicator meridian.
A.M. or P.M.
Indicator meridian cu puncte.
HH or HH12
Ora din zi (1-12).
HH24
Ora din zi (0-23).
MI
Minute.
SS
Secunde.
SSSSS
Secunde dupa miezul noptii(0-86399).

67

/.,etc.
E reprodusa punctuatia in rezultat.
"..."
Sirul cu apostrofi reprodus in rezultat.

Prefixul de mai jos poate fi adaugat astfel:


fm
'FILL mode'.Prefixind MONTH sau DAY, suprima blancurile, lasind un rezultat de
lungime variabila ,FM va suprima zerourile de inceput din formatul ddth.Nu e
folositor cu alte coduri.A doua aparitie a lui 'fm' pune blan- curile din nou.
Sufixele de mai jos pot fi adaugate astfel:
TH
nr.ordinal(ex:''DDTH" transformat in "4TH").
SP
nr.transformat in sir (ex.DDSP"pt"FOUR").
SPTH sau thsp
confirma numerele ordinale cu transformarea numar- cadru (ex.DDSPTH
pt.FOURTH).

Observatie:
? Codurile sunt case sensitive si vor afecta afisarea datelor calendaristice astfel:
DAY
Day
Month
ddth
ddTh

MONDAY
Monday
July
14th
14th

Formatul de date RR
Daca-l folositi in locul lui YY, secolul variaza in acord cu anul specificat cu 2 cifre si ultimii
2 digiti ai anului curent.
Tabloul de mai jos rezuma comportamentul elementului RR.

FORMATUL DE DATE RR(ORACLE 7)


Pentru anii in alte secole
|
|
|
|
|
|
|
|

---------------------------------------------------------------------|
|
Daca cei 2 digiti ai anului sint
|
Daca cei
--------------------------------------------------------2 digiti |
|
0-49
50-99
|
ai anului
--------------------------------------------------------curent
|
|
|
sunt
|
0
|
data intoarsa este
data intoarsa este
|
|
|
in secolul crt.
in secolul anterior |
|
49
|
celui crt.
|

68

|
| ---------------------------------------------------------|
|
50
|
data intoarsa este
data intoarsa este in|
|
|
|
in secolul dupa
secolul crt.
|
|
|
99
|
cel crt.
|
------------------------------------------------------------------------

EXEMPLE:
-------------------------------------------------------------|
Anul crt.
Valoarea formatata
Anul interpretat
|
|
(DD_ MON_RR)
|
-------------------------------------------------------------|
1994
27-oct-95
1995
|
-------------------------------------------------------------|
1994
27-oct-17
2017
|
-------------------------------------------------------------|
2001
27-oct-95
1995
|
-------------------------------------------------------------|
2001
27-oct-17
2017
|
--------------------------------------------------------------

Formatul pentru numere


Elementele modelului pt.formatul de numere sunt:
Format
Semnificatie
Exemple
-----------------------------------------------------------9
numere(nr.de 9
999999
1234
determina lung de
afisare)
0

afis.zerourile de
la inceput

099999

semnul dolar

$999999

$1234

punct zecimal in

999999.99

1234.00

pozitie specificata

MI

PR

EEEE

999,999

001234

1,234

semnele minus la
dreapta(valori
negative)

999999MI

1234-

paranteze pentru
numere negative

999999PR

<1234>

notatie stiintifica
(formatul trebuie
sa aiba 4E)
99.999EEEE
inmultire cu 10
(n=numar de 9 dupa V)

9999V99

1.234E+03

123400

afiseaza valori zero


ca blancuri nu 0
B9999.99
1234.00
-----------------------------------------------------------------

69

Observatie:
Formatele numerice afisate mai jos in tablou pot fi folosite cu comanda
SQL*PLUSCOLUMN(vezi cap.10).

TO_NUMBER
In exemplul urmator , functia TO_NUMBER e folosita pentru a transforma un numar
memorat sub forma unui caracter intr-un tip numar.
SELECT EMPNO, ENAME,JOB,SAL
FROM
EMP
WHERE SAL>TO_NUMBER('1500');

TO_DATE
Pentru a afisa toti angajatii cu data angajarii 4 iulie 1984, puteti folosi functia TO_DATE:
SELECT EMPNO,ENAME, HIREDATE
FROM
EMP
WHERE HIREDATE =TO_DATE('June 4,1984','Month dd, YYYY');
EMPNO ENAME
HIREDATE
-----------------------7844 TURNER
04-jun-84

Constanta e convertita intr-o data si apoi comparata cu valoarea HIREDATE.


Functia TO_DATE e frecvent folosita pentru a transforma o valoare in ORACLE intr-un
format diferit de cel implicit. De exemplu , cind inserati o data , Oracle asteapta o data in
formatul implicit DD_MON_YY. Daca nu vreti sa folositi formatul implicit , trebuie sa
folositi functia TO_DATE si masca formatului dorit.
De exemplu:
Pentru a introduce in tabela EMP - o linie cu un format nestandard introduceti:
INSERT INTO EMP(EMPNO,DEPTNO,HIREDATE)
VALUES(777,,20,TO_DATE('19/08/90','DD/MM/YY'));

Comanda INSERT e tratata in detaliu mai tirziu.

Functii care accepta orice tip de data la intrare


DECODE

70

DECODE este cea mai puternica functie SQL.


Aceasta faciliteaza interogarile, facind munca unui 'case' sau a unei constructii'if-then-else'.
Syntax:
DECODE (col/expression,
search1,rezult1,[search2,rezult2,....,]
default)

Col/expression e comparata cu fiecare valoare'search'si intoarce 'rezult' daca col/expression


este egal cu valoarea 'search'.
Daca nu e gasita nici o egalitate, functia DECODE intoarce valoarea 'default'.Daca
valoarea'default' e omisa, NULL e intors pentru cazurile de nepotrivire.
ARGUMENTE

DECODE trebuie sa aiba minim 4 parametrii ca argumente.


COL/EXPRESSION
numele coloanei sau expresie pentru a fi evaluate
SEARCH1
prima valoare pentru testare
RESULT1
valoarea intoarsa daca se potriveste cu SEARCH1.
SEARCH1 si RESULT1 pot fi repetate de cite ori e necesar-[SEARCH2,
RESULT2,...]
DEFAULT
valoarea pentru a fi reintoarsa daca nu exista nici o potrivire.
Observatie:

col/expression pot fi orice tip de data


SEARCH poate fi acelasi tip ca expression /col
Valoarea intoarsa este fortata la acelasi tip ca al treilea argument (result1)

Exemplul urmator decodifica tipurile 'CLERK'si' MANAGER';altele nu testate.Acestea devin


implicite pentru UNDEFINE.
SELECT ENAME,
JOB,
DECODE(JOB,'CLERK','WORKER',
'MANAGER','BOSS',
'UNDEFINED') DECODED_JOB
FROM EMP;
ENAME
JOB
DECODED_JOB
------------------------------SMITH
CLERK
WORKER
ALLEN
SALESMAN
UNDEFINED
WARD
SALESMAN
UNDEFINED

71

JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER

MANAGER
SALESMAN
MANAGER
MANAGER
ANALYST
PRESIDENT
SALESMAN
CLERK
CLERK
ANALYST
CLERK

BOSS
UNDEFINED
BOSS
BOSS
UNDEFINED
UNDEFINED
UNDEFINED
WORKER
WORKER
UNDEFINED
WORKER

Pentru a afisa procentajele in functie de coloane GRADE din tabela SALGRADE:


SELECT GRADE,
DECODE(GRADE,'1','15%'
'2','10%',
'3','8%',
'5%')BONUS FROM SALGRADE;
GRADE
BONUS
--------------1
15%
2
10%
3
8%
4
5%
5
5%

Acest exemplu ilustreaza ca valoarea intoarsa e fortata la tipul celui de al treilea argument, la
folosirea functiei DECODE. Il sfatuim pe utilizator sa specifice ordinea in care informatia e
afisata introducind o valoare la fiecare rulare:
select * from emp
order by decode (&orderby,
1,
sal,
2,
ename,
sal);
Enter value for orderby:2
order by decode (2,1,sal,2,ename,sal)
*
ERROR at line 2:ORA -1722: invalid number

Observati ca aceata comanda produce o eroare fiindca tipul lui 'ename'(char) difera de cel al
lui 'sal'(numar) care e al treilea argument.
In exemplul de mai jos , dorim sa introducem salariul crescut in functie de meseria fiecarui
angajat.
SELECT JOB,SAL,DECODE(JOB,'ANALYST',SAL*1.1,
'CLERK',SAL*1.15,
'MANAGER',SAL*0.95,
SAL) DECODED_SALARY FROM EMP;

72

JOB
SAL
DECODED_SALARY
-------------------------------CLERK
800
920
SALESMAN 1,600
1600
SALESMAN 1,250
1250
MANAGER 2,975
2826.25
SALESMAN 1,250
1250
MANAGER 2,850
2707.5
MANAGER 2,450
2327.5
ANALYST 3,000
3300
PRESIDENT5,000
5000
SALESMAN 1,500
1500
CLERK
1,100
1265
CLERK
950
1092.5
ANALYST 3,000
3300
CLERK
1,300
1495

NVL(col/value,val) converteste o valoare NULL la 'val' Tipul datei trebuie sa se potriveasca


cu (col/value si val).
SELECT
FROM
WHERE

SAL*12+NVL(COMM,0),NVL(COMM,1000),SAL*12+NVL(COMM,1000)
EMP
DEPTNO=10;

SAL*12+NVL(COMM,0) NVL(COMM,1000) SAL*12+NVL(COMM,1000)


---------------------------------------------------------29400
1000
30400
60000
1000
61000
15600
1000
16600

GREATEST(col(value1,col/value2....) -intoarce cel mai mare dintr-o lista de valori.Toate


'col/value2' sint convertite la tipul col/value1 inaintea comparatiei.

SELECT
FROM
WHERE

GREATEST(1000,2000),GREATEST(SAL,COM)
EMP
DEPTNO=30;

GREATEST(1000,2000) GREATEST(SAL,COMM)
------------------------------------------2000
1600
2000
1250
2000
1400
2000
2000
1500
2000
6 records selected.

LEAST(col/value1,col/value2....) intoace cea mai mica valoare.


Toate col/value 2 sint convertite la tipul col/value1 inainte de comparatie.

73

SELECT
FROM
WHERE

LEAST(1000,2000),LEAST(SAL,COMM)
EMP
DEPTNO=30;

LEAST(1000,2000) LEAST(SAL,COMM)
--------------------------------1000
300
1000
500
1000
1250
1000
1000
0
1000
6 records selected.

VSIZE(col/value) - intoarce nr.de biti din reprezentarea interna ORACLE a lui col/value'.

SELECT DEPTNO,VSIZE(DEPTNO),VSIZE(HIREDATE),VSIZE(SAL),
VSIZE(ENAME)
FROM
EMP
WHERE DEPTNO=10;
DEPTNO VSIZE(DEPTNO) VSIZE(HIREDATE) VSIZE(SAL) VSIZE(ENAME)
--------------------------------------------------------10
2
7
3
5
10
2
7
2
4
10
2
7
2
6

FUNCTII IMBRICATE REVIZITATE


Amintim ca functiile pot fi imbricate la orice nivel si functiile interioare sunt evaluate intii
mergind pina la functia cea mai exterioara.Este bine sa se tina nr. de paranteze de inceput
(deschidere) si de sfirsit(inchidere).Trebuie sa fie acelasi numar din fiecare tip de paranteze.
Functiile de mai jos sint imbricate si sint evaluate dupa cum urmeaza.
SELECT
ENAME,NVL(TO_CHAR(MGR),'UNMANAGEABLE')
FROM EMP
WHERE MGR IS NULL;
ENAME
NVL(TO_CHAR(MGR),'UNMANAGEABLE')
----------------------------------------------KING
UNMANAGEABLE

1. Coloana MGR e convertita la caracter cu functia TO_CHAR


2. Functia NVL inlocuieste NULL mgr cu un sir de caractere 'UNMANAGEABLE'.
Functiile imbricate pot fi de asemenea folosite pentru a afisa date de vineri , la doua luni de
azi in formatul Day dd Month YYYY.
SELECT SYSDATE,
TO_CHAR(NEXT_DAY(ADD_MONTHS(SYSDATE,2),'FRIDAY'),'Day dd
Month YYYY')

74

FROM SYS.DUAL;
SYSDATE
TO_CHAR(NEXT_DAY(ADD_MONTHS(SYSDATE,2),'FRIDAY'),'DAYDDMONTHYYYY')
-----------------------------------------------------------------------04-dec-89 Friday
09 Februarie 1990

1.
2.
3.
4.
5.
6.
7.

Functia ADD_MONTHS aduna

2 luni

Functia NEXT_DAY gaseste vineri

la luna

curenta(decembrie)

la 2 luni

de SYSDATE

Functia TO_CHAR converteste coloana data la tipul CHAR pentru


afisarea in formatul Day dd Month YYYY

Capitolul 5 Exercitii - Functii

Aceste exercitii acopera functiile


pe cele

discutate in

acest capitol, ca si

din capitolul 4.

1.
2.
3.

Afisati pt.fiecare angajat din departamentul 20 numele si data


angajarii.
Fiti siguri ca specificati aliasul 'DATE_HIRED' dupa
expresia
4.
voastra altfel coloana respectiva va fi pierduta. Se
folo5.
seste o lungime de 80 de caractere care este lungimea
implicita
6.
pentru coloane de caracter.
7.
ENAME
DATE_HIRED
8.
--------------------------9.
SMITH
June,Thirteenth 1983
10.
JONES
October,Thirty-First 1983
11.
SCOTT
March,Fifth 1984
12.
ADAMS
June,Fourth 1984
13.
FORD
December,Fifth 1983
14.
15.
16.
17.
18.
19.
20.

Afisati pt.fiecare angajat numele, data angajarii si adaugati


un an la data angajarii pt.fiecare. Ordonati iesirea in
ordinea crescatoare a datei angajarii la care s-a adaugat
un an.
ENAME
HIREDATE REVIEW

75

21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.

--------------------------SMITH
13-jun-83 13-jun-84
ALLEN
15-aug-83 15-aug-84
JONES
31-oct-83 31-oct-84
MILLER
21-nov-83 21-nov-84
MARTIN
05-dec-83 05-dec-84
FORD
05-dec-83 05-dec-84
SCOTT
05-mar-84 05-mar-85
WARD
26-mar-84 26-mar-85
CLARK
14-may-84 14-may-85
TURNER
04-jun-84 04-jun-85
ADAMS
04-jun-84 04-jun-85
BLAKE
11-jun-84 11-jun-85
KING
09-jun-84 09-jun-85
JAMES
23-jun-84 23-jun-85
14 records selected

39.
40.

Afisati lista angajatilor , pentru fiecare afisind salariul


daca acesta e mai mare ca 1500, daca e egal cu 1500
afiseaza
41.
'On Target', daca e mai mic decit 155, afiseaza 'BELOW
1500'.
42.
ENAME
SALARY
43.
-----------------44.
ADAMS
Below 1500
45.
ALLEN
1600
46.
BLAKE
2850
47.
CLARK
2450
48.
FORD
3000
49.
JAMES
Below 1500
50.
JONES
2975
51.
KING
5000
52.
MARTIN
Below 1500
53.
MILLER
Below 1500
54.
SCOTT
3000
55.
SMITH
Below 1500
56.
TURNER
On Target
57.
WARD
Below 1500
58.
59.
14 records selected
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.

Scrieti o cerere care intoarce ziua din saptamina


(ex:MONDAY), pt. fiecare data introdusa in formatul
DD.MM.YY.
Enter value for anydate:12.11.88
DAY
-----------------------SATURDAY

73.
74.

Scrieti o cerere pt. a determina cit timp au fost angajati


companiei .Folositi DEFINE pentru a evita repetarea
tipului
75.
functiilor.

76

ai

76.
77.
78.
79.
80.
81.
82.
83.

Enter value

for

employee_name:king

ENAME
LENGTH OF SERVICE
------------------------------KING
4 YEARS 4 MONTHS

84. Dindu-se un sir in formatul 'nn/nn', verificati daca primele


85.
si ultimele 2 caractere sunt numere si daca caracterul
din
86.
mijloc este '/'.
87.
Afisati expresia 'Yes' daca e asa , sau 'No' altfel.
Folositi
88.
urmatoarele valori pentru a testa solutia voastra:
89.
'12/34',01/la','99/88'
90.
VALUE VALID?
91.
----------92.
12/34 YES
93.
94.
95. Angajatii pe 15 ale fiecarei luni sau inainte sint platiti
96.
in ultima vineri a acelei luni . Cei angajati dupa data
de
97.
15 sunt platiti in ultima vineri a urmatoarei luni.
98.
Afisati o lista a angajatilor , cu data de angajare si
prima
99.
data de plata.Sortati in functie de data angajarii.
100.
ENAME
HIREDATE PAYDAY
101.
--------------------------102.
SMITH
13-jun-83 24-jun-83
103.
ALLEN
15-aug-83 26-aug-83
104.
JONES
31-oct-83 25-nov-83
105.
MILLER
21-nov-83 30-dec-83
106.
MARTIN
05-dec-83 30-dec-83
107.
FORD
05-dec-83 30-dec-83
108.
SCOTT
05-mar-84 30-mar-84
109.
WARD
26-mar-84 27-apr-84
110.
CLARK
14-may-84 25-may-84
111.
TURNER
04-jun-84 29-jun-84
112.
ADAMS
04-jun-84 29-jun-84
113.
BLAKE
11-jun-84 29-jun-84
114.
KING
09-jul-84 27-jul-84
115.
JAMES
23-jul-84 31-aug-84
116.
117.
14 records selected
118.
119.

CAPITOLUL 5 SOLUTII

77

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.

SELECT

FROM
WHERE

ENAME,
TO_CHAR(HIREDATE,'fmMonth,Ddspth YYYY')
date_hired
EMP
DEPTNO=20;

SELECT ENAME,HIREDATE,ADD_MONTHS(HIREDATE,12) REVIEW


FROM
EMP
ORDER BY ADD_MONTHS(hiredate,12);

SELECT

ENAME,
DECODE(SIGN(1500-SAL),1,'BELOW 1500',0,'On
Target',SAL)
SALARY
FROM
EMP
ORDER BY ENAME;

SELECT

TO-CHAR(TO_DATE('&ANYDATE','DD.MM.YY'),'DAY')

FROM

SYS.DUAL;

DAY
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.

DEFINE TIME=MONTHS_BETWEEN(SYSDATE,HIREDATE)
SELECT
ENAME,
FLOOR(&TIME/12)||'YEARS'||
FLOOR(MOD(&TIME,12))||'MONTHS'
"LENGTH OF SERVICE"
FROM
EMP
WHERE
ENAME=UPPER('&EMPLOYEE_NAME');

SELECT

FROM

SELECT

FROM
ORDER BY

'12/34' VALUE
DECODE(
TRANSLATE('12/34','1234567890',
'9999999999'),
'99/99','YES',NO') "VALID?"
SYS.DUAL;

ENAME,
HIREDATE,
DECODE(SIGN(TO_CHAR(HIREDATE,'DD')-15
1,NEXT-DAY(LAST-DAY(ADD_MONTHS(HIREDATE,1)),
'FRIDAY')-7,
NEXT-DAY(LAST_DAY(HIREDATE),'FRIDAY')-7)
PAYDAY
EMP
HIREDATE;

sau
SELECT

FROM
ORDER BY

ENAME,HIREDATE,
NEXT_DAY(LAST_DAY(ROUND(HIREDATE,'MONTH'))-7
'FRIDAY') PAYDAY
EMP
HIREDATE;

78

79

Capitolul 6
Functii de grup
Acest capitol explica cum informatiile concise pot fi obtinute pen- tru grupuri de siruri
folosind functiile de grup.
Vom discuta cum puteti divide sirurile dintr-o tabela in seturi mai mici si cum sa specificati
criteriile de cautare intr-un grup de siruri.
Functiile de grup se aplica unui set de siruri.Ele intorc rezultate bazate pe grupuri de siruri ,
spre deosebire de un rezultat pe sir care e returnat de functii singulare.De regula , toate
sirurile din tabela sunt tratate ca un grup.Clauza GROUP BY din cadrul lui SELECT e
folosita pentru a imparti sirurile in grupuri mai mici.
Functiile de grup sunt listate mai jos:
Valoare returnata

AVG({DISTINCT/ALL})
valoarea medie a lui n, ignorind valorile nule.
COUNT({DISTINCT/ALL} expr*)
nr. de siruri unde expresia e evaluata la altceva decit NULL. (*) face ca COUNT sa
numere toate sirurile selectate, incluzind duplicatele si sirurile cu NULL.
MAX({DISTINCT/ALL}expr)
maximul valorilor expr.
MIN({DISTINCT/ALL}expr)D
minimul valorilor expresiei expr.
STDDEV({DISTINC/ALL}n)
deviatia standard a lui n , ignorind valorile nule.
SUM({DISTINC/ALL}n)
suma valorilor lui n , ignorind valorile nule.
VARIANCE({DISTINCT/ALL}n)
variatia lui n , ignorind valorile nule.
Toate functiile de deasupra opereaza pe un nr. de siruri (de ex., o intreaga tabela) si sunt
cunoscute ca functii de grup sau agregate. DISTINCT face ca functia de grup sa considere
doar valorile(nedupli- cate).
ALL considera fiecare valoare , incluzind si toate duplicatele. Implicit este ALL.
Tipul datelor argumentelor poate fi CHAR,NUMBER sau DATA unde expr e listata.
Toate fuctiile de grup cu exceptia lui COUNT(*) ignora valorile nule. Folositi NVL ca de
obicei pentru a include null.

FUNCTII DE GRUP
Folosirea functiilor de grup
Pentru a calcula salriul mediu al tuturor angajatilor, introducem :
80

SELECT AVG(SAL)
FROM EMP;
AVG(SAL)
-------2073.21429

Notati ca liniile din tabela EMP sint considerate ca un singur grup.


O functie de grup poate fi aplicata pe un subset de linii din tabela prin folosirea clauzei
WHERE.
Pentru a gasi salariul minim cistigat de un functionar, introducem :
SELECT MIN(SAL)
FROM EMP
WHERE JOB = 'CLERK';
MIN(SAL)
-------800

Pentru a numara angajatii din departamentul 20, introducem :

SELECT COUNT(*)
FROM EMP
WHERE DEPTNO = 20;
COUNT(*)
-------5

Clauza GROUP BY
Clauza GROUP BY poate fi folosita pentru a imparti liniile dintr-o tabela in grupuri mai
mici. Functiile de rup pot fi folosite pentru a intorece informatii sumare pentru fiecare grup.
Pentru a calcula salariul mediu pentru fiecare functie diferita, introducem:

SELECT JOB, AVG(SAL)


FROM EMP
GROUP BY JOB;
JOB
------ANALYST
CLERK
MANAGER
PRESIDENT
SALESMAN

AVG(SAL)
----------3000
1037.5
2758.33333
5000
1400

81

Excluderea liniilor cind folosim GROUP BY


Liniile pot fi excluse mai intii cu o clauza WHERE, inainte de a le imparti in grupuri.
Pentru a determina salariul mediu pentru fiecare functie in afara de manager, introducem :
SELECT JOB, AVG(SAL)
FROM EMP
WHERE JOB != 'MANAGER'
GROUP BY JOB;
JOB
------ANALYST
CLERK
PRESIDENT
SALESMAN

AVG(SAL)
----------3000
1037.5
5000
1400

Solutii
1.
2.

SELECT MIN(SAL) MINIMUM


FROM EMP;

3.
4.
5.

SELECT MAX(SAL), MIN(SAL), AVG(SAL)


FROM EMP;

6.
7.
8.
9.
10.
11.

SELECT JOB,
MAX(SAL) MAXIMUM,
MIN(SAL) MINIMUM
FROM EMP
GROUP BY JOB;

12.
13.
14.
15.

SELECT COUNT(*) MANAGERS


FROM EMP
WHERE JOB = 'MANAGER';

16.
17.
18.
19.
20.
21.

SELECT JOB,
AVG(SAL) AVSAL,
AVG(SAL * 12 + NVL(COMM, 0)) AVCOMP
FROM EMP
GROUP BY JOB;

22.
23.
24.

SELECT MAX(SAL) - MIN(SAL) DIFFERENCE


FROM EMP;

25.
26.
27.
28.
29.

SELECT DEPTNO, COUNT(*)


FROM EMP
GGROUP BY DEPTNO
HAVING COUNT(*) > 3;

30.
31.
32.
33.
34.

SELECT EMPNO
FROM EMP
GROUP BY EMPNO
HAVING COUNT(*) > 1;

35.
36.

SELECT MGR, MIN(SAL)

82

37.
38.
39.
40.

FROM EMP
GROUP BY MGR
HAVING MIN(SAL) >= 1000
ORDER BY MIN(SAL);

41.

83

CAPITOLUL 7
EXTRAGEREA DATELOR DIN MAI MULT DE O TABELA
Join
Join-ul este folosit cind o cerere SQL necesita date din mai multe tabele din baza de date.
Liniile dintr-o tabela pot fi unite cu liniile din alta tabela in functie de valorile comune
existente in coloanele corespunzatoare.
Sint doua tipuri de conditie de join :
1. Equi-join
2. Non-equi-join

Equi-join
Pentru a determina angajatii din departamente, vom compara valorile din coloana DEPTNO a
angajatului cu aceleasi valori din DEPTNO din tabela DEPT. Relatia dintre tabela EMP si
DEPT este un equi-join, in care valorile din coloana DEPTNO din ambele tabele sint egale.
(Operatorul de comparatie folosit este =.)
O conditie de join este specificata in clauza WHERE:
SELECT column(s)
FROM tables
WHERE join condition is ...

Pentru a face join pe cele doua tabele EMP si DEPT, introducem:


SELECT ENAME, JOB, DNAME
FROM EMP, DEPT
WHERE EMP>DEPTNO + DEPT>DEPTNO;
ENAME
------CLARK
MILLER
KING
SMITH
SCOTT
JONES
ADAMS
FORD
ALLEN
BLAKE
TURNER
JAMES
MARTIN

JOB
-----MANAGER
CLERK
PRESIDENT
CLERK
ANALYST
MANAGER
CLERK
ANALYST
SALESMAN
MANAGER
SALESMAN
CLERK
SALESMAN

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

84

WARD

SALESMAN

SALES

Vom observa ca acum fiecare angajat are listat numele departamentului lui.
Liniile din EMP sint combinate cu liniile din DEPT si sint intoarse doar liniile pentru care
valorile EMP.DEPTNO si DEPT.DEPTNO sint eale.
Observati ca, conditia de join specifica numele coloanei precedat de numele tabelei.Aceasta
este o necesitate cind numele coloanelor sint aceleasi in ambele tabele.Este necesar sa
specificam exact ce coloane sint referite.
Aceasta necesitate este de asemenea aplicata coloanelor care pot fi ambigue in clauzele
SELECT sau ORDER BY.
Pentru a recunoaste diferentele dintre coloana DEPTNO din EMP si coloana DEPTNO din
DEPT, introducem:
SELECT DEPT.DEPTNO, ENAME, JOB, DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
ORDER BY DEPT.DEPTNO;
DEPTNO
-------10
10
10
20
20
20
20
20
30
30
30
30
30
30

ENAME
------CLARK
MILLER
KING
SMITH
SCOTT
JONES
ADAMS
FORD
ALLEN
BLAKE
TURNER
JAMES
MARTIN
WARD

JOB
-----MANAGER
CLERK
PRESIDENT
CLERK
ANALYST
MANAGER
CLERK
ANALYST
SALESMAN
MANAGER
SALESMAN
CLERK
SALESMAN
SALESMAN

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

Observati ca fiecarui numar de departament din tabela DEPT i se face join pentru a se potrivi
cu numerele de departament din tabela EMP.De exemplu, trei angajati lucreaza in
departamentul 10 - Accounting - deci exista trei potri- viri.Prin urmare ACCOUNTING este
afisat pentru fiecare angajat din acel depar- tament.

Folosirea alias-urilor de tabela


Poate fi foarte plictisitor sa tiparesti numele tabelelor repetat.Etichete temporare (sau aliasuri) pot fi folosite in clauza FROM.Aceste nume temporare sint valide doar in instructiunea
SELECT curenta.Alias-urile de tabele trebuie de asemenea sa fie specificate in clauza
SELECT.Aceasta creste efectiv viteza cererii, in care contextul contine informatii foarte
exacte.
Alias-urile de tabela sint folosite in urmatorul context:

85

SELECT E.ENAME, D.DEPTNO, D.DNAME


FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
ORDER BY D.DEPTNO;

Alias-urile de tabele pot fi de lungime de maxim 30 de caractere, dar mai scurte sint mai
bune.De asemenea incercati sa le faceti cit mai explicite.
Daca un alias de tabela este folosit pentru un nume particular de tabela in clauza FROM,
atunci acel alias trebuie sa fie substituit pentru numele tabelei in contextul din SELECT.
Produs
----------------------------------------------------------------------EMPNO
ENAME
JOB
MGR
HIREDATE
SAL
COMM
DEPTNO |
----------------------------------------------------------------------|=======================================================================|
----------------------------------------------------------------------|
7788
SCOTT
ANALYST
7566
05-MAR-84
3000
20
|-----------------------------------------------------------------------|
|=======================================================================|
|
----------------------------------------------------------------------|
|

|
|
|
|
--------------------------------------------------------------------|
|
|
|
|
|
------------------------------|
| DEPTNO
DNAME
LOC
|
|
------------------------------|--------| 10
ACCOUNTING
NEW YORK |
|--------| 20
RESEARCH
DALLAS
|
|--------| 30
SALES
CHICAO
|
|--------| 40
OPERATIONS
BOSTON
|
-------------------------------

In absenta unei conditii WHERE, fiecare linie din EMP este unita in ordine cu fiecare linie
din DEPT.
Se vor afisa 53 de linii.
Produs

86

Cind o conditie de join este invalida sau este omisa, rezultatul este omis si toate combinatiile
de linii vor fi listate.
Un produs tinde sa genereze un numar mare de linii si rezultatul sau este rar folosit.Trebuie
intotdeauna inclusa o conditie de join intr-o clauza WHERE, in afara de cazul in care este
necesara combinarea tuturor liniilor din toate tabelele.

Non-Equi-Join
Relatia dintre tabelele EMP si SALGRADE este un non-equi-join, in care nici o coloana din
EMP nu corespunde direct cu o coloana din SALGRADE.Relatia este obtinuta folosind un
operator, altul decit operatorul de egalitate (=).Pentru a evalua gradatia unui anajat, salariul
lui trebuie sa fie intre salariul minim si salariul maxim.
Operatorul BETWEEN este folosit pentru a construi conditia, introducem:
SELECT E.ENAME, E.SAL, S.GRADE
FROM EMP E, SALGRADE S
WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL;
ENAME
--------SMITH
ADAMS
JAMES
WARD
MARTIN
MILLER
ALLEN
TURNER
JONES
BLAKE
CLARK
SCOTT
FORD
KING

SAL
------800.00
1,100.00
950.00
1,250.00
1,250.00
1,300.00
1,600.00
1,500.00
2,975.00
2,850.00
2,450.00
3,000.00
3,000.00
5,000.00

GRADE
--------1
1
1
2
2
2
3
3
4
4
4
4
4
5

Alti operatori cum ar fi <= si >= pot fi folositi, oricum BETWEEN este cel mai simplu.Nu
uitati sa specificati mai intii valoarea minima si ultima va- loarea maxima cind folositi
BETWEEN.Din nou sint folosite alias-uri de tabele, nu din cauza posibilelor ambiguitati, dar
din motive de performanta.

Reguli pentru join-ul tabelelor


Pentru a face join pe cele trei tabele este necesar sa construim doua condi- tii de join.Pentru a
face join pe patru tabele sint necesare minim trei condi- tii de join.
O regula simpla este:
numarul minim de conditii de join = numarul de tabele - 1
Aceasta regula nu poate fi aplicata daca tabela are o cheie primara, care identifica in mod
unic fiecare linie (cheile primare sint explicate mai tirziu in manual).

87

Sintaxa
SELECT [DISTINCT] {[tabela].* | expresie [alias], ...}
FROM tabela [alias], ...
WHERE [conditie de join] ...
AND [conditie de linie] ...
OR [alta conditie de linie]
GROUP BY {expresie | coloana}
HAVING {conditie de grup}
ORDER BY {expresie | coloana} [ASC | DESC]

Observatii

Se pot specifica conditii de join impreuna cu alte conditii (non join);


De asemenea trebuie sa fiti atenti la precedenta operatorilor cind folo- siti predicatul
OR.

Exercitii - Join-uri simple


Aceste exxercitii au intentia de a va capata experienta practica in extrage- rea datelor din mai
mult decit o tabela si includ teme discutate in capitolele anterioare.
Tema

1. Afisati numele tuturor angajatilor si numele departamentului lor, in ordi- nea numelui
departamentelor.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.

ENAME
-------CLARK
MILLER
KING
SMITH
SCOTT
JONES
ADAMS
FORD
ALLEN
BLAKE
TURNER
JAMES
MARTIN
WARD

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

Vor fi selectate 14 inregistrari.

20. Afisati numele tuturor angajatilor, numarul si numele departamentului.


21.
22.
23.
24.
25.
26.
27.

ENAME
-------CLARK
MILLER
KING

DEPTNO
--------10
10
10

DNAME
--------ACCOUNTING
ACCOUNTING
ACCOUNTING

88

28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.

SMITH
SCOTT
JONES
ADAMS
FORD
ALLEN
BLAKE
TURNER
JAMES
MARTIN
WARD

20
20
20
20
20
30
30
30
30
30
30

RESEARCH
RESEARCH
RESEARCH
RESEARCH
RESEARCH
SALES
SALES
SALES
SALES
SALES
SALES

Vor fi selectate 14 inregistrari.

41. Afisati numele, localitatea si departamentul angajatilor al caror salariu lunar este mai
mare ca 1500.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.

ENAME
-------CLARK
KING
JONES
FORD
SCOTT
ALLEN
BLAKE

LOCATION
---------NEW YORK
NEW YORK
DALLAS
DALLAS
DALLAS
CHICAGO
CHICAGO

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

Vor fi selectate 7 inregistrari.

53. Afisati lista salariilor, gradatiilor angajatilor.


54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.

ENAME
---------SMITH
ADAMS
JAMES
WARD
MARTIN
MILLER
ALLEN
TURNER
JONES
BLAKE
CLARK
SCOTT
FORD
KING

JOB
------CLERK
CLERK
CLERK
SALESMAN
SALESMAN
CLERK
SALESMAN
SALESMAN
MANAGER
MANAGER
MANAGER
ANALYST
ANALYST
PRESIDENT

SAL
------800.00
1,100.00
950.00
1,250.00
1,250.00
1,300.00
1,600.00
1,500.00
2,975.00
2,850.00
2,450.00
3,000.00
3,000.00
5,000.00

GRADE
---------1
1
1
2
2
2
3
3
4
4
4
4
4
5

SAL
------1,600.00
1,500.00

GRADE
---------3
3

70. Listati doar angajatii cu gradatia 3.


71.
72.
73.
74.

ENAME
---------ALLEN
TURNER

JOB
------SALESMAN
SALESMAN

89

75. Listati toti angajatii din Dallas.


76.
77.
78.
79.
80.
81.
82.

ENAME
---------SMITH
SCOTT
JONES
ADAMS
FORD

SAL
------800.00
3,000.00
2,975.00
1,100.00
3,000.00

LOCATION
---------DALLAS
DALLAS
DALLAS
DALLAS
DALLAS

Alte exercitii daca aveti timp:

83. Afisati numele angajatilor, functia, salariul, gradatia si numele departa- mentului
pentru toti angajatii din companie in afara de functionari.Sortati dupa salariu, afisind
mai intii salariul cel mai mare.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.

ENAME
-------KING
FORD
SCOTT
JONES
BLAKE
CLARK
ALLEN
TURNER
MARTIN
WARD

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

SAL
-------5,000.00
3,000.00
3,000.00
2,975.00
2,850.00
2,450.00
1,600.00
1,500.00
1,250.00
1,250.00

GRADE
--------5
4
4
4
4
4
3
3
2
2

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

Vor fi selectate 10 inregistrari.

100.
Afisati urmatoarele detalii pentru angajatii care cistiga 36000$ pe an sau care
sint functionari.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.

ENAME
--------FORD
SCOTT
MILLER
JAMES
ADAMS
SMITH

JOB
ANNUAL_SAL
------- -------------ANALYST
ANALYST
CLERK
CLERK
CLERK
CLERK

36000
36000
15600
11400
13200
9600

Vor fi selectate 6 inregistrari.

Solutii
1.
2.
3.

SELECT ENAME, DNAME


FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;

90

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

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

GRADE
------4
4
2
1
1
1

4.
5.
6.
7.

SELECT ENAME, E.DEPTNO, DNAME


FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;

8.
9.
10.
11.
12.

SELECT ENAME, LOC LOCATION, DNAME


FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
AND SAL > 1500;

13.
14.
15.
16.

SELECT ENAME, JOB, SAL, GRADE


FROM EMP, SALGRADE
WHERE SAL BETWEEN LOSAL AND HISAL;

17.
18.
19.
20.
21.

SELECT ENAME, JOB, SAL, GRADE


FROM EMP, SALGRADE
WHERE SAL BETWEEN LOSAL AND HISAL
AND GRADE = 3;

22.
23.
24.
25.
26.

SELECT ENAME, SAL, LOC LOCATION


FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
AND LOC = 'DALLAS';

27.
28.
29.
30.
31.
32.
33.

SELECT ENAME, JOB, SAL, GRADE, DNAME


FROM EMP, SALGRADE, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
AND SAL BETWEEN LOSAL AND HISAL
AND JOB != 'CLERK'
ORDER BY SAL DESC;

34.
35.
36.
37.
38.
39.
40.

SELECT ENAME, JOB, SAL * 12 ANNUAL_SAL, D.DEPTNO, DNAME, GRADE


FROM EMP E, SALGRADE, DEPT D
WHERE E.DEPTNO = D.DEPTNO
AND SAL BETWEEN LOSAL AND HISAL
AND (SAL * 12 + NVL(COMM, 0) = 3600 OR E.JOB = 'CLERK')
ORDER BY E.JOB;

41.

91

CAPITOLUL 8
ALTE METODE DE JOIN
Acest capitol prezinta diferite metode de constructie a conditiilor de join.

Join extern
Daca o linie nu satisface o conditie de join, atunci linia respectiva nu va apare in rezultatul
cererii.De fapt, in conditia de equi-join pentru EMP si DEPT, departamentul 40 nu
apare.Aceasta se intimpla deoarece nu este nici un angajat in departamentul 40.
-----------------------------------------------------------------------|
JOIN EXTERN
|
|
|
|
-----------------------------------------------------|
|
| EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO |
|
|
------------------------------------------------------ ?
|
|
|======================================================|-----|
|
-----------------------------------------------------|
|
|
|
|
|
--------------------------------------------------------------|
|
|
|
|
|
|
-------------------------------|
|
|
| DEPTNO
DNAME
LOC
|
|
|
|
-------------------------------|
|
|
|================================|
|
|
|
-------------------------------|
|
|---------|
40
OPERATIONS
BOSTON
|
|
|
-------------------------------|
|
|
------------------------------------------------------------------------

Nu exista nici un angajat in departamentul 40, dar el poate fi afisat facind join intre
departamentul 40 cu o linie vida.
Liniile ce lipsesc pot fi returnate daca este folosit un operator de join extern in conditia de
join.Operatorul este semnul plus inclus intre paranteze (+) si este plasat in partea tabelei
deficiente in informatii.Operatorul are ca efect crearea uneia sau mai multor linii vide cu care
una sau mai multe linii din tabela nedeficitara in informatii poate face join.
O linie vida este creata pentru fiecare linie adaugata in tabela nedefici- tara in informatii.
SELECT E.ENAME, D.DEPTNO, D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
AND D.DEPTNO IN (30, 40);
ENAME
--------ALLEN

DEPTNO
--------30

DNAME
--------SALES

92

BLAKE
TURNER
JAMES
MARTIN
WARD

30
30
30
30
40

SALES
SALES
SALES
SALES
OPERATIONS

Operatorul de join extern pote apare doar intr-o parte a expresiei si anume in partea in care
lipsesc informatii.Vor fi intoarse acele linii dintr-o ta- bela care nu au corespondent direct in
cealalta tabela.
Alte restrictii pentru join extern sint:

nu se poate face join extern a unei tabele cu mai mult de o tabela ce di- fera de prima
intr-o singura declaratie SELECT;
o conditie ce include un join extern nu poate folosi operatorul IN sau nu i se poate fi
unita cu alte conditii prin operatorul OR.

Join-ul unei tabele cu ea insasi


Este posibila folosirea etichetelor de tabele (alias-urilor) pentru a face join unei tabele cu ea
insasi, ca si cum ar fi doua tabele separate.Aceasta permite ca liniilor dintr-o tabela sa li se
faca join cu liniile din aceeasi tabela.
Urmatoarea cerere listeaza toti angajatii care cistiga mai putin ca sefii lor :
SELECT E.ENAME EMP_NAME, E.SAL EMP_SAL,
M.ENAME MGR_NAME, M.SAL MGR_SAL
FROM EMP E, EMP M
WHERE E.MGR = E.EMPNO
AND E.SAL < M.SAL;

EMP_NAME
----------ALLEN
WARD
MARTIN
TURNER
JAMES
MILLER
ADAMS
JONES
BLAKE
CLARK
SMITH

EMP_SAL
----------1600
1250
1250
1500
950
1300
1100
2975
2850
2450
800

MGR_NAME
----------BLAKE
BLAKE
BLAKE
BLAKE
BLAKE
CLARK
SCOTT
KING
KING
KING
FORD

MGR_SAL
---------2850
2850
2850
2850
2850
2450
3000
5000
5000
5000
3000

Observati ca, clauza FROM se refera la EMP de doua ori si ca urmare EMP are asociata cite
un alias pentru ambele cazuri - E si M.Este ajutator ca alias- urile asociate sa fie cu inteles, de
exemplu E inseamna angajati (employees) si M inseamna sefi (managers).
Clauza join poate fi exprimata:
"unde numarul sefului angajatului este acelasi cu numarul angajatului se- fului lui".
93

Operatori de multimi
In cadrul acestui capitol vor fi discutate reuniunea, intersectia si dife- renta.
Reuniunea, intersectia si diferenta sint folositoare in constructia cereri- lor care se refera la
tabelediferite.Ele combina rezultatele a doua sau mai multe declaratii select in unul singur.O
cerere poate fi formata din doua sau mai multe declaratii SQL inlantuite prin operatori de
multimi.Operatorii de multimi sint numiti join-uri verticale, deoarece join-ul nu se face in
raport cu liniile din cele doua tabele, ci in raport cu coloanele.
In urmatoarele trei exemple, cererile sint aceleasi, dar operatorul este diferit in fiecare caz,
generindu-se rezultate diferite pentru cereri.

Reuniunea
Pentru a lista toate liniile diferite generate de fiecare din cereri, introducem:
SELECT JOB
FROM EMP
WHERE DEPTNO = 10
UNION
SELECT JOB
FROM EMP
WHERE DEPTNO = 30;
JOB
----CLERK
MANAGER
PRESIDENT
SALESMAN

UNION ALL
Pentru a lista toate liniile (inclusiv duplicatele) generate de fiecare din cereri, introducem:
SELECT JOB
FROM EMP
WHERE DEPTNO = 10
UNION ALL
SELECT JOB
FROM EMP
WHERE DEPTNO = 30;
JOB
----PRESIDENT
MANAGER
CLERK
MANAGER
SALESMAN
SALESMAN
SALESMAN
SALESMAN

94

CLERK

Intersectia
Pentru a lista doar liniile generate de ambele cereri, introducem:
SELECT JOB
FROM EMP
WHERE DEPTNO = 10
INTERSECT
SELECT JOB
FROM EMP
WHERE DEPTNO = 30;
JOB
----CLERK
MANAGER

Diferenta
Pentru a lista toate liniile generate de prima cerere care nu sint in a doua cerere, introducem:
SELECT JOB
FROM EMP
WHERE DEPTNO = 10
MINUS
SELECT JOB
FROM EMP
WHERE DEPTNO = 30;
JOB
----PRESIDENT

Este posibil sa se construiasca cereri cu mai multi operatori de multimi. Daca sint folositi mai
multi operatori de multimi, ordinea executiei pentru declaratiile SQL este de sus in
jos.Parantezele pot fi folosite pentru a face ordinea executiei alternativa.

ORDER BY
ORDER BY poate fi folosita o data intr-o cerere ce foloseste operatori de multimi.Daca este
folosita, clauza ORDER BY trebuie plasata la sfirsitul cererii.Deoarece pot fi selectate
coloane diferite in fiecare SELECT nu se pot numi coloanele in clauza ORDER BY.In scimb,
coloanele din ORDER BY trebuie sa fie referite prin pozitiile relative din lista din SELECT.
SELECT EMPNO, ENAME, SAL
FROM EMP
UNION
SELECT ID, NAME, SALARY
FROM EMP_HISTORY
ORDER BY 2;

95

Observati ca in clauza ORDER BY un numar (2) este folosit pentru a indica pozitia coloanei
ENAME in lista din SELECT.Aceasta inseamna ca liniile vor fi sortate in ordine ascendenta
a numelui angajatilor.

Reguli pentru folosirea operatorilor de multimi


1.
2.
3.
4.
5.
6.
7.
8.
9.

Declaratiile SELECT trebuie sa aiba acelasi numar de coloane.


Coloanele corespunzatoare trebuie sa aiba acelasi tip (corespondenta este pozitionala).
Liniile duplicate sint automat eliminate (nu poate fi folosit DISTINCT).
Numele coloanelor din prima cerere apar in rezultat.
Clauza ORDER BY apare la sfirsitul declaratiei.
ORDER BY se face doar dupa pozitia coloanei (nu dupa numele coloanei).
Operatorii de multimi pot fi folositi in subcereri.
Blocurile de cerere sint executate de sus in jos.
Operatorii de multimi multipli pot fi folositi cu paranteze, daca este necesara
schimbarea secventei executiei.

Exercitii
Aceste exercitii va vor da posibilitatea sa descoperiti diferite metode de join si sa capatati
experienta la folosirea operatorilor de multimi.

Tema
1. Afisati departamentul care nu are nici un angajat.
2.
3.
4.

DEPTNO
-------40

DNAME
-------OPERATIONS

5. Afisati toti angajatii (nume si numar) impreuna cu numele si numarul se- fului.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.

EMPNO
-------7788
7902
7499
7521
7654
7844
7900
7934
7876
7566
7698
7782
7369

ENAME
--------SCOTT
FORD
ALLEN
WARD
MARTIN
TURNER
JAMES
MILLER
ADAMS
JONES
BLAKE
CLARK
SMITH

MGRNO
-------7566
7566
7698
7698
7698
7698
7698
7782
7788
7839
7839
7839
7902

MGR_NAME
-----------JONES
JONES
BLAKE
BLAKE
BLAKE
BLAKE
BLAKE
CLARK
SCOTT
KING
KING
KING
FORD

Vor fi selectate 13 inregistrari.

96

24. Modificati solutia de la intrebarea 2 pentru a afisa KING care nu are sef.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.

EMPNO
-------7839
7788
7902
7499
7521
7654
7844
7900
7934
7876
7566
7698
7782
7369

ENAME
--------KING
SCOTT
FORD
ALLEN
WARD
MARTIN
TURNER
JAMES
MILLER
ADAMS
JONES
BLAKE
CLARK
SMITH

MGRNO
--------

MGR_NAME
------------

7566
7566
7698
7698
7698
7698
7698
7782
7788
7839
7839
7839
7902

JONES
JONES
BLAKE
BLAKE
BLAKE
BLAKE
BLAKE
CLARK
SCOTT
KING
KING
KING
FORD

Vor fi selectate 14 inregistrari.

43. Gasiti functia care a fost ocupata in prima jumatate a anului 1983 si aceeasi functie a
fost ocupata in timpul aceleiasi perioade in 1984.
44.
45.
46.
47.
48.

JOB
-----CLERK
Va fi selectata o inregistrare.

Incercati si urmatoarele daca aveti timp:


49. Gasiti toti angajatii care au venit in companie inaintea sefilor lor.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.

EMPLOYEE
----------ALLEN
WARD
MARTIN
TURNER
MILLER
JONES
BLAKE
CLARK
SMITH

HIREDATE
----------15-AUG-83
26-MAR-84
05-DEC-83
04-JUN-84
21-NOV-83
31-OCT-83
11-JUN-84
14-MAY-84
13-JUN-83

MANAGER
---------BLAKE
BLAKE
BLAKE
BLAKE
CLARK
KING
KING
KING
FORD

Vor fi selectate 9 inregistrari.

63. Gasiti alta cerere pentru intrebarea 1.


64.
65.
66.

DEPTNO
--------40

DNAME
-------OPERATIONS

Solutii
1.

97

HIREDATE
----------11-JUN-84
11-JUN-84
11-JUN-84
11-JUN-84
14-MAY-84
09-JUL-84
09-JUL-84
09-JUL-84
05-DEC-83

2.
3.
4.
5.
6.

SELECT D.DEPTNO, DNAME


FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
AND E.EMPNO IS NULL;

7.
8.
9.
10.
11.

SELECT EMPS.EMPNO, EMPS.ENAME,


MGRS.EMPNO MGRNO, MGRS.ENAME MGR_NAME
FROM EMP EMPS, EMP MGRS
WHERE EMPS.MGR = MGRS.EMPNO;

12.
13.
14.
15.
16.

SELECT EMPS.EMPNO, EMPS.ENAME,


MGRS.EMPNO MGRNO, MGRS.ENAME MGR_NAME
FROM EMP EMPS, EMP MGRS
WHERE EMPS.MGR = MGRS.EMPNO(+);

17.
18.
19.
20.
21.
22.
23.
24.

SELECT JOB
FROM EMP
WHERE HIREDATE BETWEEN '01-JAN-83' AND '30-JUN-83'
INTERSECT
SELECT JOB
FROM EMP
WHERE HIREDATE BETWEEN '01-JAN-84' AND '30-JUN-84';

25.
26.
27.
28.
29.
30.

SELECT E.ENAME EMPLOYEE, E.HIREDATE,


M.ENAME MANAGER, M.HIREDATE
FROM EMP E, EMP M
WHERE E.MGR = M.MGRNO
AND E.HIREDATE < M.HIREDATE;

31.
32.
33.
34.
35.
36.
37.

SELECT DEPTNO, DNAME


FROM DEPT
MINUS
SELECT EMP.DEPTNO, DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;

38.

98

CAPITOLUL 9
SUBCERERI
In acest capitol se vor prezenta alte caracteristici ale declaratiei SELECT, cum ar fi cereri
continute in clauza WHERE sau HAVING ale altei decla- ratii SQL.

Subcereri ascunse
O subcerere este o declaratie SELECT care este ascunsa in interiorul altei declaratii SELECT
si care intoarce rezultate intermediare.
De exemplu:
SELECT column1, column2, ...
FROM table
WHERE column =
(SELECT column
FROM table
WHERE condition)

Subcererea este adesea referita ca un subselect sau ca un SELECT interior; in general,


subcererea se executa prima si rezultatul sau este folosit pentru a completa conditia cererii
principale sau a cererii externe.Folosirea sub- cererilor permite consruirea de comenzi
puternice pornind de la unele simple. Cererea ascunsa poate fi foarte folositoare cind este
nevoie sa fie selectate linii dintr-o tabela printr-o conditie ce depinde de date din propria
tabela.

Subcereri ce intorc o linie


Pentru a gasi angajatul care cistiga salariul minim din companie (salariul minim este o
cantitate necunoscuta), trebuie parcursi doi pasi:

1. Gasirea salariului minim:


2.
3.
4.
5.
6.
7.
8.

SELECT MIN(SAL)
FROM EMP;
MIN(SAL)
---------800

9. Gasirea angajatului care cistiga salariul minim:


10.
11.
12.

SELECT ENAME, JOB, SAL

99

13.
14.

FROM EMP
WHERE SAL = (cel mai mic salariu care este cunoscut)

Putem combina cele doua cereri ca o subcerere ascunsa:


SELECT ENAME, JOB, SAL
FROM EMP
WHERE SAL = (SELECT MIN(SAL)
FROM EMP);
ENAME
------SMITH

JOB
-----CLERK

SAL
----800

Cum sint prelucrate subcererile ascunse ?


O declarartie SELECT poate fi considerata ca un bloc de cerere.Exemplul de mai sus consta
din doua blocuri de cerere - cererea principala si cererea in- terioara.
Declaratia SELECT interioara sau blocul de cerere este executata prima, producind un
rezultat al cererii: 800.Blocul de cerere principal este apoi prelucrat si foloseste valoarea
intoarsa de cererea interioara pentru a com- pleta conditia de cautare.Deci, cererea principala
in final va arata in felul urmator:
SELECT ENAME, SAL, DEPTNO
FROM EMP
WHERE SAL = 800;

In exemplul de mai sus, 800 este o valoare unica.Subcererea care a intors valoarea 800 se
numeste subcerere ce intoarce o singura linie.Cind o subcerere intoarce doar o linie, va fi
folosit un operator logic sau un operator de com- paratie.De exemplu: =, <, >, <=, etc.
Pentru a gasi toti angajatii ce au aceeasi functie ca BLAKE, vom introduce:
SELECT ENAME, JOB
FROM EMP
WHERE JOB = (SELECT JOB
FROM EMP
WHERE ENAME = 'BLAKE');
ENAME
------JONES
BLAKE
CLARK

JOB
----MANAGER
MANAGER
MANAGER

Cererea interioara intoarce functia lui BLAKE, care este folosita in partea dreapta a clauzei
WHERE di cererea principala (dupa operatorul de comparatie).

100

Subcereri ce intorc mai mult de o linie


Urmatoarea cerere gaseste angajatii care au salariul egal cu salariul minim din fiecare
departament:
SELECT ENAME, SAL, DEPTNO
FROM EMP
WHERE SAL IN
(SELECT MIN(SAL)
FROM EMP
GROUP BY DEPTNO);

ENAME
------SMITH
JAMES
MILLER

SAL
----800
950
1300

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

Observati ca, cererea interioara are clauza GROUP BY.Aceasta inseamna ca va intoarce mai
mult decit o valoare.Deci este nevoie sa folosim un operator de comparatie multi linie.In
acest caz, operatorul IN trebuie sa fie folosit, deoarece rezulta o lista de valori.
Rezultatul obtinut nu arata si departamentul in care lucreaza angajatul.
Deoarece se compara doar valorile salariilor, cererea interioara poate intoar- ce o valoare
simpla, pentru ca el cauta cel mai mic salariu pentru unul din departamente, nu in mod
necesar departamentul propriu al angajatului.Prin urmare, cererea poate fi rescrisa pentru a
gasi combinatia salariul angaja- tului si numarul departamentului cu salariul minim si
numarul departamentului:

Compararea a mai multor valori


Urmatoarea cerere ggaseste angajatii care cistiga salariul cel mai mic din departamentul lor:
SELECT ENAME, SAL, DEPTNO
FROM EMP
WHERE (SAL, DEPTNO) IN
(SELECT MIN(SAL), DEPTNO
FROM EMP
GROUP BY DEPTNO);
ENAME
------SMITH
JAMES
MILLER

SAL
----800
950
1300

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

Cererea de mai sus compara o pereche de coloane.


Observatie : coloanele din partea stinga a conditiei de cautare sint in pa- ranteze si fiecare
coloana este separata printr-o virggula.

101

Coloanele listate in clauza SELECT a subcererii trebuie sa fie in aceeasi ordine ca si lista
coloanelor dintre paranteze din clauza WHERE a cererii externe.
Coloanele intoarse de cererea interioara trebuie, de asemenea sa se potri- veasca in numar si
tip de date cu coloanele cu care ele sint comparate in cererea externa.
De exemplu :
...WHERE (numcolumn, charcolumn) =
(SELECT datecolumn, numcolumn, charcolumn ...

nu este permis.

Erori intilnite
Cind o subcerere intoarce mai mult decit o linie si este folosit un opera- tor de comparatie pt
o singura linie, SQL*Plus da urmatorul mesaj de eroare:
SELECT ENAME, SAL, DEPTNO
FROM EMP
WHERE SAL = (SELECT MIN(SAL)
FROM EMP
GROUP BY DEPTNO);

Eroare : subcerere ce trebuie sa intoarca o singura linie intoarce mai mult decit o linie.
Nu este selectata nici o inregistrare.
Daca cererea interioara nu intoarce nici o linie, va fi dat urmatorul mesaj de eroare :
SELECT ENAME, JOB
FROM EMP
WHERE JOB = (SELECT JOB
FROM EMP
WHERE ENAME = 'SMITHE');

Eroare : subcerere ce trebuie sa intoarca o singura linie nu intoarce nici o linie.


Nu este selectata nici o inregistrare.

Operatorii SOME/ANY, ALL


Operatorii ANY sau ALL pot fi folositi pentru subcererile care intorc mai mult de o linie.Ei
sint folositi in clauzele WHERE sau HAVING in legatura cu operatorii logici (=, !=, <, >, >=,
<+).
ANY (sau sinonimul sau SOME) compara o valoare cu fiecare valoare intoarsa de o
subcerere.
Pentru a afisa angajatii care cistiga mai mult decit cel mai mic salariu din departamentul 30,
introducem :

102

SELECT ENAME, SAL, JOB, DEPTNO


FROM EMP
WHERE SAL > SOME (SELECT DISTINCT SAL
FROM EMP
WHERE DEPTNO = 30)
ORDER BY SAL DESC;
ENAME
------KING
SCOTT
FORD
JONES
BLAKE
CLARK
ALLEN
MILLER
WARD
ADAMS

SAL
----5000
3000
3000
2975
2850
2450
1600
1300
1250
1100

JOB
----PRESIDENT
ANALYST
ANALYST
MANAGER
MANAGER
MANAGER
SALESMAN
CLERK
SALESMAN
CLERK

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

Cel mai mic salariu din departamentul 30 este 950$ (a lui James).Cererea principala intoarce
angajatii care cistiga un salariu mai mare ca salariul minim din departamentul 30.Asa ca '>
ANY' inseamna mai mare ca minim.'=ANY' este echivalent cu IN.
Cind se foloseste SOME/ANY, DISTINCT este frecvent folosit pentru a impie- dica sa se
selecteze linniile de mai multe ori.
ALL compara o valoare cu fiecare valoare intoarsa de o subcerere.
Urmatoarea cerere gaseste angajatii care cistiga mai mult ca fiecare angajat din departamentul
30 :
SELECT ENAME, SAL, JOB, DEPTNO
FROM EMP
WHERE SAL > ALL (SELECT DISTINCT SAL
FROM EMP
WHERE DEPTNO = 30)
ORDER BY SAL DESC;
ENAME
------KING
SCOTT
FORD
JONES

SAL
----5000
3000
3000
2975

JOB
----PRESIDENT
ANALYST
ANALYST
MANAGER

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

Cel mai mare salariu din departamentul 30 este 250$ (a lui Blake), asa ca cererea intoarce
acei angajati ai caror salariu este mai mare ca salariul maxim din departamentul 30, prin
urmare mai mare ca fiecare salariu din de- partament.
Operatorul NOT poate fi folosit cu IN, ANY sau ALL.

Clauza HAVING cu subcereri ascunse


Subcererile ascunse pot fi folosite de asemenea in clauza HAVING.

103

(Observatie : clauza WHERE se refera la o singura linie si clauza HAVING la grupuri de linii
specificate in clauza GROUP BY.)
De exemplu, pentru a afisa departamentul(ele) care au un salariu mediu mai mare ca
departamentul 30, introducem :
SELECT DEPTNO, AVG(SAL)
FROM EMP
HAVING AVG(SAL) > (SELECT AVG(SAL)
FROM EMP
WHERE DEPTNO = 30)
GROUP BY DEPTNO;
DEPTNO
-------10
20

AVG(SAL)
---------2916.66667
2175

Pentru a construi o cerere care gaseste functia cu cel mai mare salariu mediu, introducem :

SELECT JOB, AVG(SAL)


FROM EMP
GROUP BY JOB
HAVING AVG(SAL) = (SELECT MAX(AVG(SAL))
FROM EMP
GROUP BY JOB);
JOB
----PRESIDENT

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

Mai intii cererea interioara gaseste salariul mediu pentru fiecare grup de functii diferit si
functia MAX alege cel mai mare salariu mediu.Acea valoare (5000) este folosita in clauza
HAVING.Clauza GROUP BY din cererea principala este necesara pentru ca lista ce urmeaza
dupa SELECT-ul din cererea principala contine atit o coloana agregat cit si o coloana nonagragat.

Ordonarea datelor cu subcereri


Nu poate exista o clauza ORDER BY intr-o subcerere.
Regula este ca poate exista doar o singura clauza ORDER BY pentru o decla- ratie SELECT
si, daca este specificata, trebuie sa fie ultima clauza din co- manda SELECT.

Subcereri ascunse
Subcererile pot fi ascunse (folosite in interiorul unei subcereri) :
Afisati numele, functia si data angajarii pentru angajatii al caror salariu este mai mare ca cel
mai mare salariu din orice departament de vinzari.

104

SELECT ENAME, JOB, HIREDATE, SAL


FROM EMP
WHERE SAL > (SELECT MAX(SAL)
FROM EMP
WHERE DEPTNO = (SELECT DEPTNO
FROM DEPT
WHERE DNAME = 'SALES'));
ENAME
------JONES
SCOTT
KING
FORD

JOB
----MANAGER
ANALYST
PRESIDENT
ANALYST

HIREDATE
---------02-APR-81
09-DEC-82
17-NOV-81
03-DEC-81

SAL
----2975
3000
5000
3000

Limitele de imbricare
Limita nivelelor de imbricare pentru o subcerere este 255.

Reguli de scriere a cererilor

cererea interioara trebuie sa fie inclusa intre paranteze si trebuie sa fie in partea
dreapta a conditiei.
subcererile nu pot avea clauza ORDER BY.
clauza ORDER BY apare la sfirsitul declaratiei SELECT principale.
coloanele multiple din lista din SELECT a cererii interioare trebuie sa fie in aceeasi
ordine ca si coloanele ce apar in conditia din clauza cere- rii principale.De asemenea
mai trebuie sa corespunda si tipul si numarul coloanelor listate.
subcererile sint intotdeauna executate de la cea mai adinca imbricare pina la nivelul
principal de imbricare, daca nu sint subcereri corelate (acestea vor fi discutate mai
tirziu).
pot fi folositi operatorii logici si SQL la fel de bine ca si ANY si ALL.
subcererile pot
o intoarce una sau mai multe linii;
o intoarce una sau mai multe coloane;
o folosi GROUP BY sau functii de grup;
o fi folosite inlantuite cu predicate multiple AND sau OR in aceesi cerere
externa.
o uni tabele.
o recupera dintr-o tabela diferita de cea a cererii exterioare.
o apare in declaratii SELECT, UPDATE, DELETE, INSERT, CREATE
TABLE.
o fi corelate cu o cerere exterioara.
o folosi operatori de multimi.

Subcereri corelate
O subcerere corelata este o subcerere care este executata o data pentru fiecare linie candidat
considerata de cererea principala si care la executie foloseste o valoare dintr-o coloana din
cererea exterioara.Aceasta determina ca subcererea corelata sa fie prelucrata intr-un mod
diferit de subcererea ascunsa obisnuita.

105

O subcerere corelata este identificata prin folosirea unei coloane a cererii exterioare in clauza
predicatului cererii interioare.
Cu o subcerere ascunsa obisnuita, SELECT-ul interior ruleaza primul si se executa o data,
intorcind valori ce vor fi folosite de cererea principala.Pe de alta parte, o subcerere corelata se
executa o data pentru fiecare linie candidat considerata de cererea externa.Cererea interioara
este dirijata de cererea externa.
Pasii de executie ai unei subcereri corelate :
1. Se obtine linia candidat. (obtinuta de cererea exterioara)
2. Se executa cererea interioara folosind valoarea liniei candidat.
3. Se folosesc valorile rezultate din cererea interioara pentru a pastra sau pentru a
inlatura linia candidat.
4. Se repeta pina nu mai ramine nici o linie candidat.
Desi subcererea corelata se executa repetat, o data pentru fiecare linie in cererea principala,
aceasta nu inseamna ca subcererile corelate sint mai putin eficiente ca subcererile necorelate
obisnuite.Se va vorbi despre eficienta mai tirziu in acest capitol.
Putem folosi o subcerere corelata pentru a gasi angajatii care cistiga un salariu mai mare ca
salariul mediu al departamentului lor :
SELECT EMPNO, ENAME, SAL, DEPTNO
FROM EMP E
WHERE SAL > (SELECT AVG(SAL)
FROM EMP
WHERE DEPTNO = E.DEPTNO)
ORDER BY DEPTNO;
EMPNO
------7839
7566
7788
7902
7499
7698

ENAME
------KING
JONES
SCOTT
FORD
ALLEN
BLAKE

SAL
-----5000
2975
3000
3000
1600
2850

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

Putem observa imediat ca este o cerere corelata pentru ca am folosit o co- loana din
SELECT-ul extern in clauza WHERE din SELECT-ul interior.
Observati ca alias-ul este necesar doar pentru a indeparta ambiguitatea pentru numele
coloanelor.
Sa analizam exemplul de mai sus folosind tabela EMP :
Cererea principala
1. Se selecteaza prima linie candidat - Smith din departamentul 20 cistiga 800 .
2. EMP in clauza FROM are alias-ul E care obtine coloana DEPTNO referita in clauza
WHERE a cererii interioare.
106

3. Clauza WHERE compara 800 cu valoarea intoarsa de cererea interioara.

Cererea interioara
4. Calculeaza AVG(SAL) pentru departamentul angajatului.
5. Valoarea departamentului din clauza WHERE este departamentul candidatului
(E.DEPTNO), valoare transmisa cererii interioare din coloana DEPTNO a ce- rerii
exterioare.
6. AVG(SAL) pentru departamentul lui Smith - 20 - este 2175 .
7. Linia candidat nu indeplineste conditia, asa ca este indepartata.
8. Se repeta de la pasul 1 pentru urmatoarea linie candidat; ALLEN din de- partamentul
30 cistiga 1600 .
Selectia liniilor candidat continua cu verificarea conditiei ce apare in re- zultatul cererii.
Observatie : o subcerere corelata este semnalata de un nume de coloana, un nume de tabela
sau un alias de tabela in clauza WHERE, care se refera la va- loarea unei coloane in fiecare
linie candidat din SELECT-ul exterior.De aseme- nea subcererea corelata se executa repetat
pentru fiecare linie candidat in cererea principala.
Comenzile UPDATE pot contine subcereri corelate :
UPDATE EMP E
SET (SAL, COMM) = (SELECT AVG(SAL) * 1.1, AVG(COMM)
FROM EMP
WHERE DEPTNO = E.DEPTNO)
HIREDATE = '11-JUN-85';

Operatori
Cind se folosesc declaratii SELECT ascunse, operatorii logici, precum si ANY si ALL sint
toti valizi.In plus poate fi folosit operatorul EXISTS.

Operatorul EXISTS
Operatorul EXISTS este frecvent folosit cu subcererile corelate.El testeaza daca o valoare
exista (NOT EXISTS specifica daca ceva nu exista).Daca valoarea exista se intoarce TRUE;
daca valoarea nu exista se intoarce FALSE.
Pentru a gasi angajatii ce au cel putin un subordonat, introducem :
SELECT EMPNO, ENAME, JOB, DEPTNO
FROM EMP E
WHERE EXISTS (SELECT EMPNO
FROM EMP
WHERE EMP.MGR = E.EMPNO)
ORDER BY EMPNO;

107

EMPNO
------7566
7698
7782
7788
7839
7902

ENAME
------JONES
BLAKE
CLARK
SCOTT
KING
FORD

JOB
----MANAGER
MANAGER
MANAGER
ANALYST
PRESIDENT
ANALYST

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

Sa gasim toti angajatii al caror departament nu este in tabela DEPT :


SELECT EMPNO, ENAME, DEPTNO
FROM EMP
WHERE NOT EXISTS (SELECT DEPTNO
FROM DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO);

Nu va fi selectata nici o inregistrare.


Alt mod de a gasi departamentul care nu are nici un angajat este :
SELECT DEPTNO, DNAME
FROM DEPT D
WHERE NOT EXISTS (SELECT 1
FROM EMP E
WHERE E.DEPTNO = D.DEPTNO);
DEPTNO
-------40

DNAME
------OPERATIONS

Observati ca SELECT-ul interior nu este necesar sa intoarca o valoare spe- cifica, asa ca
poate fi selectata o cifra.

De ce sa folosim o subcerere corelata ?


Subcererea corelata este un mod de a 'citi' fiecare linie din tabela si de a compara valorile din
fiecare linie cu datele inrudite.Aceasta este folosita oricind o subcerere trebuie sa intoarca un
rezultat diferit sau o multime de rezultate pentru fiecare linie candidat considerata de cererea
principala.Cu alte cuvinte, o subcerere corelata este folosita pentru a raspunde la intre- bari cu
mai multe subpuncte al caror raspuns depinde de valoarea din fiecare linie din cererea
parinte.
SELECT-ul interior este executat normal o data pentru fiecare linie candi- dat.

Considerente de eficienta
Vom examina cele doua tipuri de subcereri.Trebuie mentionat ca subcererea corelata (cu
EXISTS) poate fi cel mai performant mod pentru unele cereri.

108

Performanta va depinde de folosirea indexarilor, de numarul liniilor in- toarse de cereri, de


dimensiunea tabelelor si daca sint necesare tabelele temporare pentru a evalua rezultatele
temporare.Tabelele temporare generate de ORACLE nu sint indexate si acest lucru conduce
la degradarea performantelor pentru subcererile ce folosesc IN, ANY si ALL.
Cele de mai sus sint puncte de vedere generale.Performantele sint discutate mai in detaliu in
alte cursuri.

NOT EXISTS contra NOT IN


Desi intr-o subcerere o operatie NOT IN poate fi la fel de eficienta ca si NOT EXISTS, NOT
EXISTS este mult mai sigur daca subcererea intoarce niste valori NULL, fata de de NOT IN
pentru care conditia se evalueaza la FALSE cind in lista de comparatii sint incluse valori
NULL.
Considerind urmatoarea cerere care gaseste angajatii ce nu au nici un su- bordonat :
SELECT ENAME, JOB
FROM EMP
WHERE EMPNO NOT IN (SELECT MGR
FROM EMP);

Nici o linie nu va fi intoarsa de cererea de mai sus, deoarece coloana MGR contine o valoare
NULL.
Cererea corecta este :
SELECT ENAME, JOB
FROM EMP E
WHERE NOT EXISTS (SELECT MGR
FROM EMP
WHERE MGR = E.EMPNO);
ENAME
------SMITH
ADAMS
ALLEN
WARD
MARTIN
TURNER
JAMES
MILLER

JOB
----CLERK
CLERK
SALESMAN
SALESMAN
SALESMAN
SALESMAN
CLERK
CLERK

Exercitii - Subcereri
Aceste exercitii va vor permite sa scrieti cereri complete folosind SELECT- uri ascunse si
SELECT-uri corelate.

Tema

109

1. Gasiti angajatii care cistiga cell mai mare salariu pentru fiecare tip de functie.Sortati
in ordinea descrescatoare a salariului.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

JOB
----PRESIDENT
ANALYST
ANALYST
MANAGER
SALESMAN
CLERK

ENAME
------KING
SCOTT
FORD
JONES
ALLEN
MILLER

SAL
-----5,000.00
3,000.00
3,000.00
2,975.00
1,600.00
1,300.00

Vor fi 6 inregistarri selectate.

12. Gasiti angajatii care cistiga salariul minim pentru functia lor.Afisati rezultatul in
ordine crescatoare a salariului.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.

ENAME
------SMITH
WARD
MARTIN
CLARK
SCOTT
FORD
KING

JOB
----CLERK
SALESMAN
SALESMAN
MANAGER
ANALYST
ANALYST
PRESIDENT

SAL
----800.00
1,250.00
1,250.00
2,450.00
3,000.00
3,000.00
5,000.00

Vor fi 7 inregistari selectate.

24. Gasiti cei mai recenti angajati din fiecare departament.Ordonati dupa data angajarii.
25.
26.
27.
28.
29.
30.

DEPTNO
-------20
10
30

ENAME
------ADAMS
KING
JAMES

HIREDATE
---------04-JUN-84
09-JUL-84
23-JUL-B4

31. Afisati urmatoarele detalii pentru orice angajat care cistiga un salariu mai mare ca
media pentru departamentul lor.Sortati dupa numarul departa- mentului.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.

ENAME
------KING
JONES
SCOTT
FORD
ALLEN
BLAKE

SALARY
-------5000
2975
3000
3000
1600
2850

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

Vor fi selectate 6 inregistrari.

42. Listati toate departamentele care nu au angajati (folositi o subcerere).


110

43.
44.
45.

DEPTNO
-------40

DNAME
------OPERATIONS

46. Afisati urmatoarele informatii pentru departamentul cu cea mai mare nota de plata
anuala.
47.
48.
49.

DEPTNO
-------20

COMPENSATION
--------------130500

50. Care sint primii trei angajati in functie de salariul cistigat ? Afisati numele lor si
salariul.
51.
52.
53.
54.
55.
56.
57.

ENAME
------SCOTT
KING
FORD

SAL
----3,000.00
5,000.00
3,000.00

58. In ce an s-au angajat cei mai multi in companie ? Afisati anul si numarul angajatilor.
59.
60.
61.

YEAR
-----1984

NUMBER OF EMPS
---------------8

62. Modificati intrebarea 4 pentru a afisa si salariul mediu pentru departa- ment.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.

ENAME
------ALLEN
BLAKE
JONES
FORD
SCOTT
KING

SAL
----1600
2850
2975
3000
3000
5000

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

DEPTAVG
---------1566.66667
1566.66667
2175
2175
2175
2916.66667

Vor fi selectate 6 inregistrari.

73. Scrieti o subcerere care afiseaza o '*' linga linia celui mai recent angajat.Afisati
ENAME, HIREDATE si coloana (maxdate) completata cu '*'.
74.
75.
76.
77.
78.
79.
80.

ENAME
------SMITH
ADAMS
ALLEN
BLAKE

HIREDATE
---------13-JUN-83
04-JUN-84
15-AUG-83
11-JUN-84

MAXDATE
---------

111

81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.

CLARK
FORD
JAMES
JONES
KING
MARTIN
MILLER
SCOTT
TURNER
WARD

14-MAY-84
05-DEC-83
23-JUL-84
31-OCT-83
09-JUL-84
05-DEC-83
21-NOV-83
05-MAR-84
04-JUN-84
26-MAR-84

Vor fi selectate 14 inregistrari.

Subcereri
1.
2.
3.
4.
5.
6.

SELECT JOB, ENAME, SAL


FROM EMP
WHERE (SAL, JOB) IN (SELECT MAX(SAL), JOB
FROM EMP
GROUP BY JOB)
ORDER BY SAL DESC;

7.
8.
9.
10.
11.
12.
13.

SELECT ENAME, JOB, SAL


FROM EMP
WHERE (SAL, JOB) IN (SELECT MIN(SAL), JOB
FROM EMP
GROUP BY JOB)
ORDER BY SAL;

14.
15.
16.
17.
18.
19.
20.

SELECT DEPTNO, ENAME, HIREDATE


FROM EMP
WHERE (HIREDATE, DEPTNO) IN (SELECT MAX(HIREDATE), DEPTNO
FROM EMP
GROUP BY DEPTNO)
ORDER BY HIREDATE;

21.
22.
23.
24.
25.
26.
27.

SELECT ENAME, SAL SALARY, DEPTNO


FROM EMP E
WHERE SAL > (SELECT AVG(SAL)
FROM EMP
WHERE DEPTNO = E.DEPTNO)
ORDER BY DEPTNO;

28.
29.
30.
31.
32.
33.

SELECT DEPTNO, DNAME


FROM DEPT D
WHERE NOT EXISTS (SELECT 'anything'
FROM EMP
WHERE DEPTNO = D.DEPTNO);

34.
35.
36.
37.
38.
39.
40.
41.

DEFINE REM = SAL * 12 + NVL(COMM, 0)


SELECT DEPTNO, SUM(&REM) COMPENSATION
FROM EMP
GROUP BY DEPTNO
HAVING SUM(&REM) = (SELECT MAX(SUM(&REM))
FROM EMP
GROUP BY DEPTNO);

42.
43.
44.

SELECT ENAME, SAL


FROM EMP E

112

45.
46.
47.

WHERE 3 > (SELECT COUNT(*)


FROM EMP
WHERE E.SAL < SAL);

48.
49.
50.
51.
52.
53.
54.
55.

SELECT TO_CHAR(HIREDATE, 'YYYY') YEAR,


COUNT(EMPNO) NUMBER_OF_EMPS
FROM EMP
GROUP BY TO_CHAR(HIREDATE, 'YYYY')
HAVING COUNT(EMPNO) = (SELECT MAX(COUNT(EMPNO))
FROM EMP
GROUP BY TO_CHAR(HIREDATE, 'YYYY'));

56.
57.
58.
59.
60.
61.
62.
63.
64.

SELECT E.ENAME ENAME, E.SAL, E.DEPTNO, AVG(A.SAL) DEPT_AVG


FROM EMP A, EMP E
WHERE E.DEPTNO = A.DEPTNO
AND E.SAL > (SELECT AVG(SAL)
FROM EMP
WHERE DEPTNO = E.DEPTNO)
GROUP BY E.ENAME, E.SAL, E.DEPTNO
ORDER BY AVG(A.SAL);

65.
66.
67.
68.
69.
70.
71.
72.

SELECT ENAME, HIREDATE, '*' MAXDATE


FROM EMP
WHERE HIREDATE = (SELECT MAX(HIREDATE) FROM EMP)
UNION
SELECT ENAME, HIREDATE, ' '
FROM EMP
WHERE HIREDATE <> (SELECT MAX(HIREDATE) FROM EMP)

73.

113

CAPITOLUL 10
SQL*PLUS SI REPORTING
In acest capitol vom prezenta facilitatile pentru SQL*Plus.In particular, capitolul prezinta
modul in care comenzile SQL*Plus pot fi folosite pentru a formata rezultatele cererilor in
rapoarte simple.

Comenzi SQL si SQL*Plus


SQL*Plus este un mediu in care pot apare doua tipuri de comenzi :
1. Comenzi SQL (cum ar fi SELECT).
2. Comenzi SQL*Plus (cum ar fi SAVE).
Comenzile SQL*Plus difera de comenzile SQL in urmatoarele moduri :
1. Ele nu sint conectate cu nici o declaratie particulara SELECT.
2. Ele se introduc pe o singura linie.Oricum, un caracter de continuare, li- niuta de unire,
poate fi folosit daca comanda este prea lunga pentru a o introduce pe o singura linie.
Comenzile SQL*Plus pot fi folosite pentru a influenta prezentarea datelor furnizate de
declaratiile SELECT, si din acest motiv sint folositoare pentru producerea rapoartelor, la fel
de bine ca si pentru contolul mediului si pentru identificatorul de fisier.
Comenzile SQL*Plus sint introduse la promter-ul SQL pe o singura linie, dar ele nu deschid
un buffer.Urmatoarele sint citeva comenzi suplimentare.
RUNFORM nume_fisier
ruleaza o aplicatie a Oracle Forms din interiorul sesiunii tale SQL*Plus.
Spool nume_fisier
scrie toate comenzile ulterioare si/sau le scrie in fisierul cu numele nume_fisier.
Fisierului de spool i se asociaza extensia .LIS (pe unele sisteme extensia .LST).
SPO[OL] OFF | OUT
OFF inchide fisierul de spool si OUT opreste procesul de spool-ing si trimite fisierul
de spool la imprimanta.
DESC[RIBE] nume_de_tabela
afiseaza structura tabelei din baza de date.
HELP
invoca help-ul intern din Oracle.
$0 | S comanda
HOST comanda
invoca o comanda sistem din interiorul SQL*Plus ($ este specific pentru VAX).
CONN[ECT] identificator_utilizator parola
produce logarea la alt utilizator Oracle din interiorul login-ului curent.
PROMPT text
afiseaza textul cind se ruleaza un fisier de comenzi.

114

Comenzi SET
Comenzile SET controleaza 'mediul' in care ruleaza in mod curent SQL*Plus. In general,
comenzile asociaza o valoare unei variabile de sistem sau o trece pe ON sau OFF.Aceste
comenzi pot fi folosite in mod implicit pentru fiecare sesiune prin includerea lor intr-un fisier
numit LOGIN.SQL, care este citit de fiecare data cind se ruleaza SQL*Plus.Daca o comanda
SET aparuta in timpul se- siunii modifica valoarea implicita, aceasta va fi valabila doar
pentru acea sesiune.Iesirea (EXIT) din SQL*Plus va reseta variabilele de sistem la valo- rile
lor implicite.
Comenzile SQL*Plus pot fi prescurtate.
Cuvintele subliniate reprezinta starile implicite pentru comenzile de mai jos.
ECHO {OFF ON}
ON face ca SQL*Plus sa afiseze comenzile asa cum sint ele executate dintr-un fisier
de comenzi.OFF suprima acest lucru.
FEED[BACK] {6n OFF ON}
n face ca SQL*Plus sa afiseze numarul inre- gistrarilor selectate intr-o cerere cind sint
selectate cel putin n inregistrari sau mai multe.ON sau OFF face ca aceasta sa fie sau
nu afisata. Trecerea feedback-ului pe ON face ca n sa fie setat la 1.Setarea feed- backului la 0 este echivalent cu trecerea sa pe OFF.
HEA[DING] {OFF ON}
ON face ca SQL*Plus sa afiseze in rapoarte capetele de coloane.OFF suprima
capetele de coloane.
LIN[ESIZE] {80n}
seteaza numarul de caractere pe care SQL*Plus le va afisa pe o linie si de asemenea
con- troleaza centrarea si aliniamentul din dreapta a textului.Valoarea maxima pentru
n este 500.
NEWP[AGE] {1n}
seteaza numarul liniilor goale ce vor fi tiparite intre titlul de jos de la fiecare pagina si
titlul de sus al paginii urmatoa- re.Valoarea 0 face ca SQL*Plus sa stearga ecranul pe
majoritatea terminalelor.
NUM[FORMAT] text
seteaza formatul implicit pentru afisarea numarului articolelor de date.Text trebuie sa
fie un format de numar.Vedeti optiunea COLUMN, clauza FORMAT pentru formatul
nu- merelor descris sub titlul 'COLUMN - Optiuni', mai tirziu in acest subcapitol.
NUM[WIDTH] {10n}
seteaza latimea implicita pentru afisarea valorilor numerice.
PAGES[IZE] {24n}
seteaza numarul liniilor pe o pagina.Pentru rapoarte tiparite pe hirtie de lungime de 11
inch, valoarea 54 (plus valoarea NEWPAGE 6) lasa margini de 1 inch deasupra si
dede- subtul paginii.
VER[IFY] {OFF / ON text}
ON face ca SQL*Plus sa afiseze textul unei comenzi inainte si dupa substituirea variabilei cu valoarea sa.OFF suprima acest lucru.
TIM[ING] {OFF / ON}
ON face ca SQL*Plus sa dea statistici de timp la fiecare declaratie SQL ce este
rulata.OFF suprima acest lucru pentru fiecare comanda SQL.
SPA[CE] {1n}

115

seteaza numarul de spatii dintre coloane pentru o afisare de tabela.Valoarea maxima


pentru n este 10.
TERM[OUT] {OFF ON}
OFF suprima afisarea iesirii generate de comenzi executate dintr-un fisier, asa ca
iesirea poate fi prelucrata fara sa apara pe ecran.ON permite ca iesirea sa fie afisata.
SQLCASE {MIXED / LOWER / UPPER}
LOWER / UPPER convertesc comenzile SQL chiar inainte de executie.Tot textul din
interi- orul comenzii este convertit.MIXED lasa tex- tul nemodificat.
Pentru a gasi valoarea pentru o variabila SET folosim comanda SHOW. De exemplu, pentru a
gasi dimensiunea paginii (pagesize), introducem :
SHOW PAGES[IZE]

Pentru a vedea valorile pentru toate variabilele SET, introducem :


SHOW ALL

|---------------------------------------------------------------------|
|
|
|
RAPOARTE SQL*PLUS
|
|
|
|
Titlu
|
|
|
|
|
|
|
|
|------------------------------|------------------------------|
|
|
|
|
|
|
|
|
Thu April 10
|
Page 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
COMPANY REPORT
|
|
|
|
|
|
|
|
|
|
|
|
----------------------------|
|
|
|
----------------------------|
|
|
|
----------------------------|
|
|
|
=====
|
|
|
|
|
|
|
|
|
|
|
|
----------------------------|
|
|
|
----------------------------|
|
|
|
=====
|
|
|
|
|
|
|
|
|
|
|
|
----------------------------|
|
|
|
----------------------------|
|
|
|
----------------------------|
|
|
|
----------------------------|
|
|
|
----------------------------|
|
|
|
|
=====
|
|
|
|
|
=====
|
|
|
|
|
|
|
|
|
|
|
Confidential
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

116

|
|------------------|---------------------------------|--------|
|
|
|
|
|
|
|
|
|
|
Formate de coloana
Calcule
|
|
|
|
|
|---------------------------------------------------------------------|

COLUMN - Optiuni
Comanda COLUMN stabileste optiunile de afisare pentru o coloana.Formatul este :
COL[UMN] nume_coloana / alias lista_optiuni

Observatii asupra optiunilor pentru COLUMN :


1. nume_coloana trebuie sa se refere la un alias de coloana, daca un alias de coloana este
folosit in clauza SELECT.
2. Optiunile pot apare in orice ordine.
3. O data ce apare o declaratie de coloana, ea ramine activa tot timpul cit sesiunea
SQL*Plus ramine deschisa.Ea continua sa fie setata in timp ce sint afisate alte tabele
(fara aceasta coloana).
4. Optiunile pentru COLUMN pot fi sterse in timpul unei sesiuni.
5. Pentru a gasi setarea optiunilor curente pentru o coloana, introducem :
COL nume_coloana / alias

Alte citeva optiuni pentru COLUMN sint :


WRAP
permite specificarea catre SQL*Plus ca ori de cite ori
TRUNC
continutul actual al unei coloane depaseste latimea specifi- cata, informatia aditionala
este impachetata (WRAP) prin rotunjire in linia urmatoare sau trunchiata
(TRUNC).WRAP este valoarea implicita.
WORD_WRAPPED
muta un cuvint de intrare pe linia urmatoare, in loc sa-l desparta pe doua linii.Un
cuvint nu va fi despartit pe doua linii daca nu este mai mare ca latimea coloanei.
HEADING
specifica un cap pentru o coloana.
NULL sir
seteaza NULL-uri in coloana la sirul specificat.
PRINT
NOPRINT
coloana va fi afisata / nu va fi afisata pe rapotrul de iesire.
NEW_VALUE var

117

Valoarea coloanei este inscrisa in variabila specificata in momentul in care coloana


este selectata (SELECT).

Optiuni de format in comanda COLUMN


Formatul de afisare a coloanelor
An

alfanumeric, de lungime n

pozitie numerica

999999

1234

forteaza zerouri principale

099999

001234

floating dollar

$999999

punct zecimal

999999.99

1234.00

virgula

999,999

1,234

MI

semnul minus la dreapta

999999MI

1234-

PR

numere negative intre paranteze 999999PR

EEEE

notatie stiintifica

99.999EEEE

multiplicare cu 10 la n
(n = numar de 9 dupa V)

9999V99

valorile zero devin blank-uri

B9999.99

$1234

<1234>
1.234E+03
123400

NOTA:
1. Formatul 999999 - afiseaza blank-uri pentru zerouri!
2. Formatul B9999.99 - daca punctul zecimal e inclus in formatul de afi- sare, formatul
B este cerut pentru a face valori- le nule blank-uri.
3. Formatul B999999 - Formatul B nu are efect pentru ca 999999 fara 'B' descrie
zerourile ca blank-uri.

MESAJE DE EROARE
###
%

...valoare prea mare pentru format


...tip gresit al valorii pentru format

Exemple de format al coloanelor


COLUMN
COLUMN
COLUMN
COLUMN
COLUMN
Comm'
COLUMN

DEPTNO FORMAT 099 HEADING 'Dept.'


JOB FORMAT A9 HEADING 'Job' JUSTIFY RIGHT
EMPNO FORMAT 9999 HEADING 'Empl|No'
SAL FORMAT 99,999.99 HEADING 'Monthly|Salary'
COMM FORMAT 99,990.99 HEADING 'Y-T-D|Commission' - NULL 'No
REM FORMAT 999,999.99 HEADING 'Total Rem.'

SELECT DEPTNO,
JOB,
EMPNO,
SAL,

118

COMM,
SAL*12+NVL(COMM,0) REM
FROM EMP;

Rezultatul cererii afiseaza caracteristici ale optiunilor de formatare a coloanelor. Fiecare


coloana are un titlu diferit. Justificarea titlului a fost schimbata din cea implicita, si in unele
cazuri separata peste un numar de linii, folosind o bara verticala (|), Optiunea NULL a fost
folo- sita sa forteze un sir de caractere sa fie afisat cand un null ar trebui in mod normal sa
apara.
Clauza SELECT poate contine alias-uri de coloane, coloane cu un prefix de tabela, expresii si
siruri literale care determina numele coloanei speci- ficat in comanda COLUMN a
SQL*PLUS.
Daca aceasta este lista
de articole a SELECT-ului
-------------------------

Folositi acest nume de coloana


in comanda COLUMN
------------------------------

sal

sal

emp.sal

sal

e.sal

sal

sal*12+nvl(comm,0)

sal*12+nvl(comm,0)

sal*12 annsal

annsal

sysdate

sysdate

empno||'-'||ename

empno||'-'||ename

To_char(Hiredate,'ddth
MONYYYY')

To_char(Hiredate,'ddth MONYYYY')

To_char(sysdate,'Day
Mon YY')Today

Today

Comenzile TTITLE si BTITLE


Comenzile TTITLE si BTITLE sunt folosite pentru a produce titluri pe o pagina.
Comanda
-------

Descriere
---------

TTITLE 'sir de caractere'

tipareste data curenta in coltul din


stanga sus al fiecarei pagini, numarul
paginii in coltul din dreapta sus si

centreaza titlul pe linia de dedesupt.


BTITLE 'sir de caractere'

tipareste textul centrat in partea de

jos
a fiecarei pagini. In ambele cazuri un
caracter '|' va face ca urmatorul text sa

119

fie centrat pe linia urmatoare.


TTITLE
BTITLE

afiseaza TTITLE-ul sau BTITLE-ul curent

TTITLE OFF
anteBTITLE OFF
COLUMN
COLUMN
COLUMN
COLUMN
COLUMN
Comm'
COLUMN

anuleaza afisarea unui titlu definit


rior sau a unei note de subsol.

DEPTNO FORMAT 099 HEADING 'Dept.'


JOB FORMAT A9 HEADING 'Job' JUSTIFY RIGHT
EMPNO FORMAT 9999 HEADING 'Empl|No'
SAL FORMAT 99,999.99 HEADING 'Monthly|Salary'
COMM FORMAT 99,990.99 HEADING 'Y-T-D|Commission' - NULL 'No
REM FORMAT 999,999.99 HEADING 'Total Rem.'

TTILTE 'COMPANY REPORT|Produced by Personnel Dept'


BTITLE 'Company Confidential'
SELECT DEPTNO, JOB, EMPNO, SAL, COMM, SAL*12+NVL(COMM,0) REM
FROM EMP;

Comenzile TTITLE si BTITLE pot include un numar de clauze, facand posibil ca aparitia
titlului sa fie specificata mai detaliat.
TTI[TLE] [printspec OFF ON]
contine

printspec defineste titlul si poate


mai multe clauze.

BTI[TLE] [printspec OFF ON]

printspec defineste not de subsol si poate


contine mai multe clauze.

Clauze in Printspec
COL n

sare tiparirea pozitiei n a liniei curente


(inapoi daca coloana a fost trecuta).

SKIP n

sare de la startul unei noi linii de n

ori.
Daca n este omis, sare o linie; daca n
este
0, inapoi la inceputul liniei curente.
TAB n

LEFT,CENTER and
linia
RIGHT
aces-

sare inainte n pozitii de tiparit (inapoi


daca n este negativ).
aliniere stanga, centru sau dreapta pe
curenta. Articolele de date ce urmeaza
tei clauze sunt aliniate ca un grup, pana

la
sfarsitul comenzii TTILTE sau pana la
urmatorul LEFT, CENTER, RIGHT sau COLUMN.(CENTER
si
RIGHT folosesc valoarea lui SET LINESIZE
pentru a calcula pozitiile articolelor de
da-

120

te).
FORMAT
care o

defineste formatul articolelor de date


urmeaza, pana la urmatoarea clauza FORMAT

sau
pana la sfarsitul comenzii.Specificarea
formatului este la fel cu cea a clauzei
FORMAT
a comenzii COLUMN. O singura specificare
de
format poate fi efectiva la un moment dat.
Daca este al unui tip de date gresit
pentru
un articol particular, nu are efect asupra
acelui articol particular.
Daca nu este efectiva nici o clauza FORMAT
potrivita, valorile numerice sunt tiparite
in
acord cu formatul SET NUMFORMAT, sau daca
SET NUMFORMAT nu a fost folosit, in acord
cu
formatul implicit. Valorile datei sunt
tiparite in formatul implicit.
SQL.PNO

Variabila sistem pentru numarul paginii

curente a raportului. Va puteti referi la


valoarea unei variabile sistem dandu-i
prefixul
SQL. De exemplu, pentru a folosi variabila
PNO scrieti:
TTITLE RIGHT 'page' SQL.PNO
Aceasta va produce 'page 1' la marginea
din
dreapta a liniei daca 1 este pagina
curenta.

Eliminarea valorilor duplicate si spargerea unui raport in sectiuni


Liniile unui raport pot fi sparte in sectiuni, folosind comanda BREAK. Prin spargerea unei
coloane, afisarea valorilor duplicate este eliminata. Puteti deasemenea sa lasati linii goale sau
sa incepeti o noua pagina intre sectiuni. Pana cand va aparea o 'spartura' , valorile coloanelor
se schimba de fiecare data, trebuie sa va reamintiti sa 'ORDER BY' coloana declaratia
SELECT sau raportul dumneavoastra va fi rupt in sectiuni de neinteles.
Poate fi o singura comanda BREAK activa la un moment dat; prin urmare, daca cereti breakuri multiple ele trebuie sa fie specificate ca o singura comanda BREAK. Trebuie sa listati
coloanele sparte in ordinea importantei, 'sparturile' majore mai intii.

Optiuni BREAK
Break-urile pot fi active la :

121

Column
Row
Page
Report

BREAK ON [column/alias ROW][SKIP n DUP PAGE] ON...[ON REPORT]

Un BREAK ON REPORT va permite calcule finale sumare. La orice "break", ur- matoarele
optiuni pot fi specificate:
Optiune
-------

Descriere
---------

PAGE
coloana

renunta la o pagina cand o valoare in


se schimba.

SKIP n

sare n linii cand valoarea se schimba.

DUP[LICATE]

duplica valorile. Implicit este:


NODUP[LICATE].

Exemple:
BREAK ON REPORT ON DEPTNO PAGE ON JOB SKIP 2
BREAK ON REPORT ON DEPTNO PAGE ON JOB DUP

Pentru a curata break-urile emiteti comanda:


CLEAR BREAKS

Pentru a tipari break-urile curente emiteti comanda:


BREAK

Urmatorul exemplu ilustreaza folosirea BREAK-urilor:


COLUMN
COLUMN
COLUMN
COLUMN
COLUMN
Comm'
COLUMN
TTILTE
BTITLE

DEPTNO FORMAT 099 HEADING 'Dept.'


JOB FORMAT A9 HEADING 'Job' JUSTIFY RIGHT
EMPNO FORMAT 9999 HEADING 'Empl|No'
SAL FORMAT 99,999.99 HEADING 'Monthly|Salary'
COMM FORMAT 99,990.99 HEADING 'Y-T-D|Commission' - NULL 'No
REM FORMAT 999,999.99 HEADING 'Total Rem.'
'COMPANY REPORT|Produced by Personnel Dept'
'Company Confidential'

BREAK ON DEPTNO SKIP 1 ON JOB ON REPORT


SELECT
DEPTNO, JOB, EMPNO, SAL, COMM, SAL*12+NVL(COMM,0) REM
FROM
EMP
ORDER BY DEPTNO,JOB;

122

Calcule Sumare
Comanda COMPUTE executa calcule pe break-uri stabilite de comanda BREAK.
COMPUTE clauza(e) OF coloana(e) ON break(uri)
Comanda
-------

Descriere
---------

OF

specifica coloana sau expresia a carei valoare

va
fi calculata.
ON
tabe-

specifica articolul de date sau elementul de


la care sa fie folosit ca break.

Clauza
------

Calcule
-------

Aplicate pe tipul de coloana


----------------------------

AVG

valoare medie

numar

COU[NT]

contorizeaza valori
nenule

toate tipurile

MAX[IMUM]

valoare maxima

numar, caracter

MIN[IMUM]

valoare minima

numar, caracter

NUM[BER]

contorizare a liniilor

toate tipurile

STD

deviatia standard

numar

SUM

suma valorilor nenule

numar

VAR[IANCE]

variatie

numar

Pot fi multe comenzi COMPUTE, cu toate ca adesea este mai usor sa specificati toate
calculele cerute intr-o singura comanda.
De exemplu:
COMPUTE SUM AVG OF SAL COMM ON DEPTNO REPORT

va calcula salariile medii si totale si comisionul figurate in sectiunea DEPTNO si la sfarsitul


REPORT-ului.

Fisierul de comenzi SQL*PLUS


1. compunere SELECT declaratie
2. SAVE nume fisier
3. ED nume fisier
4.
5.

SET

123

6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.

COL
TTITLE

SET UP
SQL*PLUS
ENVIRONMENT

BTITLE
BREAK

SELECT ...
SQL
/

TTITLE OFF
COL DEPTNO CLEAR
COL EMPNO CLEAR

RESET
SQL*Plus
ENVIRONMENT

Etc.

30. CTRL Z VAX SPECIFIC


31. EX[IT] or QUIT
32. START nume fisier

CAPITOLUL 10 Exercitiu - Raport sub


forma de tabel
1. Produce un raport care arata asemanator cu urmatorul. Asigurati-va la formatul
coloanelor de date, la capul de tabel, si la specificatia ti- tlului paginii si notei de
subsol.
2. Adaugati o comanda BREAK la script-ul SQL astfel ca raportul dumneavoas- tra sa
sara o linie la sfarsitul detaliilor fiecarui departament, si e- limina duplicatele numelor
de slujbe.

Capitolul 10 Solutie
SET
SET
SET
SET

ECHO OFF
PAGESIZE 24
FEEDBACK OFF
LINESIZE 78

COL A
COL B
COL C
COL D
COL E
COL F
COL G
COL H
BREAK

FORMAT A10 HEADING 'Department'


FORMAT A9 HEADING 'Job'
FORMAT 9999 HEADING 'Emp.|No.'
FORMAT A8 HEADING 'Name'
FORMAT A5 HEADING 'Hire|Date'
FORMAT B99,999.99 HEADING 'Monthly|Salary'
FORMAT 9,990.99 HEADING 'Annual|Comm'
FORMAT 999,999.99 HEADING 'Total'
ON A SKIP 1 ON B

124

TTITLE 'EMPLOYEE REPORT'


BTITLE 'CONFIDENTIAL'
SELECT

DNAME A,
JOB B,
EMPNO C,
ENAME D,
TO_CHAR(HIREDATE,'MM/YY') E,
SAL F,
COMM G,
SAL*12+NVL(COMM,0) H
FROM EMP E,DEPT D
WHERE E.DEPTNO = D.DEPTNO
ORDER BY DNAME,JOB
/
CLEAR COLUMNS
TTITLE OFF
BTITLE OFF
SET FEDBACK ON
SET PAGES 24
CLEAR BREAKS
,/pre>

125

CAPITOLUL 11
TRAVERSAREA ARBORILOR
Acest capitol detaliaza recuperarea datelor bazate pe o relatie ierarhi- ca naturala intre doua
linii ale tabelei.

Traversarea arborilor
Tabela EMP are o structura arborescenta reprezentand linia de raport a conducerii.

Parcurgerea arborelui
KING
EMPNO=7839
|
--------------------------------|
|
|
MGR=7839
CLARK
JONES
BLAKE
|
|
|
|
-----------------------------|
|
|
|
|
|
|
|
MILLER SCOTT FORD
ALLEN WARD MARTIN TURNER JAMES
|
|
|
|
ADAMS SMITH

O baza de date relationala nu contine inregistrarile intr-un mod ierarhic. Oricum, unde exista
o legatura ierarhica intre liniile unei singure tabele, este un proces numit 'parcurgere de
arbore' care face posibil ca ierarhia sa fie construita.Ierarhia poate fi creata privind la legatura
dintre valorile echivalente in coloanele EMPNO si MGR(Aceasta legatura a fost deja exploatata cu join-ul unei tabele cu ea insesi). Numarul MGR al unui angajat este EMNO-ul sefului
sau.
Cand este realizata o parcurgere de arbore, nu va asteptati sa vedeti rezultatul cererii
asemanator cu figura afisata mai sus. Numerele LEVEL (de nivel) sunt stabilite cand apare
parcurgerea arborelui si reprezinta cat de indepartate sunt nodurile (liniile) de radacina (nodul
de start).
Pentru a construi un arbore de traversare din tabela EMP, introduceti:
SELECT LEVEL, DEPTNO, ENAME, JOB, SAL
FROM EMP
CONNECT BY PRIOR EMPNO = MGR
START WITH MGR IS NULL;
Comanda
Descriere
--------------SELECT
LEVEL

Clauza SELECT standard, cu pseudo-coloana


care afiseaza cat de departe este fiecare

nod
de nodul de start.

126

FROM
WHERE
timpul

Puteti sa SELECT FROM o singura tabela.


Limiteaza liniile care sunt vizitate in
parcurgerii.

CONNECT BY
intre

Specifica coloanele unde exista legatura


linii. Aceasta clauza este ceruta pentru o
parcurgere de arbore.

PRIOR
arbo-

Stabileste directia in care este parcurs


rele. Daca PRIOR apare inainte de MGR,

atunci
valorile in coloana MGR sunt vizitate
primele,
apoi sunt gasite valorile echivalente din
EMPNO, care este in susul arborelui. Daca
PRIOR
apare inainte de EMPNO atunci arborele este
in
jos.
START WITH

Specifica unde sa inceapa arborele. Nu poate


incepe la un nivel(LEVEL). Aceasta clauza
este optionala chiar cand este ceruta o parcurgere de arbore.

ORDER BY

Apare la sfarsit de obicei.

In exemplul de mai sus, structura ierarhica a organizatiei este reflectata in parcurgerea


arborelui. Structura raportata conducere/angajati poate fi identificata cu claritate.
Puteti folosi clauza ORDER BY pentru a sorta liniile returnate.Urmatoarea comanda este
perfect legitima:
SELECT LEVEL, DEPTNO, ENAME, JOB, SAL
FROM EMP
CONNECT BY PRIOR EMPNO = MGR
START WITH MGR IS NULL
ORDER BY DEPTNO;

Oricum, este recomandat sa nu folositi clauza ORDER BY la parcurgerea arbo- relui pentru
ca ordonarea implicita a arborelui poate fi distrusa. In exemplul de mai jos, ordinea in care
liniile lui SCOTT, ADAMS, FORD si SMITH sunt afisate s-a schimbat, si ADAMS pare sa
se raporteze la FORD cand SCOTT este de fapt seful sau. Iesirea (rezultatul) nu reflecta
ierarhia "adevarata".
SELECT LEVEL, DEPTNO, ENAME, JOB, SAL
FROM EMP
CONNECT BY PRIOR EMPNO = MGR START WITH MGR IS NULL
ORDER BY DEPTNO;

127

Parcurgerea arborilor
SELECT ENAME, LEVEL, JOB
FROM EMP
CONNECT BY PRIOR EMPNO = MGR
START WITH MGR IS NULL
EXCLUDERI :
WHERE ENAME!='SCOTT'

JONES
|
---------------------------|
|
SCOTT (se sterge)
FORD
|
|
ADAMS
SMITH
CONNECT BY PRIOR EMPNO=MGR
AND ENAME!='SCOTT'
JONES
|
---------------------------|
|
SCOTT (se sterge)
FORD
|
|
ADAMS (se sterge)
SMITH

TERMINOLOGIE
Sunt cativa termeni mai degraba neobisnuiti cand parcurgeti arborele. Nu este nevoie sa-i
amintim pe toti, decat pentru informatie:
NODE

acelasi lucru cu o linie

ROOT

un nod care nu este in proprietatea nimanui

PARENT
inferior

un nod care are alte noduri la un nivel

CHILD

un nod care are un PARENT

TERMINAL NODE sau LEAF

un nod fara fii

BRANCH

un nod cu fii si nepoti

Chirurgia arborelui
Clauzele WHERE si CONNECT pot fi folosite pentru a curata arborele, care controleaza ce
noduri sunt afisate. Daca clauza WHERE este folosita pentru a elimina un nod, atunci doar
acel nod este eliminat. Daca restrictia apare in clauza CONNECT BY atunci intreaga ramura
este eliminata.
In exemplul urmator, numai linia SCOTT este eliminata, fiii sai sunt inca procesati.

128

BREAK ON DEPTNO SKIP 1


SELECT LEVEL, DEPTNO, ENAME, JOB, SAL
FROM EMP WHERE ENAME != 'SCOTT'
CONNECT BY PRIOR EMPNO = MGR
START WITH MGR IS NULL;

In exemplul de mai jos, intreaga ramura SCOTT a fost eliminata:


SELECT LEVEL, DEPTNO, ENAME, JOB, SAL
FROM EMP
CONNECT BY PRIOR EMPNO = MGR AND ENAME != 'SCOTT'
START WITH MGR IS NULL;

Notati ca de aceasta data ambele linii, parinte (SCOTT) si fiu (ADAMS), au fost excluse.

Alte utilizari ale parcurgerii arborilor


Organizarea tabelelor nu este singura aplicatie a unei cereri structura- te pe arbore. Clauza
CONNECT BY poate fi folosita de asemenea in:

nota de plata a aplicatiilor materiale, sa produca explozii sau implozii partilor


indentate.
bilantul aplicatiilor pentru scopuri de consolidare.

129

CAPITOLUL 12
Crearea si Definirea de structuri tabelare
In acest capitol, discutam aspectele logice ale tabelelor si coloanelor si commenzile necesare
pentru a construi tabele cu Constrangeri de Integri- tate. Acesta este primul din doua capitole
care acopera subsetul comenzilor SQL cunoscut ca Limbajul de Definire a Datelor(DDL).

Structuri de date ORACLE


In acest curs vom discuta aspectele logice de creare a tabelelor.Consi- deratiile fizice sunt
acoperite in celelalte cursuri.Desi tabelele pot fi create fara a da informatii de asezare fizice,
ar trebui notat ca un utili- zator ORACLE trebuie sa fi primit privilegiul de CREATE TABLE
de catre admi- nistratorul bazei de date si sa aiba alocat ceva spatiu de tabela pentru a crea
tabele.
In general, structurile de date ORACLE pot fi rezumate dupa cum urmeaza.

Tabelele pot fi create oricand, chiar cu utilizatori folosind baza de date.


Nu este necesar sa specificati dimensiunea nici unei tabele. Aceasta este definita
ultima prin cat spatiu a fost alocat bazei de date ca un intreg. Oricum, este important
sa estimati cat de mult spatiu va utiliza o tabela.
Structurile pot fi modificate online.
Tabelele pot capata automat mai mult spatiu daca dimensiunea i- nitiala este umpluta.

Limbajul de Definire a Datelor (LDD)


LDD este un subset al comenzilor SQL folosit pentru a crea, modifica sau muta
structurile bazei de date ORACLE, si deasemenea sa inregistreze informatii in
Dictionarul de Date (acesta este discutat mai tarziu).

Denumirea unei tabele


Numele pe care-l alegeti pentru o tabela trebuie sa urmeze regulile standard pentru
numirea unui obiect al unei baze de date ORACLE.
1. Numele trebuie sa inceapa cu o litera, A-Z sau a-z.
2. Poate contine litere, numerale si caracterele speciale underscore (_).
Caracterele $ si # sunt deasemenea legale, dar folosirea lor este descurajata.
3. Numele este acelasi indiferent daca sunt folosite litere mari sau mici, de
exemplu, EMP, emp, si eMp sunt toate aceeasi tabela.
4. Poate fi de maxim 30 caractere in lungime.
5. Numele nu trebuie sa duplice numele altui obiect din contul dumneavoastra.
6. Numele nu trebuie sa fie un cuvant rezervat SQL.
NUME
---EMP85

VALID ?
------da

130

85EMP

nu; nu incepe cu o litera

FIXED_ASSETS

da

FIXED ASSETS

nu; contine un blank

UP DATE

nu; cuvant rezervat SQL

Ar trebui sa folositi nume de descriere pentru tabele si alte obiecte ale bazei de date. Folositi
acelasi nume sa descrie aceeasi entitate in doua tabele diferite. De exemplu, coloana cu
numarul departamentului este numita DEPTNO in ambele EMP si DEPT.

Crearea unei tabele


Creati o noua tabela folosind comanda CREATE TABLE. Una dintre cele mai simple forme
a acestei comenzi este cand informatia de baza pentru fiecare coloana este definita impreuna
cu tipul ei de data si dimensiunea.
Sintaxa: CREATE TABLE nume tabela
(nume coloana tip(dimensiune),
nume coloana tip(dimensiune),
...);
Exemplu: CREATE TABLE DEPT
(DEPTNO NUMBER(2),
DNAME
VARCHAR2(12),
LOC
VARCHAR2(12));

Numele coloanelor intr-o tabela trebuie sa fie unice.

Tipurile coloanelor
Cand creati o tabela trebuie sa specificati fiecare tip de data al co- loanei. Tabela de mai jos
arata cele mai importante tipuri de date.
Tipul de data poate fi urmat de unul sau mai multe numere in paranteze care dau informatii
despre latimea coloanei. Latimea coloanei determina la- timea maxima pe care valorile in
coloana pot s-o aiba. VARCHAR2 trebuie sa aiba o dimensiune, dar cele implicite sunt
disponibile.
Tabela de mai jos arata tipurile de date principale in ORACLE7.
Tip de date
----------VARCHAR2(w)
Lungi-

Descriere
--------Sir de caractere de lungime maxim w.
mea maxima este de 2000 caractere.

CHAR(w)

Sir de lungime fixa w. Lungimea implicita


este 1. Lungimea maxima este 255.

NUMBER

Numere in virgula mobila cu precizie : 38


de cifre semnificative.

131

NUMBER(w)

Numere intregi de precizie w.

NUMBER(w,s)

Numere cu precizia w si scala s. Precizia


reprezinta numarul maxim de cifre

semnificative permise care nu pot depasi 38.


Scala
este numarul de pozitii zecimale
inregistrate in dreapta punctului.
DATE
inainte

Valorile datei din 1 Ianuarie 4712


de Hristos pana in 31 Decembrie 4712 dupa
Hristos. Informatia de timp este

deasemenea
stocata.
LONG

Sir de caractere de lungime variabila de


lungime 2 Gb, sau 2 la puterea 31 minus

1.
Este permisa o singura coloana de tipul
LONG
pe tabela.
RAW si
LONG RAW

Echivalent cu VARCHAR2 si respectiv LONG,


dar folosit pentru a stoca date binare ca
imagini grafice sau sunete digitizate.

NOTE:

Tipul de date VARCHAR2 al Oracle7 este sinonim cu versiunea 6 a tipu- rilor de date
'VARCHAR' si 'CHAR'.
ORACLE foloseste semantica prin comparatie non-padded daca o valoare
VARCHAR2 este folosita intr-o comparatie(vezi Capitolul 2 pentru de- talii).
Daca o valoare scrisa intr-o coloana depaseste scala coloanei, atunci va apare o
rotunjire.

Tabela de mai jos arata exemple de specificatii de coloane:


NUMBER(4)
cifre.

Poate contine toate numerele pana la 4

NUMBER(8,3)

Poate contine pana la 8 cifre, dintre care 3


pot fi in dreapta punctului zecimal.

VARCHAR2(1000)

Valorile pot contine pana la 1000 caractere.

CHAR(80)

Siruri de caractere de lungime fixa egala cu


80. Valorile mai scurte sunt inlocuite cu
blank-uri.

Crearea tabelei EMP


Tabela noastra demonstrativa, EMP, ar fi putut fi creata de o comanda CREATE TABLE ca
mai jos:
132

CREATE TABLE
(EMPNO
ENAME
JOB
MGR
HIREDATE
SAL
COMM
DEPTNO

EMP
NUMBER(4) NOT NULL,
VARCHAR2(10),
VARCHAR2(10),
NUMBER(4),
DATE,
NUMBER (7,2),
NUMBER (7,2),
NUMBER (2) NOT NULL);

Comanda DESCRIBE a SQL*PLUS-ului poate fi folosita pentru a lista detal ale coloanelor
create intr-o tabela:
DESCRIBE EMP

Constrangerea NOT NULL


In exemplul de mai sus, veti observa ca definitiile pentru coloanele EMPNO si DEPTNO sunt
urmate de NOT NULL. Aceasta ne asigura ca valoril nule sunt permise pentru aceste coloane,
de cand aceste coloane servesc ca chei pentru operatii pe aceasta tabela. Coloanele fara
constrangerea NOT NULL permit valori nule.
NOT NULL este una dintre constrangerile de integritate care pot fi defi- nite.

OPTIUNEA DEFAULT
Unei coloane ii poate fi data o valoare implicita prin optiunea DEFAULT. Aceasta previne
aparitia de null-uri (sau erori, daca NOT NULL este specifi- cata) daca o linie este inserata
fara o valoare din coloana.Valorile implici- te pot fi literali, o expresie, dar nu numele altei
coloane. Functii ca SYSDATE si USER sunt valide.
De exemplu:
HIREDATE DATE DEFAULT SYSDATE,
SAL NUMBER (7,2) DEFAULT 0

Constrangeri de integritate
Oracle permite constrangerilor de integritate sa fie definite pentru ta- bele si coloanelor sa
forteze reguli sigure, inauntrul unei tabele sau intre tabele.
Constrangerile sunt folosite:

de serverul Oracle7 sa forteze reguli la nivelul tabelei oricand este inserata o linie,
actualizata sau stearsa din acea tabela. Constrange- rea trebuie sa fie satisfacuta pentru
ca operatiile sa reuseasca.
pentru a preveni stergerea unei tabele daca sunt posesiuni din alte tabele.
prin unelte sigure Oracle, ca Oracle Forms, pentru a furniza reguli pentru utilizarea
intr-o aplicatie.
133

Constrangerile sunt clasate dupa cum urmeaza:


Constrangeri de tabela
Acestea pot referi una sau mai multe coloane si sunt definite SEPARAT de definitiile
coloanelor din tabela.
Constrangeri de coloana
Acestea refera o singura coloana si sunt definite INAUNTRUL specificatiei pentru coloana
posesoare.
Constrangerile pot fi adaugate unei tabele dupa crearea ei si deasemenea temporar dezactivate
(vezi comanda ALTER TABLE in capitolul urmator).Toate detaliile despre constrangeri sunt
stocate in Dictionarul de Date. Fiecarei constrangeri ii este repartizat un nume. Iti este mai
usor sa suplimentezi una tu singur, astfel ca poate fi mai usor referita mao tarziu, dar daca nu,
atunci un nume este generat automat pe forma:
SYS_Cn

unde n este un numar unic. Cuvantul cheie CONSTRAINT iti permite sa numesti o noua
constrangere tu insuti.

Tipuri de constrangeri
Puteti defini urmatoarele tipuri de constrangeri:

NULL/NOT NULL
UNIQUE
PRIMARY KEY
FOREIGN KEY(integritatea de referinta)
CHECK

Constrangerea UNIQUE
Aceasta desemneaza o coloana sau o combinatie de coloane ca o cheie uni- ca.Doua linii in
aceeasi tabela nu pot avea aceeasi valoare pentru aceasta cheie.NULL-urile sunt permise daca
cheia unica este bazata pe o singura co- loana.
Sintaxa constrangerii de tabela :
[CONSTRAINT nume constrangere] UNIQUE (Coloana, Coloana, ...)

Sintaxa constrangerii de coloana :


[CONSTRAINT nume constrangere] UNIQUE

De exemplu, pentru a va asigura ca nu sunt 2 nume de departamente identice la o singura


locatie:
CREATE TABLE DEPT
(DEPTNO NUMBER, DNAME VARCHAR2(9),
LOC VARCHAR2(10),

134

CONSTRAINT UNQ_DEPT_LOC UNIQUE(DNAME,LOC))

In exemplul de mai sus, constrangerea UNQ_DEPT_LOC este o constrangere de ta- bela.


Notati ca virgula precede detaliile. O constrangere unica il face pe ORACLE sa creeze un
singur index pentru a manui regula. Indecsii sunt discu- tati mai tarziu.

Constrangere de cheie primara


Ca si la cheile unice, o cheie primara forteaza unicitatea unei coloane sau combinatii de
coloane implicate si un index unic este creat pentru a con- duce aceasta. Totusi poate fi o
singura cheie primara pe o tabela, si aceasta este cunoscuta ca fiind cheia definitiva prin care
liniile in tabela sunt i- dentificate individul. NULL-urile nu sunt permise in coloanele de chei
prima- re.
Sintaxa constrangerii de tabela :
[CONSTRAINT nume constrangere] PRIMARY KEY (Coloana, Coloana, ...)

Sintaxa constrangerii de coloana :


[CONSTRAINT nume constrangere] PRIMARY KEY

Notati ca aceeasi combinatie de coloane nu poate fi folosita si pentru o cheie primara si


pentru una unica. Urmatorul exempludefineste DEPTNO ca o cheie primara folosind o
constrangere de coloana:
CREATE TABLE DEPT
(DEPTNO NUMBER(2) CONSTRAINT DEPT_PRIM PRIMARY KEY, ...)

Constrangere de cheie externa


Cheile externe furnizeaza reguli de integritate de referinta inauntrul unei tabele sau intre
tabele. O cheie exeterna este folosita intr-o relatie cu fiecare cheie primara sau unica oriunde
si poate fi folosita, de exemplu, pentru a preveni stergerea unui departament in DEPT daca
angajatii exista cu acelasi numar de departament in EMP.
Sintaxa constrangerii de tabela :
[CONSTRAINT nume constrangere] FOREIGN KEY (Coloana, Coloana, ...)
REFERENCES tabela (Coloana, Coloana, ...)

Sintaxa constrangerii de coloana :


[CONSTRAINT nume constrangere] REFERENCES tabela (Coloana)

Notati ca, cuvintele 'FOREIGN KEY' nu sunt folosite versiunea constrangerii de coloana a
sintaxei.
Exemplul 1

-----------|
DEPT
|
------------

(parinte)

135

|
|
/|\
DEPTNO
-----------|
EMP
|
(fiu)
------------

Pentru a stabili relatia dintre EMP si DEPT astfel incat EMP.DEPTNO este che- ia externa, si
fiecare angajat trebuie sa aiba un numar valid de departament care este cunoscut in DEPT:
CONSTRAINT FK_DEPTNO FOREIGN KEY (DEPTNO)
REFERENCES DEPT(DEPTNO)

Optiunea ON DELETE CASCADE


Ca rezultat al constrangerii de tabela de mai sus, (care ar fi putut la fel de bine sa fie definita
ca o constrangere de coloana), un departament in DEPT nu ar fi putut fi sters daca liniile
exista in EMP cu aceeasi valoare DEPTNO. Alternativ, puteti cere ca angajatii corespunzatori
sa fie stersi a- utomat daca departamentul parinte in DEPT este sters. Aceasta este realizata
adaugand clauza ON DELETE CASCADE.
CONSTRAINT FK_DEPTNO FOREIGN KEY (DEPTNO)
REFERENCES DEPT(DEPTNO) ON DELETE CASCADE

Exemplul 2

-------------EMPNO
|
EMP
| . .
-------------.
\|/
.
.
.
.
.
MGR
.
.
. .

Pentru a va asigura ca fiecarei linii de angajat in EMP ii este dat un


numar
de manager (MGR) pentru un angajat existent valid:

CREATE TABLE EMP


(EMPNO NUMBER(4) PRIMARY KEY, ...
MGR NUMBER(4) CONSTRAINT EMP_MGR
REFERENCES EMP(EMPNO), ...

Constrangerea de verificare (CHECK)

136

Constrangerea CHECK defineste explicit o conditie pe care fiecare


linie
trebuie sa o satisfaca(sau sa o faca necunoscuta datorita unui NULL).
Conditia poate folosi aceleasi constructii ca acelea intr-o restrictie de
cerere,
cu urmatoarele exceptii:

subcererile nu sunt permise

referirile la pseudo-coloane ca SYSDATE nu sunt permise

Sintaxa:
[CONSTRAINT nume constrangere] CHECK (conditie)

Alte optiuni ale constrangerilor


DISABLE

Adaugand DISABLE unei definitii de constrangere


inseamna ca ORACLE nu o forteaza. Constrangerea

poate
fi inca citita de uneltele ORACLE pentru a
construi
reguli intr-o aplicatie si puteti face posibila
constrangerea mai tarziu prin comanda ALTER TABLE.
CREATE TABLE EMP
( . . . . . ,
ENAME VARCHAR2(10) CONSTRAINT CHK_UPP_NAM CHECK(ENAME-UPPER(ENAME))
DISABLE,
. . . . . . . ) ;
EXCEPTIONS
INTO nume tabela
constrangerea.

Identifica o tabela existenta unde este plasata


informatia despre liniile care incalca

CREATE TABLE EMP


( . . . . . ,
ENAME VARCHAR2(10) CONSTRAINT CHK_UPP_NAM CHECK(ENAME-UPPER(ENAME))
EXCEPTIONS INTO CON_VIOLATE,
. . . . . . . ) ;

137

In final, notati ca tabelele referite intr-o constrangere trebuie sa


existe
in aceeasi baza de date. Daca ele apartin unui utilizator diferit atunci
posesorul trebuie specificat ca un prefix.

Iata un exemplu complet al constructiei tabelei EMP cu constrangeri :

CREATE TABLE EMP


(EMPNO NUMBER(4)

CONSTRAINT EMP_PRIM PRIMARY KEY,

ENAME VARCHAR2(10)

CONSTRAINT ENAME_CONS
CHECK(ENAME=UPPER(ENAME)),

JOB VARCHAR2(10),
MGR NUMBER(4)

CONSTRAINT EMP_MGR
REFERENCES EMP(EMPNO),

HIREDATE DATE DEFAULT SYSDATE,


SAL NUMBER(7,2)

CONSTRAINT SAL_CONS
NOT NULL,

COMM NUMBER(7,2),
DEPTNO NUMBER(2)

CONSTRAINT DEPTNO_CONS
NOT NULL,

CONSTRAINT

EMP_DEPT FOREIGN KEY (DEPTNO)


REFERENCES DEPT(DEPTNO))

Crearea unei tabele cu linii din alta tabela

Exista o a doua forma a declaratiei CREATE TABLE in care tabela este


creata cu linii potrivite, derivate din alta tabela:
CREATE TABLE DEPT
[(nume-coloana ,. . . .)]
AS SELECT declaratie

138

Tabela va fi creata cu coloane specificate si linii recuperate din


declaratia SELECT inserata.
Numai constrangerile NULL/NOT NULL sunt mostenite din tabela
selectata.
Daca toata coloanele in declaratia SELECT au nume bine definite
(nu
sunt expresii s.a.m.d.) specificatiile coloanei pot fi
omise.
Daca sunt date specificatiile coloanei, atunci numarul de coloane
trebuie sa fie egal cu numarul de articole in lista SELECT.

Pentru a crea o tabela DEPT30 care tine numerele angajatilor, nume, joburi
si salariile angajatilor din departamentul 30, introduceti:

CREATE TABLE DEPT30


AS
SELECT
EMPNO,ENAME,JOB,SAL
FROM
EMP
WHERE
DEPTNO = 30;

Table created.

Pentru a vedea descrierea lui DEPT30, introduceti:

DESC DEPT30

Pentru a crea o tabela tinand numele angajatului, salariul si detalii de


grad, introduceti:

CREATE TABLE EMP_SALS


(NAME,SALARY,GRADE)
AS
SELECT
ENAME, SAL, GRADE
FROM
EMP, SALGRADE
WHERE
EMP.SAL BETWEEN LOSAL AND HISAL;

139

Table created.

DESC EMP_SALS;

Pentru a afisa continutul tabelei EMP SALS, introduceti:

SELECT
FROM

*
EMP_SALS;

,/pre>

CAPITOLUL 12
Exercitii Crearea de tabele si de
constrangeri
Atelier

1.

Creati o tabela numita PROJECTS, cu coloanele specificate ca mai


jos.Pe
2.
langa aceasta , definiti PROJID ca, coloana de CHEIE PRIMARA ,
si asigura3.
ti-va ca datele P_END_DATE nu sunt mai recente decat datele
P_START_DATE.
4.
5.
6.
7.
Creati o a doua tabela, ASSIGNMENTS, ca cea de mai jos. Definiti-i
coloana
8.
PROJID ca o cheie externa care refera tabela PROJECTS. Coloana
EMPNO a ta9.
belei dumneavoastra este o viitoare cheie externa a lui EMP.
Aceste doua
10.
coloane nu ar trebui sa permita valori NULL (PROJID si EMPNO).
11.
12.
13.
Sunt alte constrangeri pe care ar trebui sa le angajam in
aceste tabele.
14.
Acestea vor fi adaugate intr-un viitor atelier.
15.
16.
17.
Folositi comanda DESCRIBE pentru a verifica definitiile
coloanelor. (Ne
18.
vom uita la constrangeri mai tarziu).
19.

140

20.

CAPITOLUL 12 -Solutii

Fiecare din constrangerile aratate mai jos ar fi putut fi definite ca


oricare constrangere de tabela sau constrangere de coloana.

1.
2.
3.
4.

CREATE TABLE PROJECTS


( PROJID
NUMBER(4) CONSTRAINT PROJ_PRIM PRIMARY
KEY,

5.
6.
7.
8.
9.
10.

P_DESC
VARCHAR2(20),
P_START_DATE
DATE,
P_END_DATE
DATE,
BUDGET_AMOUNT
NUMBER(7,2),
MAX_NO_STAFF
NUMBER(2),
CONSTRAINT P_DATE_RULE CHECK(P_START_DATE <= P_END_DATE))

11.
12.
13.
14.

CREATE TABLE ASSIGNMENTS


(PROJID
NUMBER(4) NOT NULL REFERENCES PROJECTS
(PROJID),
15.
EMPNO
NUMBER(4) NOT NULL REFERENCES EMP (EMPNO),
16.
A_START_DATE
DATE,
17.
A_END_DATE
DATE,
18.
BILL_RATE
NUMBER(4,2),
19.
ASSIGN_TYPE
VARCHAR2(2))

141

CAPITOLUL 13
Management-ul de tabela si Dictionarul de Date
In acest capitol secund al Limbajului de Definire a Datelor vom vedea comenzile pentru
modificarea si mutarea tabelelor si constrangerilor lor. Deasemenea, vom vedea cum
informatii despre baza de date pot fi extrase din Dictionarul de Date.

Modificarea unei tabele


Folositi comanda ALTER TABLE pentru a schimba definitia unei tabele.
Sintaxa:
ALTER TABLE nume-tabela
[ ADD
](specificator coloana[constrangere de coloana])[ENABLE
clauza ]
[MODIFY
]
[DISABLE
clauza]
[DROP optiuni]

Clauza ADD
Folositi cuvantul cheie ADD pentru a adauga o coloana si/sau constran- geri pentru o tabela
existenta. Pentru a adauga o coloana tabelei EMP care va tine numele sotului angajatului,
introduceti:
ALTER TABLE EMP
ADD (SPOUSES_NAME CHAR (10));

Table altered.
Pentru a vedea descrierea tabelei revizuite, introduceti:
DESCRIBE EMP;

Pentru a adauga o constrangere de tabela unei tabele existente, care specifi- ca daca salariul
lunar nu trebuie sa depaseasca 5000$, introduceti:
ALTER TABLE EMP
ADD(CHECK(SAL <=5000));
,/pre>

Clauza MODIFY

142

Folositi cuvantul cheie MODIFY pentru a modifica definitia unei


coloane
existente.

ALTER TABLE nume


MODIFY (tip coloana [NULL])

Pentru a schimba lungimea lui ENAME la 25 de caractere, introduceti :

ALTER TABLE EMP


MODIFY (ENAME CHAR (25));

Table altered.

DESCRIBE EMP;

Sunt 4 schimbari pe care nu le puteti face

1.

Nu puteti schimba o coloana continand null-uri din NULL in NOT


NULL.

2.
3.

Nu puteti adauga o noua coloana care este NOT NULL. Faceti-o null,
um4.
pleti-o complet si apoi schimbati-o in NOT NULL.
5.
6.
Nu puteti sa scadeti dimensiunea unei coloane sau sa-i schimbati
tipul de
7.
date, numai daca nu contine date.
8.
9.
Nu puteti folosi optiunea MODIFY pentru a defini constrangeri pe o
coloana
10.
exceptand NULL/NOT NULL.
11.

Pentru a modifica alte constrangeri trebuie sa le eliminati si apoi sa le


adaugati specificand modificarile.

143

Clauza DROP

Folositi clauza DROP pentru a muta o constrangere din alta tabela.

Sintaxa:
ALTER TABLE nume tabela
DROP
[CONSTRAINT nume constrangere ] [CASCADE]
[PRIMARY KEY
]
[UNIQUE (coloana, coloana, ...)]

De exemplu:

ALTER TABLE EMP


DROP CONSTRAINT EMP_MGR;
ALTER TABLE EMP
DROP PRIMARY KEY;

Optiunea CASCADE (in clauza DROP)

Optiunea CASCADE a clauzei DROP face ca orice constrangere dependenta


sa fie deasemenea eliminata.

De exemplu:

ALTER TABLE DEPT


DROP PRIMARY KEY CASCADE;

ar putea deasemenea sa faca ca constrangerea chaii exetrne din EMP>DEPTNO


sa
fie eliminata.

Clauza ENABLE/DISABLE

144

Aceasta clauza a comenzii ALTER TABLE permite constrangerilor sa fie


facute posibile sau dezactivate fara a le elimina sau recrea.

Sintaxa:
[DISABLE]
[ENABLE ]

[ UNIQUE (coloana, coloana, ...) ]


[ PRIMARY KEY
]
[ CONSTRAINT nume constrangere
]

[CASCADE]

Ca si la clauza DROP, adaugarea cuvantului cheie CASCADE semnifica ca constrangerile dependente sunt deasemenea afectate.

De exemplu:

ALTER TABLE DEPT


DISABLE CONSTRAINT DEPT_PRIM CASCADE;

Alte comenzi LDD

Eliminarea unei tabele

Pentru a sterge definitia unei tabele ORACLE, folositi comanda DROP


TABLE.

Sintaxa:
DROP TABLE nume tabela [CASCADE CONSTRAINTS]

De exemplu:

DROP TABLE EMP;

Stergerea unei tabele duce la pierderea tuturor datelor din ea si a


tu-

145

turor indecsilor asociati ei. Optiunea CASCADE CONSTRAINTS va sterge


deasemenea referirile la constrangerile de integritate dependente.

Note:

Toate datele vor fi deasemenea sterse din tabela.


Orice VIEWS sau SYNONYMS vor ramane, dar vor deveni invalide.
Orice tranzactii nerezolvate sunt realizate.
Numai creatorul tabelei sau DBA poate sa o stearga.

Comanda COMMENT

Folositi comanda COMMENT pentru a insera un comentariu pana la 255 de


caractere, despre o tabela sau coloana, in dictionarul de date.

Pentru a adauga un comentariu unei tabele numita EMP, introduceti:

COMMENT ON TABLE EMP IS 'Employee Information';

Pentru a adauga un comentariu pe coloana EMPNO in tabela EMP, introduceti:

COMMENT ON COLUMN EMP.EMPNO IS 'Unique employee number';

Pentru a sterge un comentariu, emiteti comanda COMMENT fara un comentariu:

COMMENT ON COLUMN EMP.EMPNO IS '';


,/pre>
Pentru a vedea comentariul, selectati coloana COMMENTS din una din
vederile

146

dictionarului:ALL_COL_COMMENTS sau USER_COL_COMMENTS. Dictionarul de Date


este acoperit mai tarziu in acest capitol.

Comanda RENAME

Comanda RENAME este folosita de creatorul lui TABLES, VIEWS si


SYNONYMS
pentru a scimba numele obiectului bazei de date.

Pentru a redenumi un obiect al bazei de date sintaxa este:


RENAME vechi TO nou;

Pentru a redenumi tabela EMP in EMPLOYEE, introduceti:


RENAME EMP TO EMPLOYEE;

Pentru a redenumi tabela SALGRADE, introduceti:


RENAME SALGRADE TO EMPLOYEE_GRADES;

Este important de notat ca orice aplicatii/programe/rapoarte care se


refera la obiecte ce
au fost redenumite, trebuie amendate.

Comanda TRUNCATE TABLE

Aceasta comanda va permite sa stergeti toate liniile dintr-o tabela.


Notati ca comanda DELETE poate deasemenea realiza aceasta ca o parte a tranzactiei de manipulare a datelor (acoperita in capitolul urmator), dar
comanda
TRUNCATE TABLE umple o tabela mai eficient ca o actiune de definire de
date,

147

pana cand nu este retinuta nici o informatie de rollback.

Sintaxa:
TRUNCATE TABLE nume tabela [REUSE STORAGE]

Optiunea REUSE STORAGE pastreaza spatiul din liniile sterse pentru


reutilizarea tabelei. Implicit, acest spatiu este eliberat.

Dictionarul de Date Oracle

Dictionarul de Date este una din partile cele mai importante ale lui
ORACLE RDBMS. Consta dintr-un set de tabele si vederi care furnizeaza un
ghid
de referinta accesibil doar la citire, despre baza de date. Dictionarul de
Date va va spune:

numele utilizatorilor ORACLE


drepturile si privilegiile care le-au fost acordate
numele obiectelor bazei de date (tabele, vederi, indecsi,
sinonime,secvente,...)
constrangeri aplicate tabelei
informatii de revizie, ca: cine a accesat si actualizat obiectele
bazei
de date specificate.

Dictionarul de Date este creat cand este creata baza de date. Oricand baza
de

148

date este in operatii, Dictionarul de Date este actualizat de ORACLE


RDBMS.

Dictionarul de Date este o referinta pentru toti utilizatorii bazei


de
date. Este o sursa valoroasa de informatii pentru utilizatori, proiectanti
de
aplicatii si DBA. Dictionarul de Date este deasemenea critic pentru
operatia
ORACLE RDBMS, care il reaseaza pentru a inregistra si verifica informatii
despre baza de date.

Accesul la Dictionarul de Date

Utilizatori

Accesul la obiectele Dictionarului de Date este prin SQL. Declaratiile


SELECT pot fi folosite pentru a cere informatii din Dictionarul de Date.

RDBMS

Nici un utilizator nu ar trebui sa schimbe vreodata (insereze, actualizeze


sau stearga) nici o linie sau obiect in Dictionarul de Date, este probabil
sa
compromita integritatea datelor. RDBMS actualizeaza automat Dictionarul de
Date pentru a reflecta schimbarile structurii bazei de date, permisiuni,
revizii si alte date. In timpul operatiei bazei de date, RDBMS citeste
deasemenea Dictionarul de Date pentru a descoperi obiectele care exista si ca
uti-

149

lizatorii sa aiba acces la ele.

Tabelele si vederile Dictionarului de Date

Tabele

Baza Dictionarului de Date sau fundamentul tabelelor sunt primele obiecte ce trebuie create in baza de date, pentru ca ele trebuie sa fie
prezente pentru toate obiectele ce trebuie create. Tabelel Dictionarului de
Date
sunt create automat de declaratia SQL CREATE DATABASE si nu sunt in
posesia
utilizatorului SYS. Tabelele de baza sunt rareori accesate direct,
deoarece
informatia din ele nu este usor de inteles.

Vederi

Vederile Dictionarului de Date (tabele virtuale - acoprite in


capitolul
15) contin informatii intr-o forma care este usor de inteles pentru
utilizator. Accesul public la Dictionarul de Date este dat prin vederi mai
degraba
decat prin tabele de baza. SYS poseda deasemenea vederile Dictionarului
de Date.
Vederile au fost numite pentru a reflecta tipul de utilizare dorit.
Vederile sunt clasificate in 3 grupe distingandu-se intre ele prin prefixele
USER, ALL si DBA.

150

Cele trei clase de vederi sunt:

USER_xxxxx
Obiectele posedate de utilizator pot fi accesate. De eexemplu, vederile cu acest prefix permit utilizatorului
sa afiseze informatii despre tabelele create de
utilizator si privilegiile acordate de utilizator.
ALL_xxxxx
Utilizatorii pot accesa obiecte la care le-au fost permise
drepturile de acces, in plus fata de obiectele pe care
le
poseda.
DBA_xxxxx
Pentru utilizare de catre utilizatori cu privilegiu DBA pot accesa orice obiect in baza de date.

Unele dintre vederile Dictionarului de Date nu utilizeaza prefixele


listate mai sus. Aceste vederi includ:

DICTIONARY
Listeaza toate tabelele, vederile, Dictionarului
de Date, accesibile utilizatorului.
DICT_COLUMNS
Listeaza coloanele in dictionarul obiectelor accesibile utilizatorului.
CONSTRAINT_DEFS
Listeaza toate definitiile de constrangeri introduse pentru tabelele accesibile
utilizatorului.
CONSTRAINT_COLUMNS
Listeaza toate coloanele care sunt accesibile utilizatorului curent si numite in definitiile
constrangerilor.

Vederea DICTIONARY

DICTIONARY listeaza toate obiectele Dictionarului de Date accesibile


utilizatorului cu o scurta descriere a obiectului.

151

Urmatoarea declaratie SQL afiseaza continutul tabelei DICTIONARY :


SELECT
*
FROM DICTIONARY;

Multe din vederile Dictionarului de Date au nume lung. Sinonimele publice


au
fost furnizate, ca abreviatii, pentru accesul convenabil la unele din cele
mai comune vederi ale Dictionarului de Date utilizator.
Numele Tabelei
-------------ALL_CATALOG
secven-

Comentarii
---------Toate tabelele, vederile, sinonimele,
tele accesibile utilizatorului

ALL_COL_COMMENTS
vederi-

Comentarii pe coloanele tabelelor si


le accesibile

ALL_COL_PRIVS
utiliza-

Permisiuni pe coloanele pentru care


torul este "grantor", "grantee",

proprietar,
sau un rol posibil sau PUBLIC este
"grantee"
ALL_COL_PRIVS_MADE
utiliza-

Permisiuni pe coloanele pentru care


e proprietar sau "grantor"

ALL_COL_PRIVS_RECD
utiliza-

Permisiuni pe coloanele pentru care


torul, PUBLIC sau rolul posibil este

"grantee"
ALL_CONSTRAINTS
accesi-

Definitii de constrangeri pe tabele


bile

ALL_CONS_COLUMNS

ALL_DB_LINKS
utiliza-

Informatii despre coloanele accesibile in


definitiile de constrangeri
Legaturile bazei de date accesibile
torului

ALL_DEF_AUDIT_OPTS

ALL_DEPENDENCIES
acce-

Optiuni de revizuire pentru noile obiecte


create
Dependente dinspre si inspre obiectele
sibile utilizatorului

152

ALL_ERROR
care

Erorile curente pe obiectele stocate la


utilizatorul este permis sa creeze
(pag. 13-13)

ALL_INDEXES
accesibile

Descrierea indecsilor pe tabelele


utilizatorului

ALL_IND_COLUMNS
acce-

Coloanele cuprinzand indecsi pe tabele


sibile

ALL_OBJECTS
ALL_SEQUENCES
utili-

Obiectele accesibile utilizatorului


Descrierea SEQUENCE-urilor accesibile
zatorului

ALL_SNAPSHOTS
utilizatorul
ALL_SOURCE

Instantanee la care poate privi

Sursa curenta a obiectelor create pe care

utilizatorul are permisiunea sa le creeze


ALL_SYNONYMS
utilizatorului

Toate sinonimele accesibile

ALL_TABLES
utilizatoru-

Descrierea tabelelor accesibile


lui

ALL_TAB_COLUMNS

Coloanele tuturor tabelelor, vederilor si


clusterelor

ALL_TAB_COMMENTS

Comentarii pe tabele si vederi accesibile

utilizatorului
ALL_TAB_PRIVS
utilizato-

Permisiuni pe obiecte pentru care


rul e "grantor", "grantee" sau

proprietar,
sau un rol posibil sau PUBLIC garantie
ALL_TAB_PRIVS_MADE

Permisiunile utilizatorilor si permisiuni

pe
obiectele utilizatorilor
ALL_TAB_PRIVS_RECD
utilizato-

Permisiuni pe obiecte pentru care


rul, PUBLIC sau un rol posibil este

"grantee"
ALL_TRIGGERS
curent

TRIGGER-uri accesibile utilizatorului

153

ALL_TRIGGER_COLS
utiliza-

Utilizarea coloanelor in trigger-ul


torilor sau in trigger-uri pe tabelele

utilizatorilor
ALL_USERS

Informatii despre toti utilizatorii bazei

de
date
ALL_VIEWS
utilizatorilor

Textul vederilor accesibile

AUDIT_ACTIONS
urma-

Tabela de descriere pentru actiunea de


rire a reviziei tipului de coduri

CAT

Sinonim cu USER_CATALOG

CLU

Sinonim cu USER_CLUSTERS

COLS

Sinonim cu USER_TAB_COLUMNS

COLUMN_PRIVILEGES
utilizato-

Permisiuni pe coloane pentru care


rul e "grantor", "grantee", proprietar,

sau
un rol posibil sau PUBLIC este "grantee"
DICT
DICTIONARY
Dictiona-

Sinonim cu DICTIONARY
Descrierea tabelelor si vederilor
rului de Date

GLOBAL_NAME

Numele bazei de date globale

IND

Sinonim pentru USER_INDEXES

INDEX_HISTOGRAM

Statistica pe chei cu numarare repetata

INDEX_STATS

Statistica pe arbori-B

OBJ

Sinonim pentru USER_OBJECTS

RESOURCE_COSTS

Costul fiecarei resurse

ROLE_ROLE_PRIVS

Roluri permise rolurile

ROLE_SYS_PRIVS

Privilegiile sistem permise rolurilor

ROLE_TAB_PRIVS

Privilegii de tabela permise rolurilor

SEQ

Sinonim pentru USER_SEQUENCES

SESSION_PRIVS
setat

Privilegii pe care utilizatorul le-a

154

in mod curent
SESSION_ROLES
posi-

Roluri pe care utilizatorul le-a facut


bile in mod curent

SYN

Sinonim pentru USER_SYNONYMS

TABLE_PRIVILEGES

Alocatii pe obiecte pe care utilizatorul


este "grantor", "grantee", posesor, sau

un
rol facut posibil, sau PUBLIC este "grantee-ul"
TABS
USER_AUDIT_OBJECTS
de-

Sinonim pentru USER_TABLES


Inregistrarea urmelor examinate pentru
claratii referitoare la obiecte, si

anume:
tabel, cluster, vedere, index, secventa,
legatura bazei de date [publica], sinonim
[public], procedura, trigger, segment
rollback, spatiu de tabela, rol, utilizator
USER_AUDIT_SESSION
USER_AUDIT_STATEMENT
referitoare

Inregistrarea urmelor examinate


la alocatie, anulare, examinare,

neexaminare si sistem modificat


USER_AUDIT_TRAIL

Intrari ale urmelor revizuite, relevante

utilizatorului
USER_CATALOG
poseda-

Tabele, vederi, sinonime si secvente


te de utilizator

USER_CLUSTERS

Descrieri ale clusterelor utilizatorului

USER_CLU_COLUMNS

Maparea coloanelor tabelei pentru a aduna


impreuna coloanele

TABLENAMECOMMENTS
USER_COL_COMMENTS
ve-

Comentarii despre coloanele tabelelor si


derile utilizatorului

USER_COL_PRIVS
utiliza-

Permisiuni pe coloanele pentru care


torul este posesorul, "grantor" sau

"grantee"
USER_COL_PRIVS_MADE
obiectelor

Toate permisiunile pe coloanele

155

posedate de utilizator
USER_COL_PRIVS_RECD
utilizato-

Permisiuni pe coloane pentru care


rul este "grantee"

USER_CONSTRAINTS
uti-

Definitiile constrangerilor pe tabelele


lizatorului

USER_CONS_COLUMNS

USER_DB_LINKS
utili-

Informatii despre coloanele accesibile in


definitiile constrangerilor
Legaturile bazei de date posedate de
zator

USER_DEPENDENCIES
uti-

Dependente dinspre si inspre obiectele


lizatorilor

USER_ERRORS
posedate

Erori curente pe obiecte stocate,


de utilizator

USER_EXTENTS
utilizato-

Extensii cuprinzand segmente ale


rului

USER_FREE_SPACE
accesi-

Extensii libere in spatiul tabelelor


bile utilizatorului

USER_INDEXES
USER_IND_COLUMNS
utilizatoru-

Descrierea indecsilor utilizatorului


Coloanele cuprinzand indecsi ai
lui sau pe tabele ale utilizatorului

USER_OBJECTS
USER_OBJECT_SIZE
obiecte

Obiecte posedate de utilizator


Dimensiuni, in octeti, a diferitelor
pl/sql

USER_OBJ_AUDIT_OPTS
vede-

Optiuni de revizuire pentru tabelele si


rile utilizatorului

USER_RESOURCE_LIMITS

Afiseaza limita resurselor utilizatorului

USER_ROLE_PRIVS

Roluri permise utilizatorului curent

USER_SEGMENTS

Spatiu de stocare alocat pentru segmentele


bazei de date

USER_SEQUENCES

Descrierea SEQUENCE-lor utilizatorului

156

USER_SNAPSHOTS
ve-

Instantanee pe care utilizatorul le poate


dea

USER_SNAPSHOTS_LOGS
uti-

Toate jurnalele instantanee posedate de


lizator

USER_SOURCE
utiliza-

Sursa obiectelor stocate accesibile


torului

USER_SYNONYMS
USER_SYS_PRIVS
utilizatorului

Sinonimele private ale utilizatorului


Privilegii de sistem permise
curent

USER_TABLES

Descrierea tabelelor utilizatorului

USER_TABLESPACES

Descrierea spatiilor tabelelor accesibile

USER_TAB_COLUMNS
clustere-

Coloane ale tabelelor, vederilor si


lor utilizatorului

USER_TAB_COMMENTS
pose-

Comentarii despre tabelele si vederile


date de utilizator

USER_TAB_PRIVS
utilizato-

Permisiuni pe obiecte pentru care


rul este posesorul, "grantor-ul", sau

"grantee-ul"
USER_TAB_PRIVS_MADE

Toate permisiunile pe obiecte posedate de

utilizator
USER_TAB_PRIVS_RECD
utilizato-

Permisiuni pe obiecte pentru care


rul este "grantee-ul"

USER_TRIGGERS
USER_TRIGGER_COLS
utilizatoru-

Tigger-uri posedate de utilizator


Folosirea coloanei in trigger-ul
lui

USER_TS_QUOTAS

Cota spatiului de tabela pentru utilizator

USER_USERS

Informatii despre utilizatorul curent

USER_VIEWS

Text de vederi posedat de utilizator

157

Cateva vederi folositoare

Urmatoarele vederi sunt probabile de a fi de interes pentru


majoritatea
utilizatorilor:
Nume vedere
-----------

Sinonim
-------

Descriere
----------

DICTIONARY

Dict

Lista tuturor obiectelor bazei de date

USER_OBJECTS

Obj

Obiectele posedate de utilizator

USER_CATALOG
accesi-

Cat

Tabele, vederi, sinonime, secvente


bile utilizatorului

USER_TABLES
USER_TAB_COLUMNS
utili-

Tabs

Descrierea tabelelor utilizatorului

Cols

Coloanele din tabelele si vederile


zatorului

USER_COL_COMMENTS
vede-

Comentarii pe coloanele tabelelor si


rilor utilizatorului

USER_TAB_COMMENTS

Comenzi pe tabele si vederi posedate de

utilizator
USER_SEQUENCES
utili-

Seq

Descrierea secventelor posedate de


zator

USER_SYNONYM

Syn

USER_VIEWS
USER_INDEXES
utilizatoru-

Sinonimul privat al utilizatorului


Textul vederilor posedate de utilizator

Ind

Descrierea indecsilor proprii


lui

ALL_OBJECTS
ALL_TAB_COLUMNS
vederi-

Obiectele accesibile utilizatoruluI


Coloanele pentru toate tabelele si
le accesibile utilizatorului

Daca nu stiti definitia unei tabele sau vederi a Dictionarului de Date,


sau
daca nu va puteti aminti numele unei coloane intr-o tabela/vedere
specifica,

158

atunci folositi comanda DESC[RIBE] pentru a afisa definitia


tabelei/vederii.

Pentru a vedea structura lui USER_OBJECTS, introduceti:

SQL>desc user_objects

O descriere a vederii DICTIONARY urmeaza:

SQL>desc dict

Notati ca sinonimul abreviat DICT poate fi folosit cu referire la


DICTIONARY.
Odata ce stiti structura unei tabele/vederi, puteti selecta informatia
dorita:

SELECT
FROM
WHERE

OBJECT_NAME, OBJECT_TYPE, CREATED


USER_OBJECTS
OBJECT_NAME = 'EMP'

Folosirea lui SQL pentru a genera SQL

SQL poate fi o unealta puternica pentru a genera alte declaratii


SQL,
facand folosirea informatiei in Dictionarul de Date. Puteti folosi SQL din
SQL pentru:

a evita cod repetitiv


a primi ajutor de la Dictionarul de Date
a recrea tabele, vederi, index-uri

159

a genera predicate "dinamice", continand parametri din timpul executiei

Amintiti-va, virtual puteti selecta orice.


De exemplu, pentru a genera declaratii SQL*PLUS pentru a descrie
toate
tabelele voastre, folositi urmatorul SQL:

SELECT 'DESC '||OBJECT_NAME


FROM
USER_OBJECTS
WHERE OBJECT_TYPE = 'TABLE'
/
OR
SELECT 'DESC '||TABLE_NAME
FROM USER_TABLES;

Exemplele de mai sus genereaza urmatoarea iesire:


DESC DEPT
DESC EMP
DESC SALGRADE

Pentru a executa declaratiile de mai sus, este necesara capturarea lor


intr-un fisier care poate fi pornit.

SET ECHO OFF


SET PAGES 0
SET FEEEDBACK OFF
SPOOL X
SELECT 'DESC '||TABLE_NAME
FROM
USER_TABLES
/
SPOOL OFF
START X.LIS

In exemplul de mai susm PAGE[SIZE] este pus pe 0, pentru a elimina


titlurile
din varf si de jos, ca si cele de tabel. Notati deasemenea ca extensia LIS

160

este specificata pe comanda START, deoarece START isi asuma o extensie a


SQL.
Exemple mai sofisticate ale acestei tehnici sunt detailate in Apendicele
G,
unde cererile din Dictionarul de Date sunt folosite pentru a produce
comenzi
DML si DDL si iesire.

CAPITOLUL 13 Exercitii Managementul de tabela si


Dictionarul de Date
Atelier

1.

Adaugati o coloana LONG numita COMMENTS , PROJECT TABLE-ului


dumneavoas2.
tra. Deasemenea, adaugati o coloana NUMBER, numita HOURS,
tabelului
3.
ASSIGNMENTS.
4.
5.
6.
Folositi vizualizarea dictionarului USER_OBJECTS pentru a lista
obiectele
7.
posedate de contul dumneavoastra ORACLE. Cate obiecte posedati?
8.
9.
10.
Acum definiti o constrangere pe tabela ASSIGNMENTS pentru a
asigura combi11.
natii unice de Project ID si numar de angajat.
12.
13.
14.
15.
16.

Cereti vederea USER_OBJECTS; posedati acum vreun obiect viitor?

Priviti in Dictionarul de Date pentru informatii despre


constrangeri pe
17.
tabelele voastre (puteti folosi vederea USER_CONSTRAINTS).
18.
19.
Daca aveti timp :
20.

161

21.
22.

Folositi vizualizarea dictionarului ALL_TABLES pentru a gasi


posesorii si
23.
numele tabelelor la care puteti avea acces, unde numele tabelei
include
24.
caracterele "EMP".
25.

CAPITOLUL 13

1.
2.
3.
4.
5.
6.
7.
8.

9.
10.
11.
12.
13.

14.
15.
16.
17.
18.
19.
20.

Solutii

ALTER TABLE PROJECTS


ADD (COMMENTS LONG)
ALTER TABLE ASSIGNMENTS
ADD (HOURS NUMBER)

SELECT OBJECT_NAME, OBJECT_TYPE


FROM USER_OBJECTS

ALTER TABLE ASSIGNMENTS


ADD CONSTRAINT UNQ_KEY UNIQUE (PROJID,EMPNO)

Ati fi putut alternativ sa adaugati o cheie primara, pana cele doua


coloane
21.
nu permit null-uri. In fiecare caz, un index unic a fost adaugat
listei
22.
voastre de obiecte posedate.
23.

24.
25.
26.
27.
28.
29.
30.

O cerere posibila este:

SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME


SEARCH_CONDITION
FROM USER_CONSTRAINTS

162

Probabil veti vrea sa folositi comenzile COLUMN pentru a formata


rezultatele!

31.
32.
33.
34.
35.
36.

SELECT OWNER, TABLE_NAME


FROM ALL_TABLES
WHERE TABLE_NAME LIKE '%EMP%'

163

CAPITOLUL 14
Limbajul de manipulare a datelor
Acest capitol explica cum se fac schimbari liniilor intr-o tabela, cum se adauga noi linii sau
cum se sterg. Este introdus conceptul de tranzactie. Consistenta la citire este deasemenea
discutata.

Inserarea de noi linii intr-o tabela


Comanda INSERT este folosita pentru a adauga linii unei tabele Sintaxa comenzii INSERT
este:
INSERT

INTO nume tabela [ (coloana,coloana,....)]


VALUES (valoare,valoare,....);

Este posibila inserarea unei noi linii cu valori in fiecare coloana, in care caz lista de coloane
nu este ceruta. Este recomandat ca COLUMN LIST sa fie intotdeauna specificata. Daca lista
nu este specificata, software-ul va cere modificari oriunde definitia tabelei este modificata.
Pentru a insera un nou departament, introduceti:
INSERT
VALUES

INTO DEPT (DEPTNO,DNAME,LOC)


(50,'MARKETING','SAN JOSE');

Nota aceasta comanda adauga o singura linie unei tabele.


Pentru a intra intr-un departament nou, omitand numele departamentului, lista de coloane
trebuie specificata:
INSERT
VALUES

INTO DEPT (DEPTNO,LOC)


(50,'SAN JOSE');

Alternativ, daca numele departamentului nu este cunoscut, un NULL ar putea fi specificat:


INSERT
VALUES

INTO DEPT (DEPTNO,DNAME,LOC)


(50,NULL,'SAN JOSE');

Valorile CHARACTER si DATE trebuie puse in ghilimele simple.

Folosirea Variabilelor de Substitutie pentru a insera linii


Dupa cum am mentionat anterior, INSERT este o comanda pentru o singura lini- e. Folosind
variabile de substitutie este posibil sa se mareasca viteza de intrare.
INSERT
VALUES

INTO DEPT (DEPTNO,DNAME,LOC)


(&D_NUMBER, '&D_NAME', '&LOCATION');

164

Cand comanda este rulata, valorile sunt afisate de fiecare data.

Inserarea informatiilor de data si timp


Cand se insereaza o valoare DATE, formatul DD-MON-YY este de obicei folo- sit. Cu acest
format secolul implicit este secolul 20 (19nn). Data deasemenea contine informatii de timp,
care daca nu sunt specificate, implicit devin miezul noptii (00:00:00).
Daca o data trebuie introdusa in alt secol si un timp specific este cerut deasemenea, folositi
functia TO_DATE:
INSERT
VALUES

INTO EMP
(EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO)
(7658,
'MASON',
'ANALYST',
7566,
TO_DATE('24/06/2084 9:30','DD/MM/YYYY HH:MI'),
3000,
NULL,
20);

Copierea de linii din alta tabela


INSERT

INTO tabela [(coloana, coloana, ....)]


SELECT lista-select
FROM tabela(e)

Aceasta forma a declaratiei INSERT va permite sa inserati cateva linii intr-o tabela unde
valorile sunt derivate din continutul tabelelor existente in baza de date.
Pentru a copia toate informatiile din departamentul 10 in tabela D10HISTORY, introduceti:
INSERT

INTO D10HISTORY
(EMPNO,ENAME,SAL,JOB,HIREDATE
FROM EMP
WHERE DEPTNO=10;

Notati ca cuvantul cheie 'VALUES' nu este folosit aici.

Actualizarea liniilor
Declaratia UPDATE va permite sa schimbati valori in liniile unei tabele.
UPDATE
SET
[WHERE

tabela[alias]
coloana [, coloana...] = {expresie, subcerere}
conditie];

De exemplu:
Pentru a actualiza linia lui Scott, introduceti:

165

UPDATE
SET

WHERE

EMP
JOB='SALESMAN',
HIREDATE = SYSDATE,
SAL = SAL*1.1
ENAME = 'SCOTT';

1 record updated.

Daca clauza WHERE este omisa, toate liniile din tabela vor fi actualizate. Este posibil sa
folositi subcereri inlantuite si subcereri corelate in decla- ratia UPDATE.
Sa presupunem ca ati avut o cifra noua de comisioane pentru angajati siguri. De exemplu,
tabela COMMISSION de mai jos este folosita pentru a actualiza li- nii sigure ale tabelei
EMP:
COMMISSION
EMPNO
-----7499
7654
7844
7844
7844

EMP

COMM
---1100
500
3500
2000
1500

EMPNO
----7499
7654
7844

COMM
----300
1400
0

Schimbarile listate in tabela COMMISSION pot fi aplicate tabelei EMP, folosind o subcerere
corelata si o subcerere inlantuita, ca mai jos:
Exemplul 1:
UPDATE EMP
SET COMM = (SELECT COMM FROM COMMISSION C
WHERE C.EMPNO = EMP.EMPNO)
WHERE EMPNO IN (SELECT EMPNO FROM COMMISSION);
3 records updated.

Tabela COMMISSION poate contine mai mult decat o intrare pentru fiecare angajat, ca in
exemplul de mai jos :
COMISSION
EMPNO
----7499
7654
7654
7844
7844

COMM
---1100
500
100
2000
1500

Daca doriti sa inlocuiti (REPLACE) valorile din tabela EMP pentru comision cu comisionul
TOTAL pentru fiecare angajat listat in tabela COMISSION, atunci puteti utiliza urmatorul
SQL :

166

Exemplul 2:
UPDATE EMP
SET COMM = ( SELECT SUM(COMM) FROM COMISSION C
WHERE C.EMPNO = EMP.EMPNO)
WHERE EMPNO IN (SELECT EMPNO FROM COMISSION);
3 inregistrari modificate.
Tabela EMP reflecta comisioanele modificate :
EMP
EMPNO
----7499
7654
7844

COMM
---1100
600
3500

O alta posibilitate este cea de a adauga (ADD) la valorile comisionului in tabela


COMISSION la comisioanele existente in tabela EMP mai mult decat inlocuirea lor.
Exemplul 3 realizeaza acest lucru :
Exemplul 3:
UPDATE EMP
SET COMM = ( SELECT SUM(COMM) + EMP.COMM
FROM COMISSION C
WHERE C.EMPNO = EMP.EMPNO)
WHERE EMPNO IN (SELECT EMPNO FROM COMISSION);
Tabela EMP reflecta comisioanele schimbate :
EMP
EMPNO
----7844
7499
7654

COMM
---3500
1400
2000

Stergerea Coloanelor dintr-o Tabela


Comanda DELETE permite stergerea unei sau mai multor linii dintr-o tabela.
DELETE
[WHERE

FROM tabela
conditie];

Pentru a sterge toate informatiile despre departamentul 10 din tabela EMP, introduceti :
DELETE
WHERE

FROM EMP
DEPTNO = 10;

167

Daca clauza WHERE este omisa, atunci toate liniile vor fi sterse.

TRANZACTII

Procesarea unei Tranzactii


Ce este o tranzactie ?
O tranzactie este o operatie asupra unei baze de date care implica una sau mai multe
modificari in una sau mai multe tabele.
Exista doua clase de tranzactii. Tranzactii DML care contin un numar oarecare de blocuri
DML si pe care ORACLE le trateaza ca o singura entitate sau o singura unitate logica de
lucru, si tranzactii DDL care contin un singur bloc DDL.
Nu pot exista situatii "jumatate de drum" in timpul executiei unei tranzactii, asa incat unele
modificari specificate in tranzactie sa fie aplicate bazei de date si altele nu. Pentru fiecare
tranzactie ori toate modificarile sunt aplicate bazei de date, ori nici una din modificari nu este
indeplinita ( sunt toate abandonate - discarded ).
O tranzactie incepe cand prima comanda executabila DML sau DDL este intalnita si se
termina in una din urmatoarele situatii :

Intalneste COMMIT/ROLLBACK
Comanda DDL se termina
Anumite erori (DEADLOCK)
EXIT - iesire din SQL*Plus
Eroare sistem

Un bloc DDL este executat automat si de aceea implicit incheie o tranzactie.


Dupa incheierea unei tranzactii, urmatorul bloc executabil SQL va lansa automat urmatoarea
tranzactie.

Permanentizarea Modificarilor
Pentru ca modificarile sa ramana permanente, ele trebiue executate asupra bazei de date.
comanda COMMIT realizeaza permanentizarea modificari- lor; ROLLBACK permite sa
abandonam sau sa anulam modificarile. Modifiacrea, sau modificarile, executate asupra bazei
de date intre 2 comenzi COMMIT reprezinta o tranzactie. Pana cand tranzactia nu este
executata, nici una din modificari nu este vizibila utilizatorilor.

Inlaturarea Modificarilor Nedorite


Modificarile neexecutate pot fi abandonate prin comanda ROLLBACK. ROLLBACK va
atribui datelor valorile care acestea le aveau imediat dupa executarea ultimului COMMIT
prin anularea tuturor modificarilor facute dupa ultimul COMMIT.

168

Erorile de Sistem
Cand o tranzactie este intrerupta de o eroare serioasa, de exemplu o eroare de sistem, intreaga
tranzactie este anulata. Aceasta previne erorile datorate modificarilor nedorite asupra datelor,
si realizeaza intoarcerea tabelelor la starile de dupa ultimul COMMIT. In acest fel SQL*Plus
protejea- za integritatea tabelelor.
Anularea automata este cauzata cel mai des de catre o eroare de sistem, ca de exemplu o
resetare a sistemului sau o cadere de tensiune. Erorile de tastare a comenzilor, ca de exemplu
tastarea gresita a unor nume de coloane sau incercarile de a realiza operatii neautorizate
asupra tabelelor altor utilizatori, nu intrerup tranzactia si nu realizeaza anu- larea automata.
Aceasta se datoreaza faptului ca aceste erori sunt detectate in cursul compilarii (de catre
PARSER) ( cand un bloc SQL este scanat si verificat), si nu in timpul executiei.
O tranzactie noua este lansata urmand unui COMMIT sau ROLLBACK - adica cand primul
bloc executabil DML sau DDL este intalnit.

Semnificatia Tranzactiilor
ORACLE asigura consistenta datelor bazata pe tranzactii. Tranzacti ile dau utilizatorului mai
multa flexibilitate si control la lucrul asupra datelor, si asigura consistenta datelor in cazul
unei erori a procesului utilizator sau a unei erori de sistem.
Tranzactiile ar trebui sa contina doar acele comenzi DML care realizeaza o singura
modificare asupra datelor. De exemplu un transfer de fonduri (sa spunem 1000$) intre 2
conturi ar trebui sa implice un debit al unui cont de 1000$ si un credit al altui cont de 1000$.
Ambele actiuni ar trebui sa se incheie cu succes sau sa dea eroare impreuna. Creditul nu ar
trebui executat fara debit.

Controlul Tranzactiilor cu Instructiuni SQL


Urmatoarele instructiuni SQL sunt utilizate cand apar executii (commit) sau refaceri
(rollback) :

COMMIT[WORK]
SAVEPOINT nume_savepoint
ROLLBACK[WORK] to [SAVEPOINT] nume_savepoint

De notat ca COMMIT si ROLLBACK sunt instructiuni (blocuri) SQL.


Cele 3 blocuri SQL utilizate pentru controlul tranzactiilor sunt explicate mai jos:
COMMIT[WORK]
Sintaxa : COMMIT[WORK];

Permanentizeaza schimbarile in tranzactia curenta


Sterge toate punctele de salvare (savepoint) din tranzactie
Termina tranzactia

169

Elibereaza toate blocarile (Lock) tranzactiei


Cuvantul cheie WORK este optional
Utilizatorul trebuie sa expliciteze sfarsitul tranzactiei in programul aplicatie utilizand
COMMIT (sau ROLLBACK). Daca nu se executa explicit tranzactia si programul se
termina anormal, ultima tranzactie executata va fi anulata.
Executii implicite (commit) apar in urmatoarele situatii :
o inainte de o comanda DDL
o dupa o comanda DDL
o la inchiderea mormala a unei baze de date

Blocurile DDL cauzeaza mereu executii (commit) in timpul executiei lor. Daca introduceti un
bloc DDL dupa cateva blocuri DML, blocul DDL cauzeaza aparitia unui commit inaintea
propriei executii, incheind tranzactia curenta. Astfel daca blocul DDL este executat pana la
capat, este si inregistrat.
SAVEPOINT
Sintaxa : SAVEPOINT nume_savepoint
Exemplu :
SAVEPOINT terminare_actualizari

Poate fi utilizat pentru a imparti o tranzactie in bucati mai mici


Punctele de salvare (savepoints) permit utilizatorului sa retina toata munca sa la orice
moment din timp, cu optiunea de a inregistra mai tarziu totul sau a anula totul sau o
parte din ea. Astfel, pentru o tran- zactie lunga, se pot salva parti din ea, pe masura
executiei, la sfarsit inregistrandu-se sau refacandu-se continutul initial. La aparitia
unei erori nu trebuie executat din nou fiecare bloc.
La crearea unui nou punct de salvare cu acelasi nume ca al unuia dinainte, primul
punct este sters.
Numarul maxim de puncte de salvare pentru un proces utilizator este implicit 5.
Aceasta limita poate fi schimbata.
ROLLBACK[WORK] to [SAVEPOINT] nume_punct_salvare

Instructiunea ROLLBACK este utilizata pentru a reface un lucru.


Cuvantul cheie "work" este optional. Intoarcerea la un punct de salvare este de
asemenea optionala.
Daca se utilizeaza ROLLBACK fara clauza TO SAVEPOINT, atunci :
o se termina tranzactia
o se anuleaza modificarile din tranzactia curenta
o sterge toate punctele de salvare din tranzactie
o elibereaza blocarile tranzactiei

Intoarcerea la Nivel de Bloc


O parte a unei tranzactii poate fi anulata. Daca un singur bloc DML da eroare, ORACLE V6
va intoarce inapoi doar acel bloc. Aceasta facilitate este cunoscuta ca STATEMENT LEVEL
170

ROLLBACK. Intoarcerea la nivel de bloc inseamna daca un singur segment DML da eroare
la executia unei tranzactii, efectul lui este anulat, dar schimbarile realizate de precedentul
bloc DML in tranzactie nu vor fi anulate si pot fi inscrise (COMMIT) sau intoarse
(ROLLBACK) explicit de catre utilizator.
Daca blocul este unul de tip DDL, inscrierea (commit) care precede imediat acest bloc nu este
anulata (schimbarile au fost facute deja permanen- te). ORACLE realizeaza intoarcerea la
nivel de bloc prin crearea unui punct de salvare implicit inainte de executarea fiecarei
comenzi DML. Utilizatorul nu poate referi caest punct de salvare in mod direct.
Astfel, daca va intoarceti la un punct de salvare, atunci:

anulati o parte din tranzactie


se retine punctul de salvare pentru intoarcere, dar se pierd toate celelalte punct create
dupa punctul de salvare numit.
se elibereaza toate blocarile de tabele si linii.

Intoarceri Implicite
Intoarcerile implicite apar cand se intalnesc terminari anormale ale executiei (de exemplu
cand se intrerupe un proces utilizator). Intoarcerile implicite la nivel de bloc apar la eroarea
de executie a unui bloc.
Este recomandat ca tranzactiile sa se termine explicit utilizand COMMIT[WORK] ori
ROLLBACK[WORK].
Urmatorul exemplu demonstreaza utilizarea unui punct de salvare, si a instructiunilor
ROLLBACK si COMMIT.
INSERT INTO DEPT
VALUES
( 50, 'TESTING', 'LAS VEGAS' );
SAVEPOINT insert_done;
UPDATE DEPT
SET DNAME = 'MARKETING';
ROLLBACK TO insert_done ( modificarile sunt abandonate );
UPDATE DEPT
SET DNAME = 'MARKETING' ( revizuim comanda UPDATE )
WHERE DNAME = 'SALES';
COMMIT;
AUTOCOMMIT

COMMIT sau ROLLBACK pot fi date manual sau automat prin utilizarea optiunii
AUTOCOMMIT a comenzii SET. Optiunea AUTOCOMMIT controleaza cand schimbarile
intr-o baza de date sunt facute permanente.

171

Exista doua setari :


COMANDA + DESCRIEREA
SET AUTO[COMMIT] ON
COMMIT este utilizat automat la fiecare INSERT, UPDATE sau DELETE
SET AUTO[COMMIT] OFF
COMMIT poate fi utilizata de utilizator explicit. De asemenea, COMMIT se executa
cand apare comanda Z (specifica VAX), cand se executa comenzile DROP, ALTER
sau CREATE, sau la iesirea din SQL*Plus. ROLLBACK poate fi executat explicit de
catre utilizator pentru refacerea bazei de date.
De retinut ca SET este o comanda SQL*Plus.

Consistenta la Citire
Utilizatorii bazelor de date fac doua tipuri de accesuri asupra bazelor de date:

Operatii de citire ( SELECT )


Operatii de scriere ( INSERT, UPDATE, DELETE )

Cititorului si scriitorului unei baze de date trebuie sa i se garanteze o vedere consistenta


asupra bazei de date. Cititorii nu trebuie sa vizulaizeze o data care este in curs de modificare.
Si scriitorii trebuie sa fie siguri ca schimbarile intr-o baza de date sunt facute intr-un mod
consistent : schimbarile facute de un scriitor sa nu distruga sau sa intre in confilct cu
schimbarile pe care le face un alt scriitor.
Scopul consistentei la citire este acela de a asigura faptul ca fiecare utilizator vede data ca
fiind cea de la ultimul COMMIT, inainte ca o operatie DML sa inceapa.
Consistenta la citire este implementata prin tinerea unor copii partiale ale bazei de date in
segmente de intoarcere (ROLLBACK).
Cand de executa operatii de scriere intr-o baza de date, ORACLE va face o copie a datelor
onainte de schimbare si o va scrie intr-un segment de intoarcere.
Toti cititorii, exceptandu-i pe cei care au facut schimbarile, inca mai vad baza de date care
exista inainte ca schimbarile sa fie facute - ei vad segmentul de intoarcere de fapt.
Oricum, inainte ca schimbarile sa fie facute permanente in baza de date, doar utilizatorul care
modifica datele poate sa vada baza de date cu alteratiile incorporate. Toti ceilalti vad baza
nemodificata ( fereastra din segmentul de intoarcere ). Aceasta garanteaza citirea unor date
consistente care nu fac subiectul unor modificari in curs.
Cand un bloc DML se executa, schimbarile facute in baza de date devin vizibile oricarui
utilizator care executa SELECT. Modificarile sunt facute 'universale' si acum toti utilizatorii
vad baza de date cu modificarile incorporate.
Spatiul ocupat de catre 'vechile' date in segmentul de intoarcere este eliberate pentru a fi
reutilizat.
172

Daca tranzactia este anulata (ROLLBACK), atunci toate schimbarile sunt 'anulate' :

Versiunea veche ('originala') a bazei de date aflata in segmentul de intoarcere este


scrisa inapoi ('recuperata') in baza de date.
Toti utilizatorii vad baza de date existenta inainte de inceperea tranzactiei.

Tranzactii de Citire
Implicit, modelul consistent al ORACLE RDBMS garanteaza ca rezultatul
executiei unui bloc este consistenet. Oricum, in anumite situatii se poate dori
chestionarea unor blocuri multiple asupra datelor din mai multe tabele si se
doreste asigurarea ca datele sunt consistente. Adica, re- zultatele in orice
tabela sunt consistente in timp in raport cu rezultatele din orice alta tabela.
Linia SQL : SET TRANSACTION READ ONLY este utilizata pentru a
incepe o tranzactie de citire exclusiv.
Consistenta la citire pe care READ ONLY o furnizeaza este implementa- ta in
acelasi fel cu consistenta la nivel de bloc - utilizand segmente de intoatcere.
Fiecare bloc vede implicit o fereastra consistenta a datelor la momentul
inceperii blocului. Aceasta facilitate este foarte folositoare pentru rapoarte care
ruleaza mai multe chestionari asupra mai multor tabele in timp ce alti
utilizatori actualizeaza aceleasi tabele.
Note :
SET TRANSACTION READ ONLY este utilizata pentru a incepe o
tran- zactie doar de citire.
Doar cereri ( blocuri SELECT ) sunt permise. Comenzile DML nu sunt
permise. SELECT FOR UPDATE va genera o eroare.
O instructiune COMMIT, ROLLBACK, sau un bloc DDL va termina
tran- zactia de citire ( de retinut ca blocurile DDL genereaza implicit
suprascrieri - COMMIT ). Cu blocuri DDL, nu este data nici o indicatie referitoare la faptul ca tranzactia se termina implicit.
In timpul tranzactiei de citire, toate cererile se refera la aceeasi copie a
bazei de date ( schimbarile sunt efectuate inainte ca tranzactia de citire
sa inceapa).
Alti utilizatori pot continua sa citeasca sau sa modifice datele.
Urmatoarele seturi de instructiuni pot fi rulate pentru a extrage datele din
tabelele EMP si DEPT.
COMMIT;
SET TRANSACTION READ ONLY;
SELECT DEPTNO, ENAME, JOB
FROM EMP;
SELECT DEPTNO, DNAME
FROM DEPT;

173

COMMIT;

Ultimul COMMIT este necesar pentru a termina explicit tranzactia de citire.

EXERCITII - limbajul de manipulare a datelor


Exercitiile acopera inserarea si modificarea de coloane in tabelele create
anterior.
1. Inserati in tabela PROJECTS urmatoarele informatii :
PROJID
P_DESC

1
WRITE C030 COURSE

2
PROOF READ

P_START_DATE
P_END_DATE
BUDGET_AMOUNT
MAX_NO_STAFF
COMMENTS

02-JAN-88
07-JAN-88
500
1
BE CREATIVE

01-JAN-89
10-JAN-89
600
1
YOUR CHOICE

NOTES

2. Inserati in tabela ASSIGNMENTS urmatoarele coloane:


PROJID
EMPNO
A_START_DATE
A_END_DATE
BILL_RATE
ASSIGN_TYPE
HOURS

1
7369
01-JAN-88
03-JAN-88
50.00
WR
15

1
7902
04-JAN-88
07-JAN-88
50.00
WR
20

2
7844
01-JAN-89
10-JAN-89
45.50
PF
30

3. Modificati campul ASSIGNMENT TYPE astfel incat sa se


citeasca
'WT' in loc de 'WR'. Un tip ca 'PF' trebuie sa ramana
nemodificat.
4. Inserati inca doua proiecte cu atribuiri la alagere.

REZOLVARI:
1.

INSERT INTO PROJECTS


(PROJID, P_DESC, P_START_DATE, P_END_DATE,
BUDGET_AMOUNT, MAX_NO_STAFF)
VALUES
(1,'WRITE C030 COURSE','02-JAN-88','07-JAN-88',500,2);
INSERT INTO PROJECTS
(PROJID, P_DESC, P_START_DATE, P_END_DATE,
BUDGET_AMOUNT, MAX_NO_STAFF)
VALUES
(2,'PROOF READ NOTES','01-JAN-89','10-JAN-89',600,1);

2.

INSERT INTO ASSIGNMENTS


(PROJID, EMPNO, A_START_DATE, A_END_DATE,BILL_RATE,
ASSIGN_TYPE, HOURS)
VALUES
(1,7369,'01-JAN-88','03-JAN-88',50.00,'WR',15);

174

INSERT INTO ASSIGNMENTS


(PROJID, EMPNO, A_START_DATE, A_END_DATE,BILL_RATE,
ASSIGN_TYPE, HOURS)
VALUES
(1,7092,'04-JAN-88','07-JAN-88',50.00,'WR',20);
INSERT INTO ASSIGNMENTS
(PROJID, EMPNO, A_START_DATE, A_END_DATE,BILL_RATE,
ASSIGN_TYPE, HOURS)
VALUES
(2,7844,'01-JAN-89','10-JAN-89',45.50,'PF',30);
3.

UPDATE ASSIGNMENTS
SET ASSIGN_TYPE='WT'
WHERE ASSIGN_TYPE='WR';

175

C A P I T O L U L 15
CONCURENTA SI BLOCAREA : O VEDERE GENERALA
Scopul acestui capitol este acela de a arata cum ORACLE gestioneaza blocarea.
Ariile acoperite sunt :

Tipuri si nivele de blocari


Blocarea normala
Blocari implicite si explicite
DEADLOCK

Blocari
ORACLE utilizeaza blocarile pentru a controla accesul concurent la date. Blocarile sunt
mecanisme pentru a preveni interactiunea destructiva intre utilizatorii care acceseaza aceleasi
date.
Blocarile sunt utilizate pentru a atinge doua scopuri importante:
CONCURENTA DATELOR

Utilizatorii care doresc sa citeasca adeleasi date sa nu astepte utilizatorii care scriu
aceleasi blocuri de date.
Utilizatorii care doresc sa scrie datr in baza de date sa nu astepte utilizatorii care
citesc aceleasi date.
Utilizatorii care vor sa scrie date asteapta doar ulilizatorii care modifica aceleasi linii.
CONSISTENTA LA CITIRE
Fiecare bloc de instructiuni executat are o vedere consistenta asupra
datelor din baza de date.
Fiecare bloc nu este afectat de catre nici o schimbare efectuata de catre
alt utilizator in timpul executiei acestiua.
Pentru a asigura concurenta datelor, ORACLE utilizeaza blocari si tranzactii.
Blocarile sunt mecanisme utilizate pentru a preveni interactiunea destructiva
intre utilizatorii care acceseaza aceleasi resurse.

Blocarile in ORACLE intra in urmatoarele categorii :


Blocari de date ( DML locks )
Aceste blocari protejeaza datele. Blocarile de tabele blocheaza intreaga tebela,
in timp ce blocarile de coloane blocheaza doar coloanele selectate.
Blocari de Dictionar ( Dictionary Locks )

176

Aceste blocari protejeaza structura de obiecte a bazei de date; de exemplu ele


protejeaza definitiile tebelelor si vederile (views). Blocarile de dictionar sunt
de doua tipuri : blocari sintactice (parser) si blocari DDL.
In acest curs ne vom concentra doar asupra blocarilor de date.

Nivele de Blocare
Blocarile pot fi aplicate la nivelul unie tabele sau al unei linii.
Nivel de Linie
Afecteaza liniile individual. Doar blocarile exclusive (x) se aplica la nivel de linie.
Nivel de Tabela
Afecteaza utilizarea intregii tabele.

Tipuri de Blocari
Mod blocare
Actiuni
Actiuni
Obtinut
prin
Prescurtare
interzise
permise
comenzile SQL
------------------------------------------------------------------------Share
Modificari
Blocare linii,
LOCK
TABLE tabela
-SRX,SRX,X
RS,S,cereri
IN
SHARE MODE
Exclusive
TABLE tabela
-XEXCLUSIVE MODE

Toate exceptand

Cereri

LOCK

cereri,RS,RX,S,

IN

SRX,X

si

majoritatea
blocurilor DDL
Row share
Acces exclusiv,
SELECT...FOR UPDATE,
-RSX
TABLE tabela IN

Modificari,
RS,RX,S,SRX,

LOCK

cereri

ROW

SHARE MODE
Row exclusive
UPDATE,INSERT,
-RXLOCK TABLE

Acces exclusiv

modificari

pentru citire/

RX,RS,

DELETE,

scriere,S,SRX,X

cereri

tabela

Citirea tabelei

Blocare linii

LOCK

in intregime,RX,

RS,cereri

IN

IN ROW
EXCLUSIVE MODE
Share row
TABLE tabela
exclusive
SHARE ROW

177

-SRXS,SRX,X
EXCLUSIVE MODE
--------------------------------------------------------------------------

Sumarul Blocarilor de Tabela (TM)


Blocurile care modifica linii explicite dintr-o tabela obtin mereu EXCLUSIVE
ROW LOCKS (blocari exclusive de linie) si o blocare de tabela
corespunzatoare.
EXCLUSIVE (X)
Blocarile exclusive permit cererile de interogare in resursa blocata dar interzic orice
alta acti- vitate in tabela.
SHARE (S)
Blocarile de acest tip permit interogarile dar interzic modificarile intr-o tabela.
ROW SHARE (RS)
Permite accesul concurent la o tabela. Interzice ca alti utilizatori sa blocheze tabela
pentru acces exclusiv.
ROW EXCLUSIVE (RX))
Sunt asemanatoare cu ROW SHARE dar interzic blocarea in mod SHARE. Aceste
blocari sunt generate la modi- ficare,inserare sau stergere.
SHARE ROW
Sunt folosite pentru a vizualiza o tabela pentru a
EXCLUSIVE (SRX)
executa modificari selectiv si pentru a permite altor utilizatori sa vizualizeze tabela
fara a o bloca in modul SHARE sau a modifica linii. Acest mod nu prea este utilizat.
Abreviatiile din paranteze sunt cele utilizate in Lock Monitor al SQL*DBA.
Blocarile manuale pot fi cerute de optiunea NOWAIT atunci cand utilizatorul nu doreste sa astepte ca resursa blocata sa fie eliberata.

Durata Blocarilor
Toate blocarile acumulate de-a lungul unei tranzactii sunt elibe- rate
cand tranzactia se termina.
Toate blocarile acumulate de-a lungul unei tranzactii sunt elibe- rate
cand tranzactia se intoarce .
Toate blocarile acumulate dupa un punct de salvare sunt eliberate cand
tranzactia se intoarce la punctul de salvare.

Blocarea implicita
Blocarile care apar in timpul unui DML normal, fara o cerere specifica de
blocare.

178

tabela

+--------------

+----------------------+

| Utilizator A

+--------------

+
|
|

+
|
|
UPDATE, INSERT
|
DELETE o linie
|
ROW
EXCLUSIVE
|
|
|
|
+
|
|
v
+

+----------------------+
|
|
# EXCLUSIVE
| <-------------+
+----------------------+

sau

|
|
|
|
|
|
|
|
+----------------------+
|
# EXCLUSIVE
| <-------------+
+----------------------+
+------+------|

+----------------------+

| Utilizator B
+-------------UPDATE, INSERT

sau DELETE

Blocarile Datelor
Blocarea manuala poate fi preferata daca :
O vizualizare consistenta asupra mai multor tabele este ceruta.
Nu doriti ca altcineva sa modifice datele saupra carora opereaza
tranzactia dumneavoastra.
Un bloc de instructiuni nu trebuie sa astepte o blocare.
O cerere este de citire repetata dintr-o tabela fara a schimba datele.
Blocurile de instructiuni care modifica blocarile implicite sunt :
Selectiile pentru modificari
Blocarile de tabele.
Blocarile manuale pot fi preferate blocarilor implicite in multe cazuri. Acestea
pot include vizualizarea consistenta a unor tabele. Un exemplu poate fi un
master si cateva tabele detaliate.
O tranzactie poate dori schimbarea unor date bazata pe alte inregistrari, dar
inregistrarea respectiva nu trebiue modificata pana cand nu se termina toata
tranzactia.
Un bloc nu trebuie sa astepte dupa nici un alt bloc ca sa se termine evitandu-se
astfel conflictele de blocare.
Un utilizator poate dori sa vada oun set de date in aceeasi stare in
cereri multiple: principiul 'citirii repetate'.

179

Comanda LOCK TABLE


Comanda LOCK TABLE este utilizata pentru a bloca la nivel de tabela
explicit :
LOCK TABLE tabela, tabela, ...
IN mod_de_blocare [NOWAIT]

Instructiunea SELECT FOR UPDATE


Modifica blocarea implicita
Blocheaza liniile cand acestea sunt selectate
Blocheaza o linie fara a o modifica

SELECT FOR UPDATE va suprascrie mecanismul implicit de blocare. Este


utilizata inaintea executiei unei modificari ( update ). Diferenta dintre
SELECT FOR UPDATE si UPDATE este aceea ca SELECT FOR UPDATE
blocheaza lini ile mai devreme in tranzactie. Mai intai se executa cererea de
identificare a liniilor ce vor fi modificate si dupa aceea blocheaza setul de linii,
per mitand ca schimbarile sa aiba loc mai tarziu.

Sintaxa :
SELECT ...
FOT UPDATE [ OF coloana, coloana, ... ] [NOWAIT]

SELECT FOR UPDATE este recomandata pentru cazul cand se doreste


blocarea unei linii fara modificare de exemplu, daca se doreste pornirea unei
modificari a unor valori deja existente in linii, liniile nu trebuie sa poata fi
modificare de catre altcineva inainte de suprascriere.
O cerere SELECT FOR UPDATE elibereaza blocarile la COMMIT sau
ROLLBACK. Este indicat sa se utilizeze SELECT FOR UPDATE pentru
cateva linii decat pentru un numar mare de linii.
+---------------------------+
|
|
|
|
|
|
| 1. SELECT...FOR UPDATE OF |
|
|
|
|

180

1. ROW LOCK(X)
2. TABLE LOCK(RS)

3. TABLE LOCK(RX)

|
|
+---------------------------+

Deadlock
Este foarte posibil intr-un mediu multi-utilizator, ca utilizatorii isi vor bloca
unii altora resursele. Este de asemenea posibil ca doi utilizatori sa sfarseasca
prin a-si bloca unul altuia resurse diferite. Aceasta situatie se numeste
DEADLOCK deoarece fiecare utilizator asteapta sesursele detinute de celalalt
utilizator.

De exemplu :
Tranzactia A

Tranzactia B

UPDATE EMP
SET SAL=1200
WHERE ENAME = 'SMITH';

UPDATE EMP
SET SAL=1000
WHERE ENAME = 'JONES';

UPDATE EMP
SET SAL=2200
WHERE ENAME = 'JONES';

UPDATE EMP
SET SAL=1350
WHERE ENAME = 'SMITH';

Cand primul bloc este executat, nu exista nici o problema. Oricum, cand ei vor
incerca sa obtina blocarile pentru al doilea bloc, se va astepta in spatele
celuilalt utilizator. Este deadlock deoarece nici macar prin asteptare problema
nu va fi rezolvata.
Cand ORACLE detecteaza un deadlock, genereaza o eroare la unul dintre
participantii tranzactiei, si intoarce blocul curent al tranzactiei respective.
Aceasta rezolva deadlock-ul, astfel celalalt utilizator poate inca astepta pana
cand resursa este disponibila. Utilizatorul semnalizat ar trebui sa execute
explicit un ROLLBACK in tranzactie.
Deadlock-ul poate fi evitat daca utilizatorii care acceseaza aceleasi tabele
blocheaza tabelele in aceeasi ordine ca ceilalti. Ar trebui predefinita o ordine
de acces pentru toate tabelele in aplicatii si aplicatiile astfel construite incat sa
urmeze ordinea specificata. Daca aceasta ordine este urmata in toate
aplicatiile, probabilitatea de aparitie a dead-lock va fi minima.
Blocarile de date sunt eliberate de :
COMMIT / ROLLBACK
LOG OFF
Orice bloc explicit DDL.
ROWID (id. de linie) si Blocarea

181

COL ROWID VALOARE_NOUA IDENTIFICATOR_LINIE NOPRINT


SELECT ENAME, JOB, HIREDATE SAL, ROWID
FROM EMP
WHERE WNAME = 'SCOTT'
FOR UPDATE

ROWID

+--------------------+
| 00004C90.0001.0001 |
+--------------------+

UPDATE EMP
SET JOB = 'SALESMAN,
HIREDATE=SYSDATE,
SAL=1.1*SAL
WHERE ROWID='&ROW_IDENT'

Este important sa se eexcute COMMIT cat mai cutand posibil pentru ca


blocarile sa fue eliberate devreme.
Procesul COMMIT poate fi accelerat prin folosirea ROWID pentru a localiza
liniile in tabele. ROWID este o pseudo-coloana care are cate o valoare pentru
fiecare linie din tabela. ROWID ne spune adresa unei linii si prin aceasta este
cea mai rapida cale de acces disponibila. Intoarce trei parti de informatie
necesare pentru a localiza o linie :

ROWID

00004C90.0001.0001

Care bloc in fisierul bazei de date (00004C90)


Care linie din bloc (0001)
In care fisier din baza de date este (0001)
Cand este creat ROWID ?
ROWID este creat automat de ORACLE cand o linie este modificata cu succes
intr-o tabela de baze de date; cand o inserare este facuta permanenta.
De ce sa utilizam ROWID ?
ROWID are cateva utilizari importante :
Sunt cele mai rapide mijloace de accesare a unei linii explicite
Sunt identificatori unici pentru linii in tabele.
De notat ca se poate executa UPDATE / DELETE pe o linie cu ROWID doar
daca linia respectiva a fost inainte blocata (adica SELECT FOR UPDATE).

182

C A P I T O L U L 16
IMAGINI (VIEWS)

Ce este o Imagine ?

O imagine este ca o fereastra prin intermediul careia datele din tebele pot fi
vizualizate sau schimbate.
O imagine este derivata dintr-o alta imagine sau tabela la care este referita ca tabela de
baza a imaginii - o tabela 'reala' cu date care sunt stocate fizic.
O imagine este stocata doar ca o secventa SELECT. Este o tabela virtuala - adica este
o tabela care nu exista fizic, dar ii apare utilizatorului ca si cum ar exista.
O imagine nu are date proprii. Ea manipuleaza datele din tabela de baza asociata.

Imaginile sunt utile pentru urmatoarele scopuri :

Ingradirea accesului la o baza de date. Selectand dintr-o imagine (VIEW) putem afisa
o parte restransa din baza de date.
Permite utilizatorilor sa faca cereri simple pentru obtinerea de rezultate din cereri
complicate. De exemplu, imaginile permit utili- zatorilor sa selecteze informatii din
tabele multiple fara cunoas- terea mecanismelor instructiunii JOIN.
Furnizeaza independenta datelor pentru useri ad-hoc si programele aplicatiilor. O
imagine poate fi utilizata pentru a extrage trans- parent date din mai multe tebele. De
asemenea imaginile permit ca aceleasi date sa fie vazute de utilizatori diferiti in feluri
dife- rite.

Imagini Simple vs. Imagini Complexe


Clasificarea unei imagini simple :

furnizeaza date dintr-o singura tabela


nu contine functii sau grupuri (GROUP) de date.

O imagine complexa poate fi compusa din date care sunt :

furnizate din mai multe tabele


contine functii sau grupuri de date.

Comanda CREATE VIEW


CREATE
AS
SELECT

[ OR REPLACE ] [FORCE] VIEW nume-view


[(coloana1, coloana2, ...)]
secventa-select
[WITH CHECK OPTION [CONSTRAINT nume_constr]]

Coloana1, coloana2, etc. sunt numele date coloanelor in imaginesi trebiue sa corespunda
elementelor din lista selectata.

183

Pentru a crea o imagine simpla numita D10EMP, care contine unele detalii ale angajatilor din
Departamentul 10, introduceti :
CREATE
AS
SELECT
FROM
WHERE

VIEW D10EMP
EMPNO,ENAME,SAL
EMP
DEPTNO = 10;

Cand o imagine este creata, un mesaj este afisat : "View created."


Imaginea poate fi utilizata ca orice tabela :
SELECT
FROM
ODRER BY

*
D10EMP
ENAME;

Pentru a crea o imagine complexa numita DEPT_SUMMARY, care contine functii de grup si
date din doua tabele :
CREATE
AS
SELECT
FROM
WHERE
GROUP

VIEW DEPT_SUMMARY
( NAME, MINSAL, MAXSAL, AVSAL )
DNAME, MIN(SAL), MAX(SAL), AVG(SAL)
EMP,DEPT
EMP.DEPTNO = DEPT.DEPTNO
BY DNAME;

De notat faptul ca numele coloanelor alternative au fost specificate pentru imagine. Aceasta
este o cerinta pentru cazul cand elementele SELECTate nu sunt conforme cu conventia
denumirilor din tabele / coloane, sau daca orice coloana din imagine este derivata dintr-o
functie sau expresie.
De notat si faptul ca daca o coloana este utilizata intr-o cerere (ANNSAL), o imagine a unui
alias al coloanei ( nume alternativ pentru coloana in imagine ) nu e necesar. De exemplu :

CREATE
AS
SELECT
FROM
WHERE

VIEW DEPT20
ENAME, SAL*12 ANNSAL
EMP
DEPTNO = 20;

O imagine nu poate contine clauza ORDER BY. Clauza ORDER BY este specificata cand se
executa SELECT din imagine.

Optiunea OR REPLACE
184

Aceasta optiune permite ca o imagine sa fie creata chiar daca exista una cu acelasi nume,
astfel inlociundu-se vechea varianta a imaginii pentru proprietarul ei. Aceasta inseamna ca o
imagine poate fi alterata fara a fi abandonata, recreandu-se si redand privilegiile obiectului.

Optiunea FORCE
Aceasta optiune creaza o imagine chiar daca tabela de baza nu exista, sau sunt prea putine
drepturi pentru tabela respectiva. Oricum, tabela trebiue sa existe inainte ca imaginea sa poata
fi utilizata.

Utilizarea unei Imagini cu Operatii DML


Imaginile sunt facilitati puternice deoarece ele ne permit sa executam verificari de integritate
referentiale asupra datelor modificate prin utilizarea imaginilor.
Clauza WITH CHECK OPTION specifica faptul ca INSERT si UPDATE executate pein
intermediul imaginii nu permit crearea de linii noi pe care imaginea nu le poate selecta, si de
aceea mermite constrangerile de integritate si vreificarile validarilor de date sa fie fortate
asupra datelor ce vor fi inserate sau actualizate.
In urmatorul exeplu, o imagine numita D10EMP este creata cu WITH CHECK OPTION.
Aceasta inseamna ca doar linii care au DEPTNO = 10 pot fi inserate, actualizate sau sterse.
Adica nici o secventa DML nu poate sa adreseze imaginea decat daca conditiile clauzei
imaginii sunt indepli- nite.

CREATE
AS
SELECT
FROM
WHERE
WITH

VIEW D10EMP
EMPNO, ENAME, DEPTNO
EMP
DEPTNO = 10
CHECK OPTION;

Daca exista o incercare de a executa actiuni DML asupra liniilor pe care imaginea nu le poate
selecta intr-o claiza WHERE, se afiseaza eroare :

"ORA_01402 VIEW WITH CHECK OPTION


WHERE_Clause voilation."

Urmatorul exemplu va valida intratea oricarei comenzi INSERT/UPDATE astfel incat


numarul SAL sa fie intre 1000 si 2000, MGR va trebui sa aibe campul EMPNO valid, si
DEPTNO sa existe in tabela DEPT.

CREATE

VIEW EMP_DATA

185

AS
SELECT
FROM
WHERE
AND
AND
WITH

EMPNO, ENAME, JOB, MGR, SAL, DEPTNO


EMP
SAL BETWEEN 1000 AND 2000
MGR IN ( SELECT DISTINCT EMPNO
FROM EMP )
DEPTNO IN ( SELECT DEPTNO
FROM DEPT )
CHECK OPTION;

Pentru a crea o imagine care sa restranga accesul la detaliile personale ale unui angajat valid
in tabela EMP, si timpul de acces la orele de servici, atunci introduceti urmatoarea comanda :

CREATE
AS
SELECT
FROM
WHERE
AND
AND
WITH

VIEW EMP_DETAILS
EMPNO, ENAME, JOB, DEPTNO
EMP
ENAME = USER
TO_CHAR(SYSDATE,'HH24') BETWEEN 9 AND 17
TO_CHAR(SYSDATE,'D')
BETWEEN 2 AND 6
CHECK OPTION;

Cand creati o imagine cu WITH CHECK OPTION, trebiue s-i atribuiti un nume restrictiei
WITH CHECK OPTION.

CREATE VIEW EMPLOYEES( ID_NUMBER, NAME, DEPARTMENT)


AS
SELECT EMPNO, ENAME, JOB, DEPTNO
FROM EMP
WHERE DEPTNO IN ( SELECT DISTINCT DEPTNO FROM DEPT)
WITH CHECK OPTION CONSTRAINT DEPT_CHECK;

Aceasta restrictie previne inserarea unei coloane in tabela EMP cu un numar care nu exista in
tabela DEPT.
Cand comanda CREATE VIEW este executata in seventa SELECT care urmeaza AS nu e
executata; in loc este doar depozitata in dictionarul de date.
Cand accesati date, via o imagine, ORACLE executa urmatoarele operatii :

recupereaza definitia imaginii din dictionarul de date


verifica drepturile de acces
converteste cererea imaginii intr-o operatie echivalenta asupra tabelei sau tabelelor
asociate. Cu alte cuvinte, datele sunt recu- perate din, sau o actualizare este facuta
asupra, tabelei(lor) de baza.

186

Odata ca imaginea a fost creata, trebuie sa se execute o cerere la Tabela Dictionarului de Date
numita USER_VIEWS ca sa se vada conanda view.
Acesti parametrii SETabili vor influienta afisarea imaginii text :

Maxdata
Arraysize
Long

Imaginea text este memorata intr-o coloana de tipul de date Long si ar trebui setat
ARRAYSIZE la o valoare mica ( de ex. 1 ) pentru a vizualiza textul.

Modificarea Datelor prin Imagini


Dupa cum am discutat, restrictiile pot fi impuse cu ajutirul clauzei WITH CHECK OPTION
cand o imagine este creata. Mai sunt si alte constrangeri de care trebiue sa fiti atenti.
DELETE este interzis cand o imagine contine :
1.
2.
3.
4.
5.

conditie Join
functii de grup
clauza GROUP BY
comanda DISTINCT
ROWNUM (nr de ordine al randului dupa ce acesta a fost adus din baza de date).

UPDATE este interzis cand :


1. Oricare de mai sus
2. Coloane definite prin expresii ( de ex. SAL*12 )

INSERT este interzis cand :


1. Oricare de mai sus
2. Orice NOT NULL coloane nu sunt selectate de imagine ( ex. EMPNO )

Comanda DROP VIEW


Utilizati comanda DROP pentru a sterge o imagine. Aceasta comanda elimina definitia
imaginii din baza de date. Coloanele si liniile nu sunt afectate deoarece sunt stocate in
tabelele de unde a derivat fiecare ima- gine. Imaginile sau alte aplicatii bazate pe o imagine
stearsa devin in- valide.
De notat ca o imagine poate fi derivata dintr-o tabela sau de fapt dintr-o alta imagine !

187

Sintaxa DROP este :


DROP

VIEW nume_imagine;

Doar creatorul imaginii poate sa o stearga.

Exercitii - CAP 16 - Crearea si Utilizarea Imaginilor


1. Definiti o imagine care sa produca urmatoarea iesire cand este referita intr-o cerere.
Rulati o cerere pentru a testa imaginea.
2.
3.
4.
5.
6.

DEPTNO
AVERAGE
NO_COMMS
------ -----------10
2196.66667
0
20
2175
0
30
1566.66667
4

MAXIMUM

MINIMUM

SUM

NO_SALS

-------

-------

-----

--------

5000

1300

8750

3000

800

10875

2850

950

9400

-----

7. Utilizand imaginea de mai sus, extrageti urmatoarea informatie. Nuarul angajatului


trebuie introdus la rulare.
8.

EMPNO
AVERAGE
9.
----------10.
7902
2175

ENAME

JOB

SAL

HIREDATE

MINIMUM

MAXIMUM

---------

-------

----

---------

-------

-------

FORD

ANALYST

3000

05-DEC-83

800

3000

11. Creati o imagine care sa impuna urmatoarele restrictii la insrearea datelor in tabela
ASSIGNMENTS.
1. Projid trebuie sa fie mai mic de 2000.
2. Data de sfarsit trebiue sa fie dupa data de inceput.
3. Tiputile valide pentru Assign_type sunt PF, WT sau ED.
4. Bill_rate trebuie sa fie mai mic decat 50.00 pentru Assign_type PF, mai mic
de 60.00 pentru WT si mai mic de 70.00 pentru ED.
5. EMPNO trebuie sa fie valid.
6. Retineti clauza WITH CKECK OPTION.
SOLUTII - CAP 16
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.

CREATE

AS
SELECT

VIEW AGGREGATES
( DEPTNO, AVERAGE, MAXIMUM, MINIMUM, SUM,
NO_SALS, NO_COMMS )

FROM
GROUP

DEPTNO,
AVG(SAL),
MAX(SAL),
MIN(SAL),
COUNT(SAL),
COUNT(COMM),
EMP
BY DEPTNO;

SELECT

EMP.DEPTNO,

14.
15.
16.

188

17.
18.
19.
20.
21.
22.
23.
24.
25.
26.

FROM
WHERE
AND

ENAME,
JOB,
SAL,
HIREDATE,
MINIMUM,
MAXIMUM,
AVERAGE
EMP, AGGREGATES AGG
EMP.DEPTNO = AGG.DEPTNO
EMP.EMPNO = & EMPNO;

27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.

CREATE
AS
SELECT

VIEW ASG_VAL

PROJID,
EMPNO,
A_START_DATE,
A_END_DATE,
BILL_RATE,
ASSIGN_TYPE,
HOURS,
FROM
ASSIGNMENTS
WHERE
A_START_DATE < A_END_DATE
AND
PROJID < 2000
AND
BILL_RATE <= DECODE(
ASSIGN_TYPE,'PF',50,'WT',60,70)
42.
AND
EMPNO IN
43.
( SELECT EMPNO FROM EMP )
44.
WITH
CHECK OPTION;

45.

189

C A P I T O L U L 17
Utilizatorii si Securitatea
Sistemul de securitate descentralizata a lui ORACLE este explicat in acest capitol. In special
vom explica cum sa utilizati comenzile GRANT si REVOKE pentru a controla accesul la
baza de date si sa inregistrati noi utilizatori cu diferite niveluri de drepturi de acces.

Privilegiile si Functiile Sistemului


ORACLE utilizeaza un sistem de securitate descentralizat, unde utilizatorii sunt ei insisi
responsabili pentru acordarea drepturilor de acces pentru obiectele pe care le detin celorlalti
utilizatori. Oricum, inainte ca ei sa faca aceasta, un utilizator va avea nevoie de drepturile
importante ale sistemului care permit actiuni ca conectarea la o baza de date sau crearea de
obiecte.
Cand Administratorul Bazelor de Date a creat un nou utilizator ORACLE, un numar de
drepturi pot fi atribuite pentru a defini tiputile de activitati ale bazelor de date pentru fiecare
utilizator, este mult mai convenabil pentru Administratorul Bazelor de Date de a grupa
combinatiile obisnuite de drepturi in roluri (roles). rolurile corespunzatoare pot atunci fi
asignate utilizatorilor.

Privilegiile Sistemului
Sunt mai mult de 80 tipuri de drepturi ale sistemului disponibile pentru atribuite catre
utilizatori si roluri. Unele din cele mai importante sunt listate mai jos. Pentru o specificare
completa, vedeti "Oracle7 Server SQL reference Manual".
Drept Sistem
Operatii autorizate
CREATE SESSION
Permite posesorului conectarea la baza de date.
CREATE TABLE
Permite posesorului crearea de tabele. Uti- lizatorul trebuie de asemenea sa aiba o
cota intr-o "tablespace" (arie a bazei de date).
CREATE VIEW
Permite crearea imaginilor.
CREATE USER
Permite posesorului sa creeze alti utiliza- tori ORACLE (un drept cerut pentru o
functie DBA).

Roluri
Un rol este o colectie de drepturi sistem cu nume. Un utilizator poate avea acces la mai multe
roluri, si mai multi utilizatori pot fi atribuiti aceluiasi rol, dandu-se flexibilitate si usurinta
sistemului de securitate.
Sunt cateva roluri predefinite, ca DBA ( Administrator de Baze de Date ) care include toate
privilegiile sistemului, dar un DBA va crea de obicei roluri pentru cerintele sistemului.

190

Daca aveti atribuite mai multe roluri, puteti oscila intre ele in timpul unei sesiuni pentru a
activa sau nu drepturile asociate. Aceasta este realizata prin comanda SET ROLE.
De exemplu, pentru a activa un rol care are parola "marigold" atasata :

SET ROLE gardener IDENTIFIED BY marigold;

Pentru a activa toate rolurile exeptand un singur rol pentru un uti- lisator :

SET ROLE ALL EXCEPT manager;

Pentru a deactiva toate rolurile :

SET ROLE NONE;

Un utilizator va avea unele roluri implicite care sunt activate la intrare in sesiune. Acestea
sunt de obicei toate rolurile acordate utilizatorului, dar pot fi schimbate cu comanda ALTER
USER.

ROLURI
Acordarea de drepturi
fara roluri

Utilizatori
o
o
o
/|\
/|\
/|\
/^\
/^\
/^\
|
|
|
+----+--+-------+-------+
|
|
| |
| |
| +-----|-+--+--|-+-----|-+
| |
| |
| | | | |
| | +---|-|-+---|-|-++--|-|-+
/\+ |
/\+ |
/\+ |
/\+ |
\/--+
\/--+
\/--+
\/--+
DREPTURI

Acordarea de drepturi
utilizand roluri
o
/|\
/^\
\
\
\
\

o
/|\
/^\
|
|
|
|

191

o
/|\
/^\
/
/
/
/

Utilizatori

++---+---++
|
| <------------ ROL
+--+---+--+
| |
| |
+-------+ |
| +-------+
|
|
|
|
/\
/\ /\
/\
\/
\/ \/
\/
Privilegii
Schimbarea Parolei Utilizatorului

DBA atribuie utilizatorului o parola initiala cand utilizatorul este creat ( via CREATE USER
). Utilizatorul poate mai tarziu sa-si schimbe parola utilizand comanda ALTER USER.
Sintaxa :
ALTER USER nume_utilizator IDENTIFIED BY parola
De exemplu :
ALTER USER glenn IDENTIFIED BY swordfish;

De notat ca de asameni comanda poate fi utilizata pentru a scimba parola proprie, alte optiuni
in ALTER USER pot necesita unele drepturi ale sistemului pentru a se incheia cu succes.

Comanda GRANT

Este utilizata pentru a atribui drepturile unui obiect catre


o un utilizator
o un rol

Atribiurea unui utilizator :


GRANT priv1, priv2, ... ON nume_obiect
TO utilizator, utilizator, ... [ WITH GRANT OPTION ]
Atribuirea catre un rol :
GRANT priv1,priv2, ... ON nume_obiect
TO rol, rol, ...

'nume_obiect' poate referi :


o o tabela
o o imagine (view)
o o secventa (sequence)
o un sinonim (synonym)
o o procedura
o o functie
192

un pachet (package)

Privilegiile unui Obiect


Detineti fiecare tabela, imagine, secventa si sinonim pe care il creati. Daca nu doriti sa
impartiti un astfel de obiect cu alti utiliza- tori ORACLE, doar dumneavoastra si orice DBA il
poate accesa.
Pentru a permite accesul altor utilizatori la obiectele bazei de date, utilizati comanda GRANT
:
GRANT
ON
TO

drepturi
obiect
utilizator;

Tabelul de mai jos arata drepturile care pot fi acordate la tabele si imagini.
Drept
----SELECT
INSERT
UPDATE
DELETE
ALTER
INDEX
REFERENCES

Obiect
-----date in tebele sau imagini
linii in tabele sau imagini
linii sau coloane specificate intr-o tabela sau
imagine
linii dintr-o tabela sau imagine
definitii de coloane in tabele
indexare la o tabela
se refera la o tabela numita in interiorul unei
restrictii de tabela sau coloana.

ALL

De notat ca ALTER, INDEX si REFERENCES nu sunt valabile ca optiuni cu imagini.


Doar ALTER si SELECT pot fi aplicate unor secvente.
Cel mai simplu fel de GRANT este unul care acorda un singur drept unui singur utilizator.
Pentru a acorda lui ADAMS dreptul de SELECT din tabela DEPT, introduceti :

GRANT
ON
TO

SELECT
DEPT
ADAMS;

Grant succeeded.
Mesajul :
Grant succeeded.
confirma acordarea dreptului.

193

Pentru a acorda dreptul UPDATE pentru anumite coloane lui ADAMS, introduceti :
GRANT
ON
TO

UPDATE ( DNAME, LOC )


DEPT
ADAMS;

Pentru a acorda mai multe drepturi odata, introduceti toate drepturile separate prin virgule.
Similar, pentru a acorda mai multe privilegii mai multor utilizatori, introduceti numele
utilizatorilor separate prin virgule.
Pentru a acorda drepturile INSERT si UPDATE asupra DEPT lui ADAMS si JONES,
introduceti :

GRANT
ON
TO

INSERT, UPDATE
DEPT
ADAMS, JONES;

Grant succeeded.

Pentru a acorda toate privilegiile asupra DEPT lui ADAMS, introdu ceti :
GRANT
ON
TO

ALL
DEPT
ADAMS;

Grant succeeded.
Transmiterea de Privilegii care au fost Acordate.

Cand s-a acordat un drept de acces, utilizatorul care primeste dreptul, in mod normal nu
primeste si autorizarea de a transmite acest drept si altora. Pentru a da unui utilizator dreptul
de a transmite dreptul mai departe, utilizati clauza WITH GRANT OPTION.
Pentru a acorda dreptul SELECT asupra EMP lui ADAMS, cu autorizarea de a acorda acest
drept si altora, introduceti :
GRANT
ON
TO
WITH

SELECT
EMP
ADAMS
GRANT OPTION;

Grant succeeded.
Dreptul Public

Permite detinatorului unei tabele sa acorde accesul tuturor utilizatorilor cu o singura


comanda,
194

Acordarea da drept(uri) asupra unei tabele lui PUBLIC.


GRANT
ON
TO

SELECT
EMP
PUBLIC;

Secventa
Pentru a permite accesul asupra secventei lui Ford -F_SEQ- lui BLAKE, FORD va introduce
:
GRANT SELECT ON F_SEQ TO BLAKE;
Alte Obiecte

Comanda GRANT pate fi utilizata pentru a permite accesul utiliza torilor asupra procedurilor
stocate, functii si pachete (Oracle7 Procedural Option).
Puteti sa permiteti accesului unui rol asupra unui obiect. Fiecare utilizator caruia ii este
asignat acel rol poate utiliza obiectul respectiv.
De exemplu :
GRANT SELECT ON EMP TO ROLE_2;
Optiunea 'WITH GRANT OPTION' nu este permisa in acest caz.

Violarea Drepturilor de Acces

Daca incercati sa executati o operatie neutorizata ( de exemplu stergerea dintr-o tabela fara a
avea dreptul DELETE ), ORACLE nu va permite ca operatia sa aiba loc.
Daca primiti mesajul de eroare ORACLE ' table or view does not exist', aceasta poate
insemna doua lucruri :

aveti o tabela sau o imagine cu nume care nu exista


ati incercat sa executati o operatie asupra acelei tabele sau imagini pentru care nu
aveti drepturile corespunzatoare.

Comanda REVOKE
Pentru a retrage un drept acordat, utilizati comanda REVOKE. Este similara cu GRANT :
REVOKE
ON
FROM

drepturi
tabela sau imagine
utilizatori;

Cand utlilzati comanda REVOKE, drepturile specificate sunt anulate utilizatorilor enumerati,
si celorlalti utilizatori carora acestia le-au transmis aceste drepturi.

195

Pentru a anula toate drepturile asupra DEPT de la ADAMS, introduceti


REVOKE
ON
FROM

ALL
EMP
ADAMS;

Revoke succeeded.

Drepturile publice sunt retrase utilizand comanda REVOKE :


REVOKE
ON
FROM

SELECT
EMP
PUBLIC;

Pentru a afla acre utilizatori au drepturi asupra tabelelor imagi nilor sau secventelor dvs.,
executati o cerere catre imaginea Dictionarului de Date USER_TAB_GRANTS, sau
USER_COL_GRANTS.

Crearea unui SYNONYM pentru o Tabela, Imagine sau Secventa


Pentru a referi o tabela detinuta de un alt utilizator, trebuie sa prefixati numele tabelei cu
numele utilizatorului care a creat-o urmat de punct (.).
Pentru a referi tabela EMP detinuta de SCOTT, introduceti :
SELECT
FROM

*
SCOTT.EMP;

Alternativa este de a crea un sinonim ( alt nume ) pentru tabela sau imaginea data.
Pentru a referi tabela EMP a lui SCOTT doar cu numele 'EMP', introduceti :
CREATE SYNONYM
FOR

EMP
SCOTT.EMP;

Acum, cand executati o cerere asupra tabelei EMP a lui Scott, doar introduceti :
SELECT
FROM

*
EMP;

Doar DBA poate crea sinonime PUBLICe la care toti utilizatorii sa aiba acces.
CREATE PUBLIC SYNONYM
nume_sinonim
for [proprietar.] nume_obiect;

196

Un sinonim public poate fi eliminat prin tastarea :

DROP [ PUBLIC ] SYNONYM nume_sinonim;

Sinonimele sunt utilizate din motive de sceuritate si comoditate, incluzand :

pentru a referi o tabela, secventa sau imagine fara a specifica detinatorul obiectului
pentru a furniza un alt nume pentru tabela.

Din motive de performanta, du e recomandabila utilizarea de sinonime la referirea de tabele


in aplicatii.

197

CAPITOLUL 18
OBIECTE in BAZELE de DATE :
SECVENTIALE si INDEXATE
Acest paragraf descrie cum se poate indexa o tabela pentru a imbunatati timpul de raspuns in
cazul unei interogari.
Crearea si utilizarea accesului secvential este de asemenea discutata (aceasta permite
atribuirea automata de numere de secventa unice in cadrul unei aplicatii.)

Generatorul de numere de secventa


In server-ul Oracle versiunea 6, generatorul de numere de secventa poate fi utilizat
pentru a genera automat numere de secventa pentru rinduri in cadrul tabelelor. De
exemplu se poate folosi generatorul pentru a produce cheii primare unice.
Pentru a genera automat numere de secventa, trebuie sa definiti o secventa folosind
comanda CREATE SEQUENCE. Sintaxa este urmatoarea:
CREATE SEQUENCE [user.] sequence_name
[ increment by n]
[ start with n]
[ maxvalue n | nomaxvalue ]
[ minvalue n | nominvalue ]

Toti parametrii comenzii sunt optionali si au urmatoarea semnificatie:

o
o
o

o
o
o
o
o

user: proprietarul secventei.Implicit este user-ul care a generat comanda


CREATE SEQUENCE
sequence_name: numele de secventa care respecta conventiile SQL de
denumire a obiectelor
INCREMENT BY: determina intervalul dintre numerele de secventa generate.
Daca valoarea este pozitiva, atunci numerele de secventa vor creste. Daca
valoarea este negativa atunci acestea vor scade. Se poate folosi orice intreg
nenul. Implicit aceasta valoare este 1
START WITH: specifica primul numar de secventa care va fi generat. Implicit
este 1 pentru indexi crescatori si MAXVALUE pentru indici descrescatori
MINVALUE| valoarea minima a secventei ce va fi generata.Implicit este 1
NOMINVALUE pentru indici crescatori si 10E27-1 pentru indici
descrescatori
MAXVALUE| valoarea maxima ce va poate fi generata.Implicit este 1 pentru
NOMAXVALUE secvente descrescatoare, si -1 pentru secvente crescatoare.
Orice incercare de a genera numere de secventa peste aceasta valoare va esua
si se va intoarce un cod de eroare.

198

Urmatoarea comanda creaza o secventa pentru coloana DEPTNO a tabelei DEPT.


CREATE SEQUENCE dept_sep
INCREMENT BY 10
START WITH 10
MAXVALUE 10000;

Dupa ce o secventa a fost creata ea poate fi folosita pentru a genera numere unice de
secventa.

Generarea de numere de secventa cu NEXTVAL


NEXTVAL este utilizata pentru a extrage numere de secventa succesive dintr-o
secventa specificata. Cind se acceseaza NEXTVAL on nou numar de secventa este
generat.
SELECT dept_seq.NEXTVAL
FROM SYS.DUAL ;;
NEXTVAL
------------10

Daca se reexecuta comanda SQL anterioara valoarea creste cu 10.

SELECT dept_seq.NEXTVAL
FROM SYS.DUAL ;;
NEXTVAL
------------20

Prima valoare obtinuta este 10 si aceasta se incrementeaza apoi cu pasul 10.


Nota:

o
o

intodeauna se prefixeaza NEXTVAL cu numele de secventa


daca se refera NEXTVAL de mai multe ori pentru o singura comanda SQL
orice referire va intoarce aceasi valoare.

NEXTVAL este foarte folositoare in comenzi DML. De exemplu cind se completeaza

199

o tabela se poate folosi o secventa pentru a produce valori unice pentru coloana cu
cheii primare a tabelei. Exemplul urmator foloseste secventa dept_seq pentru a adauga
cheii primare unice in tabela DEPT.
INSERT INTO DEPT
VALUES
(dept_seq.NEXTVAL,

'ACCOUNTING', `NEW YORK');

1 record created
SQL> SELECT * FROM DEPT;
DEPTNO DNAME
-----------10

LOC
-------------ACCOUNTING

-----------------NEW YORK

Inaintea versiunii 6, numere unice de secventa erau generate la nivelul aplicatiilor. De


exemplu, o modalitate obisnuita de implementare este de a forta fiecare tranzactie sa
blocheze tabela cu numarul de secventa sa incrementeze secventa si apoi sa elibereze
resursa. In aceasta implementare, numai un singur numar de secventa poate fi generat
la un moment dat. Generatorul de numere de secventa ORACLE permite generarea
simultana a multiple numere de secventa de catre useri diferiti.

Cind un astfel de numar este generat, secventa este incrementata indiferent de


tranzactiile in desfasurare. Daca doi useri acceseaza aceeasi secventa in acelasi timp,
atunci fiecare user poate sa obtina eroare deoarece numere de secventa sunt de
asemenea generate de al doilea user. Doi useri nu vor genera niciodata acelasi numar
de secventa utilizind aceiasi secventa. Numere de secventa pot fi "sarite" daca un user
nu-si termina o tranzactie sau daca aceasta sfirseste in mod anormal.

Utilizarea numerelor de secventa cu CURRVAL


Pentru a accesa un numar de secventa care tocmai a fost generat (numarul de secventa
curent ) se foloseste pseudo-coloana CURRVAL. CURRVAL reprezinta ultima
valoare intoarsa unui program. Cind se adreseaza NEXTVAL pentru o secventa data,
numarul de secventa curent este plasat in CURRVAL. NEXTVAL trebuie folosit
pentru a genera numere de secventa in sesiunea curenta a unui user, inainte de a putea
adresa CURRVAL.
INSERT INTO DEPT_HISTORY
VALUES (dept_seg.CURRVAL, 'ACCOUNTING' , `NEW YORK');
1 record created.

200

SQL> SELECT * FROM DEPT_HISTORY


DEPTNO
DNAME
-----------------10

LOC
-----------ACCOUNTING

----------------NEW YORK

Reguli de folosire NEXTVAL si CURRVAL


NEXTVAL si CURRVAL pot fi folosite in cadrul:
clauza SELECT dintr-o declaratie SELECT (exceptie la afisari)
lista VALUES dintr-o declaratie INSERT
clauza SET dintr-o declaratie UPDATE
in afara SELECT
Restrictii de folosire NEXTVAL si CURRVAL
o
o
o
o

NEXTVAL si CURRVAL nu pot fi folosite:


o
o
o
o

intr-o lista SELECT din VIEW


impreuna cu cuvintul cheie DISTINCT
cu clauzele ORDER BY, GROUP BY, CONNECT BY, sau HAVING dintr-o
declaratie SELECT
cu operatorii UNION, INTERSECT, MINUS

Secventele sunt tratate in mod similar cu tabelele si pot fi modificate sau abandonate.
Proprietarul unei secvente poate de asemenea atribui privilegii si altor useri asupra
secventei.

Modificarea unei Secvente


Se foloseste comanda ALTER SEQUENCE pentru a modifica o secventa existenta.
AKTER SEQUENCE [user.]sequence_name
[INCREMENT BY n]
[MAXVALUE n | NOMAXVALUE]
[MINVALUE n | NOMINVALUE]

De exemplu pentru a seta o noua valoare maxima pentru secventa dept_deq,

ALTER SEQUENCE dept_seq


maxvalue 100000

Pentru a modifica o secventa este necesar sa fii proprietarul eu sau sa ai dreptul DBA

201

sau sa fi primit dreptul ALTER pentru secventa din partea proprietarului.


Nota:
Numai secventele viitoare vor fi influientate de catre comanda ALTER
SEQUENCE
o Sunt facute anumite verificari. De exemplu o noua MAXVALUE nu poate
impune care este mai mica decit numarul de secventa curent
o Valoarea START WITH nu poate fi schimbata folosint comanda ALTER
SEQUENCE
o Secventa trebuie abandonata si recreata pentru a reporni secventa la un numar
diferit.
Atribuirea drepturilor asupra Secventelor
o

Proprietarul unei secvente poate atribui altor useri drepturi de ALTER sau SELECT
asupra secventei, si WITH GRANT OPTION ramine valida.
Detalii in UNIT-ul 17.

Stergerea unei Secvente


Folositi comanda DROP SEQUENCE pentru a sterge o definitie de secventa.
Sintaxa este:
DROP SEQUENCE [user.]sequence_namel

Trebuie sa fii proprietarul secventei sau sa ai dreptul de DBA pentru a o sterge.


Pentru a sterge secventa dept_seq, tastati:

DROP SEQUENCE sept_seq;

Tiparirea Secventelor
Toate definitiile secventelor sunt memorate intr-o tabela de secvente. Pentru a vedea
secventele la care ai access, interogheaza baza de date urmarind
USER_SEQUENCES sau ALL_SEQUENCES.

Indexarea
Indexarea in sistemul ORACLE are doua principale scopuri:

1.

Pentru a accelera afisarea liniilor cu o cheie particulara.


2. Pentru a forta unicitatea valorilor din coloane, de obicei valorile cheii
principale.

202

Folosirea indexarii este puternic recomandata pentru a obtine performante mai bune.
Retineti ca ORACLE 7 creiaza automat INDEXI pentru coloanele care au setate
PRIMARY KEY sau UNIQUE.
Proprietarul unei tabele poate crea indexi pentru ea. Orice user ORACLE care detine
dreptul de access INDEX poate creea un index.
Odata creat, ORACLE va folosi index-ul ori de cite ori este posibil pentru a accelera
accesul datelor. Acest lucru se face in mod automat si deobicei nu este necesara
interventia userului care poate sa nu stie de existenta acestul index.

Structura unui INDEX ORACLE


ORACLE foloseste arbori B pentru indexare. Timpul de access este independent de
volumul de date indexat. Fiecare index construit de ORACLE contine un numar de
pagini memorate in arbore. Fiecare pagina contine un numar de cheii. ORACLE
gestioneaza aceasta structura la fel cum sunt inserate sau sterse linii. Valorile NULL
nu sunt memorate in index, si din fericire nu ocupa spatiu. -------- Aici se afla poza de
la pagina 18-9 --------

Tipuri de INDEX

TYPE
---------------UNIQUE
unice
NON UNIQUE
(implicit)
SINGLE COLUMN
CONCATENATED

Crearea unui Index

DESCRIERE
--------------------------------------------------asigura ca valorile din coloanele specificate sunt
asigura obtinerea cit mai repede a rezultatului
exista numai o coloana in index
mai mult de 16 coloane specificate in index.

Index ORACLE poate fi creat in linia de comanda cu comanda CREATE INDEX.


CREATE [UNIQUE] INDEX index_name
ON table (column [m]...)

Crearea unui INDEX pentru a imbunatati timpul de raspuns


Pentru a creea un index numit I_NAME care va fi folosit pentru a imbunatatii timpul
de interogare , introduceti:
CREATE INDEX I_ENAME
ON EMP (ENAME);

203

Crearea unui INDEX pentru a asigura unicitatea


Indecsi unici sunt creati automat ca un rezultat al constantelor PRIMARY KEY sau
UNIQUE in tabela. Oricum , se mai pot creea folosind comanda CREATE UNIQUE
INDEX.
Pentru a evita valori duplicate in coloana EMPNO, introduceti:
CREATE UNIQUE INDEX I_EMPNO
ON EMP (EMPNO);

Index-ul urmator asigura unicitatea valorii introduse in tabela SHIPMENTS.


Acesta este denumit index CONCATENATED.

CREATE UNIQUE INDEX ORDER


ON SHIPMENTS (S_Num, P_Num);

Stergerea unui INDEX


Pentru a sterge definitia unui index din tabela de date , introduceti:
DROP INDEX indexname;

Cind este folosit un INDEX ?


Folosirea unui INDEX depinde in parte de optimizatorul ORACLE in momentul
executiei. ORACLE 7 permite ambele metode de optimizare SQL, functie de un set
de reguli sau functie de cost.

Reguli de folosire al unui index


Oracle decide cind este adecvat sa foloseasca indexi. Oracle tine seama de coloanele
indexate si de tipul indexului si decide functie de urmatoarele reguli:

0.
Indexii de pe coloane trebuie adresati in clauza WHERE:
Urmatoarea interogare nu foloseste un index atita timp cit clauza WHERE nu este prezenta:
1.
2.
3.

SELECT ENAME,JOB,SAL,COMM
FROM

204

EMP;

Urmatoarea indetogare va folosi un index pe coloana ENAME:

SELECT
FROM
WHERE

*
EMP
ENAME = 'JHONES';

4.
Un index nu va fi folosit daca coloana referita in clauza WHERE face
parte dintr-o expresie sau functie.
Exemplul urmator nu foloseste index deoarece coloana este parte a unei
functii:
5.
6.
7.
8.

SELECT
FROM
WHERE

*
EMP
UPPER(ENAME)= 'JHONES';

In mod similar daca HIREDATE a fost indexata, aceasta interogare nu va


folosi index deoarece este o expresie:

SELECT
*
FROM
EMP
WHERE HIREDATE+7 = '01-JAN-84';

Utilizarea indexarii functie de cost


Modulul de optimizare bazat pe costul executiei decide un plan de executie pentru o
secventa SQL calculind costul cailor alternative folosind informatii statistice
acumulate daca este posibil. De obicei se va decide cea mai buna cale de utilizare a
unui index.

Sugestii pentru INDEXARE


o O tabela cu mai mult de 200 linii va beneficia din indexare pentru
imbunatatirea performantelor, daca mai putin de 10% din linii vor fi intoarse
in cazul unei interogari.
o Indexati toate coloanele acolo unde sunt cerute valori unice.
o Daca doua sau mai multe coloane sunt utilizate in mod frecvent impreuna in
clauza WHERE sau JOIN atunci creeati un index concatenat.
(CONCATENATED INDEX)
o Evitati mai mult de trei indexi pentru o tabela. In acest caz va fi o
supraincarcare in cazul unei operatii DML. (aceasta regula s-ar putea sa nu fie
205

valabila pentru tabele la care SELECT este operatiunea cea mai frecventa, de
exemplu tabele de referinte.)
Indexare si Imbinare
Daca nu exista index in cadrul coloanelor IMBINATE atunci se poate obtine o
"sortare-imbinata". Asca inseamna ca fiecare este sortata separat si apoi listele sortate
sunt imbinate . De obicei coloanele folosite pentru imbinari trebuie sa fie indexate.
Daca numai una din tabele are un index utilizabil, atunci cealalta tabela este tabela
conducatoare.
De exemplu:
SELECT
FROM
WHERE

ENAME, DNAME
DEPT, EMP
EMP.DEPTNO = DEPT.DEPTNO

Daca numai EMP.DEPTNO este indexata , atunci DEPT este tabela conducatoare.
Acest lucru este normal deoarece DEPT intoarce mai multe linii decit EMP. Daca
ambele sunt indexate, Oracle alege tabela conducatoare cintarind rangurile celor doua
sisteme. Daca rangurile sunt egale atunci Oracle alege tabela care este listata ultima in
clauza FROM.

Asa ca trebuie listate tabele mari cu cel mai mic numar de linii la sfirsitul clauzei
FROM.
SELECT
FROM
WHERE

ENAME, DNAME
EMP, DEPT
EMP.DEPTNO = DEPT.DEPTNO

Unit 18 Exercitii
0. Creati un indice neunic in coloana Projid a tabelei de atribuire.
1. Interogati tabela DDT (data dictionary table) pentru a obtine informatii despre
indexii folositi (USER_INDEXES).
Solutii:
2.
3.
4.

CREATE
ON

INDEX ASG_PROJID
ASSIGNMENTS
(PROJID);

SELECT

TABE_NAME, INDEX_NAME

5.
6.
7.

206

8.

FROM

USER_INDEXES;

9.

207

CAPITOLUL 19
INTRODUCERE IN PL/SQL
CE ESTE PL/SQL ?

Un limbaj procedural
Un vehicul pentru procesarea tranzactiilor
O tehnologie disponibila in citeva aplicatii ORACLE
O extensie SQL

Ce este PL/SQL ?
PL/SQL (Procedural Language /SQL) este o extensie la SQL, incorporind multe
facilitati ale limbajalor de programare din ultimii ani. El permite ca manipularea
datelor si procedurile de interogare din SQL sa fie incluse in blocuri stucturate si
proceduri, PL/SQL devenind astfel un puternic limbaj de procesare al tranzactiilor.

Avantaje ale PL/SQL

1. Stuctura de bloc
PL/SQL este un limbaj structurat, adica programele pot fi impartite in blocuri
logice, fiecare continind resursele necesare in acel bloc. variabilele pot fi
declarate local in cadrul unui bloc in care vor fi folosite, iar tratarea erorilor
(sau Exceptiile) se poate face in blocul in care apar.

2. Controlul executiei
Deciziile, buclele si salturile pot fi folosite pentru a controla executia
programelor, decizind daca si cind SQL si alte actiuni sa fie executate. Aceste
facilitati permit aplicatiilor ORACLE cum ar fi SQL*Forms, de a grupa
comenzi si de a controla executia lor prin PL/SQL.

3. Portabilitatea
Deoarece PL/SQL deriva din ORACLE, programele pot fo portate pe toate
masinile ce suporta ORACLE si PL/SQL.

208

4. Integrarea
PL/SQL joaca un rol din ce in ce mai important in RDBMS si in aplicatiile
ORACLE. Variabilele si tipurile de date din PL/SQL sunt compatibile cu cele
din SQL.PL/SQL acopera golul dintre nevoia de access la tehnologia bazelor
de date si nevoia de facilitati pentru programarea procedurala.

5. Performantele
Utilizarea PL/SQL poate ajuta la imbunatatirea performantelor aplicatiilor.
Avantajele difera , functie de mediul in care PL/SQL este folosit. Aceste
avantaje vor fi discutate mai tirziu in acelasi unit.
--------- Desene pag 19-4 --------

Structura PL/SQL
Fiecare unit al PL/SQL contine unul sau mai multe blocuri. Aceste blocuri pot fi
complet separate sau lipite unul de altul. Astfel, un bloc poate fi numai o mica parte a
altui bloc, care la rindul lui poate fi numai o parte din intreegul program.
De obicei, un bloc poate fi un bloc anonim sau un sub-program.

Blocuri anonime
Uzual sunt blocurile fara un nume. Aceste blocuri sunt declarate in punctul din
aplicatie unde vor fi folosite, si transferate modulului PL/SQL la momentul
executiei. Blocurile anonime pot apare in cadrul unui program precompilat
(sau program OCI) si cu SQL*Plus sau SQL*DBA. Partile de executie din
SQL*Forms contin asemenea blocuri.

Sub-programe
Acestea sunt denumite blocuri PL/SQL. Pot fi declarate ca proceduri sau ca
functii. In ultimul caz, ele intorc o valoare daca sunt apelate. SQL*Forms
permite ca procedurile si functiile sa fie declarate ca parte a Form-ului, si
apelate din orice punct.

In acest curs ne vom concentra mai mult asupra blocurilor anonime. Definirea unui
bloc anonim este urmatoarea:
--------------------------------------------------|
DECLARE
|
|
Definitia obiectelor PL/SQL care vor
|
|
fi folosite in acest bloc.
|

209

--------------------------------------------------|
BEGIN
|
|
Actiuni executabile
|
--------------------------------------------------|
EXCEPTION
|
|
Tratarea erorilor (cazuri de exceptie)
|
|
ce trebuie facut daca o actiune cauzeaza |
|
o eroare
|
|
END;
|
---------------------------------------------------

Cuvintele cheie BEGIN si END sunt obligatorii si delimiteaza corpul actiunii ce


urmeaza a fi executate. Sectiunea DECLARE este optionala si se foloseste pentru a
defini obiecte PL/SQL cum ar fi variabile folosite in cadrul blocului sau un bloc
inclus in acesta. La sfirsit sectiune EXCEPTION este folosita pentru a minui erori
predefinite, si defineste actiunile ce vor fi intreprinse daca astfel de conditii apar.De
asemenea, sectiunea EXCEPTION este optionala, si este plasata imediat inainte de
clauza 'END'.

Sa urmarim un exemplu de bloc, si sa fim atenti la structura si tipul actiunilor :


DECLARE
qty_on_hand
NUMBER(5);
BEGIN
SELECT quontity INTO qty_on_hand FROM inventory
WHERE product = 'TENNIS RACKET';
IF qty_on_hand > 0 THEN
UPDATE inventory SET quantity =
quantity -1
WHERE

product = 'TENNIS RACKET';

INSERT INTO purchase record


VALUES ('Tennis Racket purchased',
SYSDATE);
ELSE
INSERT INTO purchased_record
VALUES ('OUT of Tennis Rackets',
SYSDATE);
END IF;
COMMIT;
EXCEPTION
WHEN no_data_found THEN
INSERT INTO error_table
VALUES ('Product Tennis Rackets not
found');

210

END;

Retineti ca sectiunea de cuvinte cheie DECLARE, BEGIN, EXCEPTION nu sunt


urmare de ';' dar END si toate celelatle instructiuni PL/SQL au nevoie de ';'. Acest
lucru permite sa scriem mai multe instructiuni pe aceiasi linie daca avem nevoie.
Exemplul anterior daclara o variabila PL/SQL qty_on_hand si apoi foloseste
instructiunea SELECT pentru a completa cu Tennis Rackets. Tabela 'inventory' este
apoi actualizata daca valoarea este pozitiva.
Daca instructiunea SELECT esueaza in a gasi o linia cu acest produs, atunci se
genereaza eroarea 'no_data_found' si controlul este pasat imediat sectiunii
EXCEPTION unde problema este inregistrata in tabela de erori.

Mediul de lucru PL/SQL


PL/SQL nu este in sine un produs ORACLE. Este o tehnologie folosita de RDBMS si
de anumite aplicatii ORACLE. Blocuri ale PL/SQL sunt pasate de asemenea si
procesate de unitatea de executie PL/SQL. Unitatea folosita va depinde de locul in
care PL/SQL este apelat.

Unitatea de executie PL/SQL


Aceasta unitate executa instructiuni procedurale, dar trimite instructiuni SQL catre
Procesorul de Instructiuni SQL in cadrul ORACLE RDBMS. In acest fel unitatea de
executie filtreaza instructiunile SQL, si instructiunile procedurale ramase sunt
procesate in Unitatea de Executie A Instructiunilor Procedurale, care este in interiorul
unitatii de executie.

PL/SQL in programe SQL*Plus si SQL*DBA


Blocurile care sunt transmise din acest mediu sunt procesate de catre unitatea de
executie in RDBMS.SQL din cadrul blocului nu este spart in instructiuni separate
pina cind ajunge la unitatea PL/SQL, unde comenzile SQL sunt trimise unitatii de
executie SQL. Acest lucru inseamna ca un singur transfer este necesar pentru a trimite
blocul de la aplicatie la ORACLE, imbunatatind performantele in mod special intr-o
retea de tipul client-server. --------- Poza de la pag. 19-7 --------Folosirea PL/SQL in SQL*Plus este discutata in Unitul 2. Folosirea PL/SQL in alte
medii care folosesc unitatea RDBMS este subiect pentru viitoare cursuri.

PL/SQL in SQL*Forms V3, SQL*Menu V5 si Aplicatii CDE Oracle


Multe aplicatii ORACLE, incluzind partea din CDE (Medii de Dezvoltare
Cooperante) au propriile unitati de PL/SQL, care sunt independente de orice alta
unitate prezenta in RDBMS. Asa cum unitatile rezida in aplicatii comenzile SQL sunt
separate inainte de a fi transferate catre ORACLE.
Procesarea datelor locale aplicatiilor (care este in interiorul mediului de lucru client,
spre deosebire de baza de date) poate fi procesata de Procesorul de Instructiuni
PL/SQL, fata de folosirea SQL, deci reducind munca trimisa catre RDBMS, si
numarul de locatii de memorie necesare. ------------- Poza 19-8 -------------

211

Retineti ca Procedurile si Functiile declarate ca parte a aplicatiilor CDE si


SQL*Forms sunt diferite de acelea care pot fi stocate in baza de date cu optiunea
Procedural, altfel structura generala raminind aceiasi.

Facilitati PL/SQL
Urmatoarea parte a unit-ului discuta avantajele (facilitatile) ale PL/SQL comune
fiecarui mediu de lucru unde limbajul este instalat.
Acesta este un sumar.

Variabile si Constante
pentru memorarea si manipularea valorilor. Tipurile de date includ NUMBER,
CHAR si DATE.

SQL suport
SELECT, INSERT, UPDATE, DELETE, COMMIT, SAVEPOINT si
ROLLBACK sunt instructiuni suportate.

Tipuri de date compuse


Recordurile permit definirea grupurilor de cimpuri si folosirea in blocuri
PL/SQL. Versiunea 2 suporta de asemenea tabele, la fel ca sirurile.

Controlul Executiei
Instructiunea IF, Bucle, salturi (GOTO) si etichete ofera actiuni conditionale,
teste complexe, bucle iterative.

Functii Interne
Multe functii SQL sunt disponibile pentru a manipula variabile si valori
PL/SQL.

Tratarea Exceptiilor

212

Avertismentele si Erorile sunt definita ca exceptii, care pot fi minuite in


fiecare bloc. Exceptiile definite de user pot fi declarate si folosite la fel de bine
ca erorile standard ORACLE.

Stocarea de cod in baza de date


Optiunea Procedural din ORACLE suporta functii si proceduri care pot fi
memorate in baza de date si facute disponibile pentru toate aplicatiile.

213

CAPITOLUL 20
REPREZENTAREA DETELOR
In acest unit vom discuta tipurile de date suportate de PL/SQL, variabile scalare, si cum pot fi
manipulate datele si expresiile. Acest unit introduce de asemenea modul de utilizare al
PL/SQL cu SQL*Plus, care este o cale interactiva convenabila pentru testarea blocurilor pe
care le veti scrie.

Sintaxa de BAZA a PL/SQL


Din moment ce PL/SQL este o extensie pentru SQL, regulele sintactice de baza
aplicabile la SQL sunt aplicabile de asemenea si la PL/SQL.Iata un rezumat al
acestora:
o instructiunile pot avea mai multe linii daca este necesar dar cuvintele cheie nu
pot avea mai multe linii.
o Unitatile lexicale (identificatorii, numele de operatori) pot fi separate de unul
sau mai multe spatii, sau alt delimitator care nu poate face parte din unitati
lexicale
o Cuvintele rezervate (Vezi apendizul B) nu pot fi folosite ca identificatori decit
marcate in ghilimele duble( de ex. "SELECT"_
o Identificatorii trebuie sa inceapa cu o litera si pot contine pina la 30 de
caractere.
o Sirurile trebuie marcate cu ghilemele simple.
o Numerele pot fi reprezentate prin valoarea lor (ex. -32.65) sau scrierea
stiintifica ( ex. 2E5 inseamna 2x10 la puterea 5 = 200000 ).
o Comentariile pot fi marcate cu simbolurile /* si */, caz in care comentariile se
pot lungi pe mai multe linii ( tip 'C') sau incepind cu '--' in care sfirsitul liniei
marcheaza sfirsitul comentariului.

Exemplu:
/*

Acesta comentariu se prelungeste pe


mai multe linii. Orice secventa de cod
aflata aici este considerata comentariu.

COMMIT;

*/

--Aici se termina transferul

Delimitatori
Delimitatorii sunt simboluri sau simboluri compuse, care au o semnificatie speciala
pentru PL/SQL. Veti recunoaste multe dintre acestia ca operatori pentru SQL.

214

Simboluri simple Acestea sunt formate dintr-un singur caracter


-----------------------------------------------------------------+
*
/
=
>
<
)
(
;
,
.
@
'
:

operatorul de adunare
operatorul de scadere/negare
operatorul de multiplecare
operatorul de impartire
operator relational
operator relational
operator relational
delimitator de lista sau expresii
-||delimitator de instructiuni
separator de obiect
selector de componenta
delimitator de access la distanta
delimitator de sir
delimitator de masina

Simboluri Compuse Sunt formate din doua caractere


-------------------------------------------------------------------**
<>
!=
^=
<=
>=
:=
=>
..
||
<<
>>
-/*
*/

exponential
relational
-||-||-||-||asignare
asociere
rang
concatenare
eticheta
-||comentariu
-||-||-

Retineti ca spatiile nu sunt permise intre cele doua caractere ale simbolurilor
combinate.

Blocurile Incluse
Anumite blocuri pot fi incluse in altele, in orice fel in care instructiunea o permite( nu
se recomanda sa se include blocuri in cadrul unor bucle). Partea executabila a unui
bloc poate fi sparta in blocuri mai mici, si de asemenea sectiunea EXCEPTION poate
include alte blocuri.
Exemplu:

215

BEGIN
-- actiuni in bucla principala
DECLARE
-- declaratii de obiecte
BEGIN
-- actiuni ale blocului
EXCEPTION
-- ce'i de facut daca apare o eroare in acest
bloc.
END;

-- alte actiuni in blocul principal


EXCEPTION
WHEN errors_trickle_through THEN
BEGIN
-- minuire a erorilor in blocul propriu
EXCEPTION
-- ce'i de facut daca tratarea unei erori
-- merge gresit !!
END;
END;

Retineti ca sectiunea DECLARE este optionala ; exemplul prezentat contine citeva


blocuri fare sectiunea DECLARE.

Domeniul OBIECTELOR
"Domeniul" unui obiect este zona unui program in care acest obiect poate fi folosit.
Scurt zis este 'Timpul de viata'. Aceste reguli se aplica toturor obiectelor declarate,
incluzind variabile, cursor, constante si exceptii definite de utilizator.
Domeniul unui obiect este blocul complet in care obiectul este declarat, inclusiv
oricare sub-bloc inclus in acest bloc. Obiectele declarate in sub-blocuri sunt valabile
pina cind sub-blocul se termina.
Exemplu:
DECLARE
X NUMBER;

----------------|
|
|
|

BEGIN
...
domeniul
DECLARE
Y NUMBER;
BEGIN

216

-----|
| domeniul lui y
|

| lui
| x
|
|
|

...

|
-----|

END;
...
END;

|
|
|
|
---------------|

Retineti ca pe timpul 'Timpului de viata' al lui y, suntem tot in domeniul lui 'x', si
putem defini expresii care sa foloseasca ambele variabile.
Sa presupunem ca variabila din sub-bloc nu se numeste 'y' ci 'x'. Cu alte cuvinte, are
acelasi nume ca si variabila din sub-bloc.
DECLARE
x NUMBER;
BEGIN
...
DECLARE
x NUMBER;
BEGIN
...
END;
...
END;

-- variabila x din blocul principal

-- variabila x din sub-bloc

Doua obiecte pot avea acelasi nume, dar definite in doua blocuri diferite. Acolo unde
se intilneste aceasta situatie, ca in exemplul anterior, atunci numai obiectul declarat un
sub-bloc ( acesta este blocul curent) poate fi folosit.

Reguli de VIZIBILITATE
In exemplul anterior, variabila 'x' din sub-bloc dezactiveaza folosirea variabilei 'x' din
blocul principal pina cind variabile intilnesc sfirsitul de valabilitate. In cadrul subblocului, variabila 'x' din blocul principal exista dar nu este vizibila.

Declararea de Variabile si de constante


PL/SQL permite o varietate de tipuri de date ce pot fi folosite pentru declararea de
variabile si de constante. Variabile in mod optional pot avea asignate valori la
declarare, si pot sa-si schimbe valoarea prin asignari ulterioare in cadrul blocului.
Constatele sunt identificatori care pastreaza o valoare fixa care trebuie asignata cind
constanta este declarata.

Tipurile de DATE SCALARE


Aceste sunt tipurile de date care reprezinta o singura valoare.Principalele tipuri de
date sunt acelea ce corespund coloanei de tipuri in tabela ORACLE. PL/SQL suporta
de asemenea tipurile booleene.

TIPUL NUMERIC
NUMBER
Valorile sunt

Valoare numerica cu precizia de 38 de cifre.

217

rotunjite la numere intregi mai putin atunci cind

este data

scala.( ex.

NUMBER(7,2) inseamna 7 cifre, cu 2

zecimale.

Implicit precizia este de 38 cifre.)


TIPUL CARACTER
VARCHAR2
Folosit pentru a memora variabile de tip
caracter.Lungime
implicita 1 caracter. Maxima permisa 32767.
ex. VARCHAR2(30)
CHAR
lungimea maxima

PL/SQL Versiunea 1:la fel ca VARCHAR2, dar cu


de 255

PL/SQL Versiunea 2:Lungimea poate fi mai mare de


32767

caractere.
TIPUL BOOLEAN
BOOLEAN
Rezultatul

Pentru minuirea valorilor booleene TRUE si FALSE.


expresiilor booleene poate fi asignat acestor

variabile si

testat mai tirziu in instructiuni conditionale.


TIPUL DATA
DATE

Datele valide sunt intre 4712 BC si 4712AD.

Declararea VARIABILELOR
Variabilele PL/SQL pot fi declarate si optional le pot fi asignate o valoare initiala, in
sectiunea DECLARE a unui bloc. Alte variabile referite in partea declarativa trebuie
declarate separat in declaratiile anterioare.
Sintaxa:
indentificator tipdata [(precizia,scala)] [NOT NULL] [ := expresie ] ;
Unde 'expresie' poate fi o alta variabila, sau o expresie cu functii si operatori. Daca o
valoare initiala nu este asignata, atunci variabila va contine o valoare nula pina cind ii
va fi asignata ulterior o valoare. Constanta NOT NULL nu mai este permisa in aceasta
situatie.
Exemple:
v_count
v_salary
v_annsal

NUMBER NOT NULL := 0;


NUMBER(7,2);
NUMBER(9,2) := month_sal * 12;
-- mount_sal trebuie sa existe deja

218

postcode
surname
v_message

CHAR(7);
VARCHAR2(25)
VARCHAR2(80)

:= 'Skywalker' ;
:= 'May the course be woth

married

BOOLEAN

:= FALSE;

today

DATE

:= SYSDATE;

you!' ;

Este indicat sa nu alegeti acelasi nume (identificator) pentru o variabila ca nume


pentru coloanele din tabela folosite in cadrul blocului. Daca variabilele PL/SQL apar
in instructiuni SQL si au acelasi nume ca coloana, atunci ORACLE considera ce se
refera coloana.

Declararea CONSTANTELOR
Constantele permit asignarea unei valori unui identificator, pentru o viitoare referire
in cadrul unui bloc. Orice incercare de a modicica valoarea unei constante va cauza
producerea unei erori PL/SQL.
Sintaxa:

identificator CONSTANT tipdata [(precision,scala)] :=


expresie ;

Exemple:

pi CONSTANT NUMBER(9,5) := 3.14159 ;


vat CONSTANT NUMBER(4,2) := 17.5 ;

ATRIBUIRILE si EXPRESIILE
Instructiunile de atribuire PL/SQL permit unei valori de a fi atribuite sau reatribuite
unei variabile dupa sectiunea DECLARE din bloc. Variabila care va primi noua
valoare trebuie explicit numita in partea stinga a operatorului de asignare. Asta este,
nu se poate face referinta indirecta via o alta variabila.(Unele unitati PL/SQL cum ar
fi SQL*Forms includ unele facilitati pentru adresare indirecta.)
Sintaxa:

identificator := expresie ;

Unde 'identificator' este numele variabilei tinta, sau cimp, pentru a primi valoarea
'expresie'.

219

'Expresie' poate fi literal, numele unei alte variabile existente, sau alta expresie
necesara pentru a determina valoarea ce va fi asignata. De obicei, cele mai multe din
expresiile disponibile in inderogarile SQL , clauza SELECT sunt disponibile aici.
Functiile si expresiile permise in PL/SQL vor fi discutate mai tirziu in acest UNIT.
Exemple:
v_count := v_count +1;
ann_sal := mount_sal * 12 +NVL(comm,0);
lev
:= 6;

mess
:= 'The current level is ' || TO_CHAR(lev) ;
v_ename := 'KING';

Valorile pe care le pot lua variabilele booleene pot fi TRUE si FALSE, ca rezultat a
unei expresii booleene.
Exemple:

overpaid
male
salary_ok
female

:=
:=
:=
:=

ann_sal > 35000 ;


UPPER(title) == 'MR' ;
NOT overpaid ;
NOT male ;

switch1
switch2

:= TRUE;
:= FALSE;

Accesarea variabilelor NON PL/SQL


Variabilele declarate in mediul de lucru 'masina' pot fi referite in instructiuni PL/SQL.
Aceasta include variabilele de lucru ale masinii declarate in programele precompilate.
Adresarea variabilelor non-PL/SQL trebuie facuta prin prefixarea cu ':' pentru a le
distinge de declararea de variabile PL/SQL.
Exemple:

:screen_field1
:warp_factor
:global.var1

:= ann_sal ;
:= 9 ;
:= 'YES' ;

Detalii despre modul de minuire al variabilelor NON PL/SQL sunt descrise in cursuri
ORACLE special destinate acestor variabile.

220

Conversii de tipuri de date


PL/SQL incearca sa converteaza dipurile de date in mod dinamic daca sunt mixate in
cadrul unei instructiuni. De exemplu daca un numar este asignat unei variabile
CHAR, atunci in mod automat numarul este translatat astfel incit va putea fi stocat in
cariabila de tip CHAR.
Exemple:

sal_message

VARCHAR2(12)

:= 3500;

Situatia inversa se aplica de asemenea,

salary NUMBER(12,2)

:= sal_message;

Oricum, o eroare va fi generata daca valorile sunt incompatibile:

salary := 'King earns $5000'; -- eroare

Dovedind ca sunt compatibile, se pot asigna caractere in variabile DATE si viceversa:

today VARCHAR2(9)
hired DATE

:= SYSDATE ;
:= '21-JAN-1992' ;

In cadrul expresiilor trebuie sa va asigurati ca tipurile de date sunt aceleasi. Daca apar
tipuri diferite de date in aceiasi expresie, atunci se foloseste cea mai potrivita functie
de conversie:
TO_CHAR
TO_DATE
TO_NUMBER

PL/SQL va incerca sa faca conversia, daca este posibil. De obicei, PL/SQL este mai
pretentios decit SQL daca tipurile de date sunt mixate in cadrul unei expresiilor. Deci
daca nu sunteti sigur, folositi cea mai potrivita functie de conversie.
Exemplu:
v_message VARCHAR2(80) := 'SCOTT earns' || TO_CHAR
(month_sal*12) ;

221

Precedenta operatorilor
Operatorii logici, aritmetici si de concatenare folositi in PL/SQL sunt aceeasi ca in
SQL. In plus mai exista un operator exponential (**) .
Ordinea in care operatiile sunt realizate poate fi controlata folosind paranteze, ca in
SQL.
Reamintim ordinea naturala a operatiilor in cadrul unei expresii:
Ordinea de evaluare a operatorilor
----------------------------------------------------------------------------|
|
| OPERATOR
| OPERATIE
|
|---------------------------------------------------------------------------|
|Primul | ** , NOT
| exponential,
negatie logica|
|
| + , | identitate, negatie
|
|
| * , /
| inmultire,
impartire
|
|
| + , - , ||
| adunare, scadere,
|
|
|
| concatenare
|
|
| = , != , < , > , <= , >=
| comparatie
|
|
| IN NULL, LIKE, BETWEEN, IN
|
|
|
| AND
| conjunctie
|
|Ultimul| OR
| incluziune
|
|---------------------------------------------------------------------------|

Functii interne
Multe din functiile disponibile in SQL sunt de asemenea disponibile si in PL/SQL.
Acestea includ:
o Functii numerice pentru o singura linie
o Functii caracter pentru o singura linie
o Functii de conversie de tip de data
o Functii de timp
o Functii diverse
In plus PL/SQL ofera doua functii pentru minuirea raportatea erorilor denumite
SQLCODE si SQLERRM care vor fi discutate in unitul urmator.

222

Functii nedisponibile in instructiuni structurale sunt:


GREATEST and LEAST
AGV, MIN, MAX, COUNT, SUM, STDDEV si VARIANCE

Blocuri PL/SQL in buffere SQL

Folosirea PL/SQL in SQL*Plus


Limbajul PL/SQL este permis si in SQL*Plus Versiunea 3.0 sau mai mare. Deoarece
SQL*PLUS foloseste unitatea de executie PL/SQL in RDBMS, este necesar ca
ORACLE RDBMS sa foloseasca aceasta facilitate. Aceasta optiune este:

|-----------------------------------------------------------------|
|
SQL> DECLARE
|
|
2 x NUMBER(7,2);
|
|
3 BEGIN
|
|
4
SELECT sal INTO x FROM emp WHERE empno= &&n;
|
|
5
IF x<3000 THEN
|
|
6
UPDATE emp SET sal=3000;
|
|
7
WHERE empno = &&n;
|
|
8
END IF;
|
|
9 END;
|
|
10.
|
|
SQL>
|
|-----------------------------------------------------------------|
o Buffer-ul se inchide cu un '.'
o Executia buffer-ului de face cu RUN sau '/'

Procedural Option (Oracle7 Server)

SQL*Plus este un bun instrument pentru testarea blocurilor PL/SQL,de aceea il vom
folosi si noi pentru partea practica a cursului.
Sunt doua cai pentru a prelucra blocuri PL/SQL in SQL*Plus:
o
o

Se defineste un bloc in buffer-ul SQL, si apoi se ruleaza


Se defineste un bloc ca parte a unui script SQL*Plus, si apoi se ruleaza
scriptul

Declararea de blocuri PL/SQL in buffere SQL


Acolo unde PL/SQL nu se foloseste, bufferul SQL poate contine numai o singura
instructiune SQL. Daca se plaseaza o alta instructiune in buffer aceasta o suprascrie
pe prima. De acea un bloc PL/SQL este tratat ca o instructiune continua iar ':' intr-un
bloc un inchid si nici nu ruleaza bufferul.

223

SQL*Plus detecteaza inceputul unui bloc PL/SQL dupa introducerea cuvintelor cheie
DECLARE si BEGIN la promptul 'SQL >'.Bufferul poate fi inchis fara a executa
blocul sau programul prin introducerea unui '.' la prompt.
Exemplu:
SQL>
2
3
4
5
6
7
8
9

DECLARE
x NUMBER(7,2);
BEGIN
SELECT sal INTO x FROM emp WHERE empno = 7788;
IF x < 3000 THEN UPDATE emp SET sal = 3000
WHERE empno = 7788;
END IF;
END;
.

Continutul bufferului poate fi editat in maniera obisnuita sau salvat intr-un fisier
folosind comanda SQL*Plus "SAVE".
Pentru a rula buffer-ul PL/SQL, tastati comanda RUN sau '/' la promptul SQL. Daca
executia reuseste fara tratari de eroare atunci singurul mesaj care apare ar trebuie sa
fie:
'PL/SQL procedure seccessfully completed'

Folosirea de blocuri PL/SQL in cadrul fisierelor SQL*Plus


Fisiere SQL si comenzi SQL*Plus pot include blocuri PL/SQL care se comporta ca o
singura instructiune in cadrul scriptului.Fisierul poate fi editat in maniera obisnuita,
folosind comenzi ale sistemului de operare si editoare, sau cu ajutorul comenzii
"SAVE" din buffer-ul SQL cum a fost mentionat mai inainte.
Retineti ca comenzile SQL*Plus nu pot apare in interiorul blocului PL/SQL dar pot fi
incluse ori unde in alta parte in fisier. Variabilele de substitutie din SQL*Plus pot fi
referite din cadrul blocului, dar retineti ca ele sunt inlocuite cu continutul variabilelor
INAINTE ca codul sa fie complet interpretat sau executat.
Exemplu:
SET ECHO OFF
BEGIN
INSERT INTO dept ( deptno, dname ) VALUES ( &1, ' &2
' );
COMMIT;
EXCEPTION
WHEN dup_val on index THEN
INSERT INTO tav VALUES (' Duplicate departament
No.');
END;
/

224

SELECT * FROM error tab;


SET ECHO ON

SQL*Plus - descoperind ce se intimpla


dupa rularea unui bloc PL/SQL, veti vedea fiecare mesaj de tipul
'PL/SQL procedure successfully completed'
( procedura PL/SQL terminata cu succes )
Parse-time Error MEssages
( mesaje de eroare, aparute dinamic in timpul procesarii.)
An 'Unhandled Exception' Message
( Mesaj de eroare netratata.)
Instructiunile PL/SQL nu pot scrie pe ecran !
Mesajele sunt scrise intr-o tabela si dupa acea se parcurge tabela
Scrie mesajele intr-o variabila de asociere si apoi foloseste comanda PRINT dupa ce blocul a
rulat.
Se apeleaza o procedura care afiseaza mesajele pe ecran

Cum se pot afla rezultatele actiunilor PL/SQL


Daca apare vreo eroare netratata in timpul compilarii sau al executiei unui bloc, atunci sunt
afisate mesaje pentru a informa utilizatorul ce eroare a aparut, o explicatie a erorii si o
interpretare a liniei(lor) care au generat eroarea.
Oricum, continutul variabilelor si al tabelelor bazei de date nu pot fi afisate pe ecran in timpul
executiei blocurilor PL/SQL in sesiuni SQL*PLus (cel putin pina cind nu sunt folosite
procedurile pachetului DBMS_OUTPUT). Trebuie sa scrieti orice rezultat pe care doriti sa-l
afisati intr-o tabela in baza de date si dupa executie sa parcurgeti tabela. Aceasta parcurgere
poate fi facuta in acelasi fisier care cuprindea si blocul, ca in exemplul anterior.
Situatia este diferita in aplicatii cum ar fi SQL*Forms, unde blocurile PL/SQL pot afisa
variabile direct pe ecran prin folosirea unor functii interne.
Apelul Functiilor si Procedurilor PL/SQL memorate
Atunci cind subprograme (functii si proceduri) PL/SQL sunt memorate in baza de date, ele
pot fi apelate ca parte a unui alt bloc PL/SQL, daca cel care face apelul are drepturi
suficiente. Sintaxa generala a apelului este:

225

nume-Procedura [ ( param1, param2, param3, ... ) ];


La apelare, parametrii trebuie pusi in ordinea de definire. Aceasta inseamna si tipurile de date
trebuie sa fie aceleasi cu cele definite. Anumiti parametrii pot avea valori implicite, dar daca
o valoare este data ca parametru atunci toti parametrii anteriori trebuie folositi.
In exemplul urmator, procedura CLEAR_DEPT are doi parametrii disponibili. Primul
parametru DEPARTAMENT_NAME ( datatype VARCHAR2 ) si al doilea parametru
DELETE_DEPARTAMENT ( datatype BOOLEAN cu valoarea implicita FALSE ).

CLEAR_DEPT( `ACCOUNTING' ); -- al doilea parametru este implicit

CLEAR_DEPT ( `ACCOUNTING', TRUE);


Parametrii pot fi folositi alternativ impreuna cu numele formal, prin folosirea operatorului de
asociere. In acest caz pozitia lor nu mai este importanta:

CLEAR_DEPT ( DELETE_DEPARTAMENT => TRUE,


DEPARTAMENT_NAME => `ACCOUNTING' ) ;

In final, deoarece sub-programele trebuie apelate din blocuri PL/SQL, se poate apela din
promptul SQL in SQL*Plus prin impachetarea apelului cu BEGIN si END. Aceasta poate fi
realizata prin comanda EXECUTE din SQL*Plus.

SQL> EXECUTE CLEAR_DEPT( `ACCOUNTING' );

care este identica cu :

BEGIN CLEAR_DEPT( `ACCOUNTING ');

END;

Unitul 20, EXERCITII


In fiecare din urmatoarele exercitii puteti crea blocuri PL/SQL in buffere SQL si puteti salva
mai tirziu in fisier, sau puteti alternativ edita fisierul folosind un editor de texte al masinii. In
ambele cazuri, retineti numele pe care il dati fiecarui fisier.
226

In multe din exercitii, aveti nevoie de inregistrarea rezultatelor intr-o tabela. Vom folosi
pentru aceasta tabela MESSAGES. Definirea acesteia este urmatoarea:
Table MESSAGES

Coloana

Descrierea

------------ ------------------------------------NUMCOL1

NUMBER (9,2)

NUMCOL2

NUMBER (9,2)

CHARCOL1

VARCHAR2(60)

CHARCOL2

VARCHAR2(60)

DATECOL1

DATE

DATECOL2

DATE

Creati un bloc, cu patru variabile:


V_BOOL1 Boolean
V_BOOL2 Boolean
V_CHAR Character ( lungime variabila)
V_NUM Number

si apoi atribuiti valori variabilelor dupa cum urmeaza:


Variabila

Valoare

------------- ----------------------------------------V_CHAR

Literar `42 este raspunsul'

V_NUM

Primele doua caractere din V_CHAR

V_BOOL1

TRUE si FALSE functie de cum este V_NUM

fata de 100
V_BOOL2

Opus lui V_BOOL1

227

Scrieti si rulati un bloc PL/SQL care accepta soua numere din variabile PL/SQL. Primul din
numere trebuie "ridicat la putere" cu cel de-al doilea numar, in cadrul blocului, si rezultatul
scris intr-o variabila PL/SQL. INregistrati rezultatul in tabela MESSAGES, si alternativ in
variabila de asociere SQL*Plus. (Operatorul exponential in PL/SQL este '**' ).

Unit 20 SOLUTII

DECLARE
V_BOOL1

BOOLEAN;

V_BOOL2

BOOLEAN;

V_CHAR

VARCHAR2(16);

V_NUM

NUMBER(2);

-- cel putin 16 caractere

BEGIN
V_CHAR := '42 este raspunsul';
V_NUM := SUNSTR(V_CHAR,1,2); -- conversie dinamica la mumar
V_BOOL1 := V_NUM < 100;
V_BOOL2 := NOT V_BOOL1;
END;

DECLARE
V_RESULT NUMBER(9,2);
BEGIN
V_RESULT := &main_var ** &exponent ;
-- sau POWER(&main_var,&exponent);
INSERT INTO messages(numcol1) VALUES ( V_RESULT ) ;
END;
228

Sau o solutie alternativa folosind SQL*Plus :

BIND VARIABILES .............


VARIABILE V_RESULT NUMBER
BEGIN
:V_RESULT := &main_var ** &exponent;
END;
PRINT V_RESULT

229

CAPITOLUL 21
INTERACTIUNEA CU ORACLE
In acest unit se va trata modalitatea de access la baza de date si de controlarea tranzactiilor,
prin instructiuni SQL in PL/SQL. De asemenea veti vedea cum erorile cauzate de SQL pot fi
tratate de catre rutinele de tratare a exceptiilor.

Comenzi SQL in PL/SQL


PL/SQL ofera citeva instructiuni procedurale pentru manipularea si testarea datelor,
de multe ori fara sa avem nevoie sa apelam comenzi SQL. Aceasta metoda este
preferabila, deoarece SQL face access la baza de date.
Oricum, cind vrem sa extragem informatii din baza de date, sau sa facem modificari
atunci trebuie sa folosim SQL. PL/SQL suporta toate facilitatile DML si toate
comenzile de control al tranzactiilor din SQL. Si, bineinteles, instructiunea SELECT
poate fi folosita pentru a atribui variabilelor valori din liniile in tabele.
Iata citeva puncte mai inportante care trebuie amintite:
o
o
o
o
o

Fiecare comanda SQL trebuie terminata de ';'


Un bloc PL/SQL nu este o unitate de tranzactie - COMMIT si ROLLBACK
sunt implementate independent de blocuri, dar pot face parte din ele.
Comenzile DDL nu sunt permise in PL/SQL
Comanda SELECT care nu intoarce un singur rind cauzeaza o eroare
Comenzile DML pot procesa mai multe linii

Referirile PL/SQL in comenzi SQL


Valorile memorate in variabile si constante PL/SQL pot fi pasate direct comenzilor
SQL, unde ele sunt procesate de modulele PL/SQL pe masura ce blocul este executat.
Atentie mare ar trebui acordate pentru a nu referi variabile PL/SQL in SQL unde
variabilele au acelasi nume cu coloana in tabela.
Exemplul urmator ilustreaza aceasta problema.
Exemplu:

DECLARE
empno NUMBER(4) := 7788;
BEGIN
UPDATE emp SET sal = 9000;
WHERE empno = empno;

230

-- unde coloana este egala cu ea insasi


......
END;

In exemplul anterior fiecare linie din tabela 'emp' trebuie reactualizata. Fiecare
adresare in instructiunea UPDATE catre 'empno' este tratata ca nume de coloana. De
aceea, alegeti nume de variabile PL/SQL care nu intra in conflict cu numele
coloanelor din tabela pe care doriti sa o folositi.
De asemenea, retineti ca atributele si functiile PL/SQL care sunt unice PL/SQL nu pot
fi adresate direct din comenzi SQL. Acestea includ SQLCODE si SQLERRM, care
vor fi discutate mai tirziu in acest unit.

COMENZI PENTRU MANIPULAREA DATELOR

INSERT
UPDATE
DELETE
[LOCK TABLE]

Exemple:

DECLARE
v_empno NUMBER(4) := 7788 ;
BEGIN
UPDATE emp SET sal = 9000 ;
WHERE empno = v_empno ;
...
END;

Nota) Atentie la numele variabilelor !

Comenzi pentru manipularea datelor ( DML )


Comenzile DML, INSERT UPDATE, DELETE pot fi folosite fara restrictii in
PL/SQL. Tabela sau linia apare ca un rezultat al acestor comenzi si apar la sfirsitul
tranzactiilor DML, in maniera obisnuita:

231

Exemplu:

DECLARE
v_empno NUMBER (4) := 7788;
BEGIN
UPDATE emp SET val = 9000;
WHERE empno = v_empno;
...
END;

Exemplul de mai sus tinteste liniile pentru UPDATE care au valoarea 'empno' de
7788. Daca zero sau mai multe linii satisfac conditia, comanda este inca incheiata cu
succes.

Cursorul implicit - Testarea rezultatelor comenzilor SQL


Ori de cite ori sunt executate comenzi SQL, o zona de memorie este deschisa in care
comanda poate fi interpretata si executata. Un cursor este un identificator pentru
aceasta zona.
Comenzile SQL ce fac parte din partea executabila a unui bloc sunt executate in
'cursorul implicit' care are identificatorul 'SQL'. Acest cursor este gestionat automat
pentru utilizatori de catre PL/SQL.
PL/SQL ofera citeva 'atribute' care ne permit sa determinam ce se intimpla cind
cursorul implicit a fost utilizat ultima data. Acestea sunt:
SQL%ROWCOUNT
SQL%FOUND
procesata,
SQL%NOTFOUND

- numarul de linii procesate de instructiuni


SQL ( valoare intreaga)
- TRUE daca cel putin o linie a fost
altfel FALSE ( valoare booleana)
- TRUE daca nu a fost procesata nici o linie
altfel FALSE ( valoare booleana)

Aceste atribute pot fi folosite in aceeasi maniera ca functiile in comenzi PL/SQL, dar
nu in comenzi SQL.
Atributele pot fi folosite in sectiune EXCEPTION a unui bloc pentru a evalua
rezultatul unei instructiuni SELECT esuate (cereia i se permite sa intoarca doar o
linie), dar probabil ca este mult mai folositor sa evaluam rezultatul operatiei DML.
Exemplu:
DECLARE
rows_deleted NUMBER;
BEGIN
DELETE FROM dept WHERE deptno = 50;

232

rows_deleted := SQL%ROWCOUNT ;
INSERT INTO del_history VALUES ('DEPT',
rows_deleted,SYSDATE);
END;

Controlul Tranzactiilor
La fel ca si ORACLE in general, tranzactiile DML vor incepe la prima comanda ce
urmeaza lui COMMIT sau ROLLBACK, si sfirsitul urmatorului COMMIT sau
ROLLBACK terminat cu succes. Aceste actiuni pot avea loc intr-un bloc PL/SQL sau
ca rezultat al evenimentelor din mediu masinii.
Urmatoarele comenzi de control al Tranzactiilor sunt valide in PL/SQL, dar
variabilele de mediu ale masinii pot impune unele restrictii de utilizare:
COMMIT
[ WORK ]
ROLLBACK
[TO savepoint]
SAVEPOINT
SET TRANSACTION

Comenzi de blocare, care dureaza pina la sfirsitul tranzactiei pot fi de asemenea


include in bloc. Acestea sunt : LOCK TABLE, SELECT .. FOR, UPDATE.
Exemple:
In exemplul urmator, este prezentat un "rollback" din variabilele de mediu ale masinii
( de exemplu SQL*Plus) pentru a anula orice actiune DML aplicata in bloc de la
punctul salvat(savepoint).
BEGIN
...
SAVEPOINT ok_so_far;
...
END;
ROLLBACK

TO

ok_so_far;

Exemplul urmator "rools back" toate toate tranzactiile, incluzind orice modificare
facute in exteriorul blocului, faca functia UPDATE nu gaseste nici o linie. Altfel, se
transmit toate schimbarile in tranzactie.
DELETE FROM emp WHERE job = 'CLERK';
BEGIN
UPDATE emp SET sal = 8000 WHERE job = 'CAPTAIN' ;
IF SQL%NOTFOUND
THEN ROLLBACK;
ELSE COMMIT;
END IF;
END;

233

Retineti ca SQL*Plus trateaza un bloc PL/SQL ca o singura instructiune. Daca


optiunea AUTOCOMMIT este activa (ON), actiunile realizate in bloc nu sunt
realizate pina cind nu este procesat si sfirsitul blocului. In mod opus, daca o actiune
DML cauzeaza o exceptie netratata atunci blocul se va termina cu esec si practic se
vor anula actiunile DML din cadrul blocului.

Instructiunea SELECT in PL/SQL


SELECT se foloseste ca instructiune executabila in cadrul blocurilor PL/SQL si i se
aplica urmatoarea regula:
Interogarile

trebuie sa intoarca o coloana si numai una,

altfel
o eroare va fi generata.

De acea, SELECT-ul care nu intoarce nici o linie, sau mai mult de o linie cauzeaza
una din urmatoarele erori:
ORA-01403
ORA-01422

No Data Found (ANSI error 100)


Data negasita
Exact fetch returns more than requested
number of rows

PL/SQL trateaza aceste erori prin tratarea exceptiilor, care pot fi trasate in sectiunea
EXCEPTION a blocului. Dar despre aceste tratatea acestor exceptii vom vorbi mai
tirziu in cadrul acestui unit. In mod normal ar trebui folosit SELECT pentru a obtine o
singura linie. Urmatoarele clauze sunt permise:
SELECT
INTO
FROM
[WHERE
[GROUP BY
[HAVING
[FOR UPDATE];

articol, articol, ...


variabila, variabila, ...
tabela, tabela, ...
conditie(ii) ]
articol, articol, ... ]
conditie(ii)]

Atributele %TYPE
Cind variabile PL/SQL sunt declarate pentru incarcare ulterioara cu valoarea coloanei,
trebuie sa va asigurati ca variabila este compatibila ca tip de data cu coloana si ca este
suficient de mare pentru a stoca valoarea de pe coloana. Daca nu este atunci PL/SQL
va genera eroare.
Decit sa incercati sa ghiciti tipul si precizia pentru o variabila, puteti sa va bazati pe
definitia coloaneo din Data Dictionary. Acest lucru se face folosind atributul %TYPE.
Atributul este prefixat cu numele tabelei si al coloanei, si folosit cind este nevoie de
tipul datei in declaratia variabilei:

234

identificator

numetabela.coloana%TYPE

Folosind aceasta metoda, tipul de data si dimensiunea sunt determinate atunci cind
blocul este compilat.
Exemplu:
DECLARE
v_deptno
v_loc

dept.deptno%TYPE;
dept,loc%TYPE;

BEGIN
SELECT
INTO
FROM

deptno,
loc
v_deptno, v_loc
dept ...

END;

INTRODUCERE IN TRATAREA EXCEPTIILOR (ERORILOR)


o
o

Ce sunt exceptiile ?
Conditii care vor termina un bloc.
Doua tipuri principale
Predefinite
Definite de USER
Tratarea exceptiilor
Previne erorile de a se propaga in afara blocului
Defineste actiunile ce se vor face cind exceptia apare

WHEN

identificator_exceptie THEN actiuni;

Introducere in tratarea exceptiilor


Asa cum am vazut pe scurt mai inainte, exceptiile sunt identificatori in PL/SQL care
pot dispare in timpul executiei unui bloc pentru a termina partea principala a actiunii.
Un bloc se va termina INTOTDEAUNA cind apare o exceptie, dar se poate specifica
un mod de tratare pentru a realiza actiunea finala inainte ca blocul sa se termine. daca
exceptia este tratata, atunci exceptia nu se propaga si in afara blocului.
Sunt doua clase principale de exceptii:
Predefinite
Acestea sunt predefinite de PL/SQL si au asociate coduri specifice de eroare.
Definite de utilizator
Sunt declarate in bloc de utilizator. Acestea vor fi folosite numai daca se cere acest
lucru, dar pot fi de asemenea asociate cu coduri de eroare daca se doreste acest lucru.

235

In acest unit ne vom concentra asupra exceptiilor interne predefinite. Acestea sunt
urmatoarele:
Numele exceptiei
-----------------

Codul de eroare ORACLE


-----------------------------

DUP_VA_ON_INDEX
INVALID_CURSOR
INVALID_NUMBER
LOGIN_DENIED
NO_DATA_FOUND
NOT_LOGGED_ON
PROGRAM_ERROR
STORAGE_ERROR
TIMEOUT_IN_RESPONSE
TOO_MANY_ROWS
VALUE_ERROR
ZERO_DEVIDE
CURSOR_ALREADY_OPEN
TRANSACTION_BACKED_OUT

-1
-1001
-1722
-1017
-1403 (ANSI +100)
-1012
-6501
-6500
-51
-1422
-6502
-1476
-6511
-61

Identificatori exceptie
Daca orice tip de exceptie este generat controlul este trecut sectiunii EXCEPTION a blocului
in care exceptia apare. Daca exceptia nu e minuita aici sau daca nu exista nici o sectiune
EXCEPTION atunci blocul se termina cu o exceptie `Unhandled` care poate avea
repercursiuni in mediul de inchidere.
EXEMPLU:
BEGIN
INSERT INTO dept (deptno, dname) VALUES (50, `CLEANING`);
INSERT INTO dept (deptno, dname) VALUES (50, `TRAINING`);
-- Exception DUP_VAL_ON_INDEX raised here

...

END;
-- Block terminates which Unhandled Exception - ORA -00001

Pentru a prinde asemenea evenimente si a preveni propagarea exceptiilor catre mediile de


inchidere sau blocuri se poate defini identificatorul exceptie in sectiunea EXCEPTION.
Sintaxa:
WHEN exception-identifier THEN actions;

236

unde `actions` poate fi una sau mai multe declaratii PL/SQL sau SQL fiecare terminata cu ':'.
Actiunile unui identificator exceptie sint delimitate fie de sfirsitul blocului (END) fie de
inceputul unui alt identificator exceptie (WHEN).
Principalele exceptii care pot apare ca un rezultat al declaratiei SELECT sint
NO_DATA_FOUND (fara linii returnate) si TOO_MANY_ROWS (mai mult decit o linie
returnata).
Exemplu:
DECLARE
v_ename emp.ename%TYPE;
v_job emp.job%TYPE;
BEGIN
SELECT ename, job
INTO v_ename, v_job
FROM emp
WHERE hiredate BETWEEN '1-JAN-92' AND '31-DEC-92';
...
EXCEPTION
WHEN no_data_found THEN
INSERT INTO error_tab
VALUES ('Nobody in 92');
WHEN too_many_rows THEN
INSERT INTO error_tab
VALUES ('More then one person in 92');
END;

Notati ca, citiva identificatori exceptie pot fi definiti pentru bloc fiecare cu setul propriu de
actiuni. Totusi cind o exceptie apare numai un identificator va fi procesat inainte de a parasi
blocul.

Identificatorii exceptie 'WHEN OTHERS'


Desi sectiunea EXCEPTION din exemplul de sus va prinde cele doua exceptii specificate alte
tipuri de exceptie se vor strecura in retea mai bine decit definirea unui identificator separat
pentru fiecare tip de exceptie se poate folosi identificatorul exceptie 'WHEN OTHERS' care

237

minuieste toate erorile neminuite inca in bloc. Daca e folosit 'WHWN OTHERS' trebuie sa
fie codat dupa orice alt identificator exceptie din bloc.
Exemplu:
BEGIN
SAVEPOINT

so_far_so_good;

INSERT INTO statistics_tab VALUES (18, 25,91);


EXCEPTION
WHEN dup_val_on_index THEN
INSERT INTO error_tab VALUES (`Error
during block`);
END;

Functii pentru prinderea erorii


Cind o exceptie a aparut, veti dori evaluarea codului erorii asociate sau mesajul
eroare.Aceasta poate fi important in minuirea exceptiilor folosind `WHEN OTHERS`, pina
cind veti dori a decide ce actiune sa fie dupa eroare. PL/SQL furnizeaza 2 functii in acest
scop :
SQLCODE
intoarce nr. erorii asociata cu exceptia care a aparut (in cazul lui NO_DATA_FOUND
acesta va fi codul ANSI +100).Daca e folosit un singur identificator EXCEPTION,
functia va intoarce 0.
SQLERRM
intoarce mesajul complet de eroare asociat cu exceptia (incluzind nr. erorii)
SQLCODE intoarce date numerice, si poate fi asignat unei variabile NUMBER cu precizie
implicita.SQLERRM intoarce date caracter.Este recomandat a trunchia valoarea la o lungime
cnoscuta inainte de a incerca sa o scriem intro variabila.
Exemplu:
DECLARE
error-message CHAR (100);
error-code

NUMBER;

BEGIN
...
EXCEPTION

238

WHEN OTHERS

THEN
error_message :=SUBSTR(SQLERM,1,100);
error_code :=SQLCODE;
INSERT INTO errors VALUES (error_message, error_code);
END;

SQLERRM are un parametru optional care accepta numarul erorii a carui mesaj e returnat.
NOTA: SQLERRM si SQLCODE nu pot fi folosite direct ca parti ale unei declaratii
INSERT; valorile lor trebuie sa fie trecute prima data unei variabile.

Cum se propaga exceptiile?


Cind un subbloc minuieste o exceptie se termina normal si controlul va fi rezumat in blocul e
inchidere imediat dupa END-ul subblocului.
Totusi cind o exceptie este generata si blocul curent nu are un identificator pentru el exceptia
se propaga. Aceasta inseamna ca exceptia se reproduce ea insasi in blocuri de inchidere
succesive pina cind un identificator e gasit. Daca nici unul dintre blocuri nu minuieste
exceptia atunci o exceptie Unhandled este produsa in mediul gazda.
Aceasta saritura intre sectiunile EXCEPTION de la blocurile interne catre cele externe
produce actiunile executabile ramase in aceste blocuri sa fie trecute (actiunile intre END-ul
unui subbloc si keyword-ul EXCEPTION al blocului de inchidere nu sint procesate).
EXEMPLU:
BEGIN
...
BEGIN
...
--Exception X raised at this point
EXCEPTION
--No handler that deals whith exception X
END;
...
EXCEPTION
--Handler for X present here (i.e. The Buck stops here!)
END;

239

Un avantaj al acestei comportari este ca anumite declaratii care cer minuirea propriilor erori
poate fi inclus in propriul bloc lasind minuirea exceptiilor generale blocurilor de inchidere.
EXEMPLU:
DECLARE
e_mess CHAR(80)
BEGIN
DECLARE
v1 NUMBER(4);
BEGIN
SELECT empno INTO v1 FROM emp WHERE job = 'PRESIDENT';
EXCEPTION
WHEN too_many_rows THEN
INSERT INTO job_errors VALUES ('More than one
President!');
END;

DECLARE
v1 NUMBER (4);
BEGIN
SELECT empno INTO v1 FROM emp WHERE job = 'MANAGER';
EXCEPTION
WHEN too_many_rows THEN
INSERT INTO job_errors VALUES ('More than one
Manager');
END;
EXCEPTION
WHEN OTHERS THEN
e_mess := SUBSTR(SQLERRM, 1, 80);
INSERT INTO general VALUES (e_mess);
END;

240

Exercitii
Alterati blocul dvs. produs la Cap. 20 Ex. 2.Redefiniti variabila PL/SQL ca
NUMBER(1).Ce se intimpla daca 2 valori de intrare are valorile 4 si 2?
Adaugati un Identificator Exceptie la blocul care inregistreaza un mesaj explicit in Messages
pentru orice tip de exceptie care poate apare. Apoi lansati blocul din nou.
Scrieti un script PL/SQL care primeste la rulare un singur parammetru, unde este furnizt un
tip de slujba.
Ex.

@UNI3_FILE MANAGER

Blocul PL/SQL din fisier trebuie sa SELECT-ezr rinduri din tabela EMP care are tipul jobului in coloana JOB. (Va referiti la parametru ca '&1'). Trimiteti un mesaj in tabela
MESSAGES, in functie de faptul ca se returneaza unul,niciunul sau mai multe rinduri.
Ex.
'Jobtype found once'
'Jobtype not found'
'Jobtype found more than once'

Inregistrati Jobtype si in tabela MESSAGES, s executati tranzactia, indiferent de mesajul


produs.

Solutii.
O exceptie VALUE_ERROR este lansata daca valoarea este prea mare pt. variabila.
DECLARE
V_RESULT NU MBER(9.2) ;
V_MESSAGE CHAR(60);
BEGIN
V_RESULT := &main_var ** &exponent ;
-- or POWER (&main_var, &exponent);
INSERT INTO messages (numcol1) VALUES (V_RESULT);
EXCEPTION
WHEN OTHERS THEN V_MESSAGE := SUBSTR(SQLERRM,1,60);
INSERT INTO messages (charcol1);
VALUES (V_MESSAGE);
END;

241


DECLARE
JOBTYPE emp.job%TYPE;
BEGIN
SELECT job INTO JOBTYPE
FROM emp WHERE job = '&1' ;
INSERT INTO messages (charcol1, charcol2)
VALUES ('&1', 'Jobtype found once');
COMMIT;
EXCEPTION
WHEN no_data_found THEN
INSERT INTO messages (charcol1, charcol2)
VALUES ('&1', 'Jobtype not found');
COMMIT;
WHEN too_many_rows THEN
INSERT INTO messages (charcol1, charcol2)
VALUES ('&1', 'Jobtype found more than once');
COMMIT;
END;

242

Structuri de control
In acest capitol se explica structurile de control ale unui program PL/SQL. Acestea sint
expresiile conditionale, salturile si buclele.

Introducere in expresiile de control ale PL/SQL


PL/SQL ofera facilitati de control al executiei conditionat si neconditionat. Aceste sint:
instructiuneaIF
Ofera controlul selectiv al actiunilor, bazat pe indeplinirea unor conditii.
instructiunea GOTO
Se foloseste la saltul neconditionat la o eticheta din program.
ciclul simplu
Asigura repetarea unor actiuni fara impunerea de conditii
ciclul FOR
Pentru control iterativ al actiunilor, bazat pe un contor.
cicluri WHILE
Pentru control iterativ al actiunilor, bazat pe indeplinrea unei conditii
instructiunea EXIT
Pentru a iesi dintr-un ciclu
Acolo unde aceste facilitati includ o conditie, aceasta poate fi orice expresie booleana valida
in SQL, cu exceptia query imbricat. Aceasta include:

Operatori logici ( ,, -, NOT, etc.)


Operatori de compunere ( AND, OR )
Operatori SQL ( LIKE, IN, BETWEEN, IS NULL )

Exemple:
var <= var2
var3 LIKE '%S%'
var4 BETWEEN '01-JUN-92' AND '01-SEP-92'
var2 IS NOT NULL
bool_var
x IN ( 'Y', 'N', 'YES', 'NO' )
( a = b OR c = 5 ) AND p < 400

Instructiunea IF
Instructiunea IF are o structura similara cu echivalentul din limbajele procedurale. Ea permite
executarea unor actiuni selectiv, bazat pe indeplinirea unor conditii. Structura sa generala este
prezentata mai jos. Sintaxa:
IF conditie THEN actiuni [ ELSIF conditie THEN actiuni ]
[ ELSE actiuni ]
END IF;

unde "actiuni" pot fi una sau mai multe instructiuni PL/SQL sau SQL, fiecare terminata cu
punct-virgula. Aceste "actiuni" pot include alte instructiuni IF cu aceiasi structura, ceea ce
inseamna ca instruciunea poate contine IF, ELSE, ELSIF imbricate.

Instructiunea IF simpla
Sa incepem cu un exemplu care implica numai o conditie, fara nici una din clauzele
optionale:

243

IF v_ename = 'SCOTTY' THEN beam_me_up := 'YES';


COMMIT;
END IF;

Cele doua actiuni sind executate numai daca conditia este adevarata (TRUE). Daca conditia
este falsa (FALSE sau NULL) atunci cele doua instructiuni sint excluse. In oricare din caz,
executia continua cu urmatoarea instructiune din program de dupa END IF.
Notati ca daca constructia 'END IF' nu este prezenta la sfirsitul instructiunii, atunci PL/SQL
ca cauta in instructiunile urmatoare cautind 'END IF'. Ca si in alte limbaje procedurale
aceasta poate provoca afisarea unor mesaje de eroare confuze.
Urmatorul exemplu arata cum pot fi executate instructiuni alternative prin intermediul clauzei
ELSE. Actiunile specificate prin ELSE sint executate daca conditiila este FALSE sau NULL,
dupa care programul continua cu instructiunile ce urmeaza dupa END IF.
IF ename = 'SCOTTY' THEN beam_me_up = 'YES' ;
COMMIT;
ELSE beam_me_up = 'NO' ;
ROLLBACK;
END IF;

Oricare set de actiuni poate include instructiuni IF inlantuite pentru a executa teste ulterioare
inainte ca o actiune specifica sa fie executata. Fiecare instructiune IF inlantuita trebuie sa fie
terminata de END IF-ul corespunzator.
Exemplu:
IF deptno = 10 THEN accounting := 'YES';
IF job = 'MANAGER' THEN
INSERT INTO status VALUES ( ' Dept10
Manager');
END IF;
COMMIT;
ELSE accounting := 'NO';
IF job = 'MANAGER' THEN
INSERT INTO status VALUES (' Alt Mgr.');
END IF;
COMMIT;
END IF;

Adesea, actiunile de executat in clauza ELSIF pot contine doar un alt IF. In aceasta situatie,
este mult mai convenabil sa folositi clauza ELSIF, care elimina necesitatea de a inlantui END
IF la sfirsitul fiecarui set ulterior de conditii/actiuni:
IF f_title = 'doamna' THEN status := 'MARITATA';
ELSIF f_title = 'domnisoara' THEN
status := 'NEM.'
ELSE
status:= 'NECUNOSCUTA';
END IF;

Datorita posibilitatii de a imbrica actiuni, clauza ELSIF poate fi utilizata recursiv, daca doriti:

244

IF choise = 1 THEN actiune


ELSIF choice
ELSIF choice
ELSIF choice
ELSE actiune
END IF;

:= 'Run Payroll'
= 2 THEN actiune
= 3 THEN actiune
= 4 THEN actiune
:= 'Invalid';

;
:= 'Run Accounts';
:= 'Backups';
:= 'Restore';

Cicluri de baza si instructiunea EXIT


Structura:
LOOP
-- actiuni de executat in
-- cadrul ciclului
END LOOP;
* EXIT termina ciclul

Sintaxa:
EXIT [eticheta-ciclu] [WHEN conditie];

Cicluri si salturi in PL/SQL


PL/SQL ofera un numar de facilitati pentru cicluri si pentru a iesi din cicluri, cind se doreste,
spre alta parte a programului. Cel mai simplu caz contine instructiunile ce se doresc repetate
incluse intre delimitatorii LOOP si END LOOP:
LOOP
-- actiuni de executat
-- in cadrul ciclului
END LOOP;

De fiecare data cind programul ajunge la constructia END LOOP, controlul este redat
expresiei LOOP corespunzatoare. Acest ciclu necontrolat va fi, bineinteles, infinit daca nu se
folosesc instructiuni de control in interiorul ciclului, care sa provoace saltul in afara ciclului.

Instructiunea EXIT
Un ciclu poate fi terminat din interior, daca este utilizata instructiunea EXIT. EXIT permite
transferul controlului instructiunii urmatoare de dupa END LOOP, permitind astfel incheierea
imediata a ciclului.
Sintaxa:
EXIT [loop-label] [WHEN conditie];

EXIT poate fi executat fie ca o actiune dintr-un IF, sau ca o instructiune individuala in cadrul
unui ciclu. In acest caz, o clauza WHEN poate fi atasata la instructiunea IF, permitind
terminarea conditionata a ciclului.
Exemplul 1:
LOOP
counter := counter + 1;
INSERT INTO numbered_rows VALUES (counter);
...
IF counter = 10 THEN COMMIT;

245

EXIT;
END IF;
END LOOP;

Exemplul 2:
LOOP
...
EXIT WHEN total_sals = 60000;
...
END LOOP;

O alta posibilitate de a iesi dintr-un ciclu ar fi sa sariti la o instructiune etichetata in afara


ciclului, folosind instructiunea GOTO. Aceasta este in general considerata ca o metoda mai
putin structurata. GOTO si etichetele vor fi discutate mai tirziu, in acest capitol.

Utilizarea ciclurilor FOR pentru controlul iteratiilor


Ciclurile FOR au aceeasi structura generala ca si celee pe care deja le-ati vazut, dar adauga
instructiuni de control la inceputul ciclului, care vor determina numarul de iteratii ce vor fi
efectuate.
Sintaxa:
FOR variabila_control IN [REVERSE] valoare_inferioare ..
valoare_superioara

Unde 'variabila_control' este numele unei variabile intregi ale carei valori vor fi
incrementate/decrementate automat la fiecare iteratie a ciclului. Aceasta variabila este creata
de catre ciclu, si nu poate fi scrisa de nici o instructiune din cadrul ciclului. Durata de viata se
termina la terminarea ciclului.
'valoare_inferioara' si 'valoare_superioar' sint expresii intregi, care determina valorile pe care
le va lua variabila de control.
Implicit, variabila de control este initializata cu o valoare mica, si este incrementata cu +1 la
fiecare iteratie pina cind valoarea superioara este atinsa.
Exemplu:
FOR i IN 1 .. 2000
LOOP
INSEERT INTO numbered_rows VALUES (i);
preserve_i := i;
...
END LOOP;

Observati ca daca valoarea lui 'i' este necesara dupa terminarea ciclului, atunci ea trebuie
copiata intr-o variabila declarata inainte de terminarea ciclului.
Ciclul FOR poate si sa decrementeze variabila de control, incepind de la valoarea superioara
in prima iteratie:

246

FOR n IN REVERSE 50 .. myvar+50


LOOP
-- n are valoarea myvar+50 la prima iteratie.
-- si valoarea 50 la ultima
END LOOP;

Utilizarea ciclurilor WHILE pentru controlul iteratiilor


Aceasta este o structura de control alternativa, care permite iteratiilor sa fie executate
conditionat.
Sintaxa:
WHILE conditie

Conditia este evaluata la inceputul fiecarei iteratii, si ciclul este terminat cind conditia este
FALSE. Daca conditia este FALSE atunci cind ciclul incepe, atunci nici o interatie nu se
executa.
Exemplul 1:
WHILE bill <250 AND food LIKE '%taco%'
LOOP
-- actiuni
END LOOP;

Exemplul 2:
WHILE bool_var
LOOP
-- actiuni
END LOOP;

Normal, daca variabila implicata in conditii nu se schimba in timpul executiei ciclului, atunci
ciclul nu se va termina niciodata. Totusi instructiunea EXIT poate fi inclusa atit in ciclurile
FOR si WHILE.

Controlul ciclurilor imbricate


Ciclurile pot fi imbricate pe nivele multiple. Puteti imbrica cicluri FOR in cicluri WHILE si
invers. In mod normal, terminarea unui ciclu intern nu termina ciclul care il include,
exceptind cazul cind este generata o exceptie.
Etichetele in PL/SQL sint definite astfel:
<< label-name >>

Numele etichetei urmeaza aceleasi reguli ca si orice identificatori. O eticheta este plasata
inaintea unei instructiuni, fie pe aceasi linie, fie pe o linie separata.
Ciclurile pot fi etichetate prin plasatea unei etichete inainte de cuvintul LOOP, si dupa END
LOOP, conform:

247

<< outer_limits >> LOOP


-- actiuni
END LOOP outer_limits;

Daca un ciclu subordonat executa un EXIT, atunci el poate specifica care ciclu sa fie incheiat
prin specificarea etichetei.
Exemplu:
<< main >> LOOP
...
LOOP
...
EXIT main WHEN total_done = 'YES';
-- paraseste ambele cicluri
EXIT WHEN inner_done = 'YES';
-- paraseste doar ciclul interior
END LOOP main;

Folosirea GOTO si a etichetelor


Dupa cum ati vazut, etichetele pot fi utilizate pentru a identifica cicluri atunci cind apar in
structuri inlantuite. Aceasta este si cazul blocurilor inlantuite. O eticheta poate fi plasata
inaintea inceputului si dupa sfirsitul unui bloc PL/SQL, astfel incit identitatea sa declarate sa
poate fi deosebita de celelalte blocuri din structura inlantuita. Sa luam exemplul urmator:
DECLARE
var1 NUMBER;
BEGIN
.
DECLARE
var1 NUMBER := 400;
BEGIN
.
var1 := var1 + 1 ; -- var1 din subbloc se mareste cu 1
.
END;
.
END;

Variabila var1 care a fost declarata in blocul exterior nu se "vede" in cadrul blocului interior,
deoarece acesta a declarat o variabila cu acelasi nume. Toate referirile la 'var1' din sub-bloc
vor fi deci folosite pentru variabila local declarata.
Totusi, daca blocurile sint etichetate, identificatorii pot fi referiti prefixati de numele blocului
dorit. (Observatie: blocul exterior nu trebuie neaparat etichetat). Un exemplu:
BEGIN
<> DECLARE
var1 NUMBER;
.
BEGIN
.
<> DECLARE
var1 NUMBER := 400;
BEGIN

248

.
block1.var1 := block1.var + 1;
-- variabila din block 1
-- este incrementata
END block2;
END block1;
END;

Asa cum s-a aratat, END poate include numele blocului care trebuie terminat.

Instructiunea GOTO
Aceasta instructiune ofera salturi neconditionate la o eticheta in cadrul unui program
PL/SQL. Utilizarea instructiunii trebuie minimizata, deoarece folosirea excesiva poate duce
la programe foarte dezorganizate.
Valabilitatea unei etichete este in intregul bloc in care a fost definita. GOTO poate, deci,
transmite controlul catre puncte etichetate din blocul curent sau catre un punct etichetat dintrun alt bloc care contine blocul curent.
Sintaxa:
GOTO eticheta;

Unde 'eticheta' poate fi orice eticheta care marcheaza o pozitie in cadrul blocului curent sau al
altuia ce il cuprinde. GOTO nu poate transmite controlul in interiorul unui sub-bloc.

Exercitii pentru capitolul 22


1. Scrieti un bloc PL/SQL care sa insereze un rind in tabela MESSAGES cu coloana
NUMCOL1 continind 1 daca este primul rind, 2 daca este al 2-lea s.a.m.d. Nu inserati
rinduri etichetate 6 sau 8 si iesiti din ciclu cind valoarea 10 a fost inserata. Actualizati
baza cind se termina ciclul. (atentie - COUNT este cuvint rezervat!)
2. (daca aveti timp) Selectati coloanele ENAME, HIREDATE si SAL din tabela EMP
unde EMPNO este egal cu un numar introdus in timpul executiei. Dupa ce ati selectat
coloanele in variabile, inserai un rind in MESSAGES bazat pe unul din urmatoarele
criterii: Criteriu / Mesaj
Salariu mai mare de 1200
Salariu mai mare de 1200
ENAME contine 'T'
Numele contine "T"
HIREDATE este Decembrie
Decembrie
Nici unul din cazurile precedente
** Nimic **
Testatti pentru angajatii cu numerele 7654, 7369, 7900, 7876.
3. Urmatorul cod executa un ciclu, cu diferite valori pentru V la fiecare interatie (in
domeniul 1 la 10).

249

4.
5.

UPDATE messages SET numcol2 = 100


WHERE numcol1 = V ;

Daca rularea UPDATE produce altceva decit un singur rind, atunci se va iesi din
ciclu.( Puteti testa atributul SQL%ROWCOUNT, asa cum este discutat in capitolul
23).

Solutii la capitolul 22
1.
2.
3.
4.
5.
6.
7.
8.
9.

BEGIN
FOR v_count IN 1..10
LOOP
IF v_count NOT IN (6,8) THEN
INSERT INTO messages (numcol1) VALUES (v_count);
END IF;
END LOOP;
COMMIT;
END;

10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.

DECLARE
v_ename
v_hiredate
v_sal
v_message
BEGIN
SELECT ename,
INTO v_ename,
FROM emp
WHERE empno =

emp.ename%TYPE;
emp.hiredate%TYPE;
emp.sal%TYPE;
CHAR(30);
hiredate, sal
v_hiredate, v_sal
&EMPLOYEE_NO ;

IF v_sal > 1200 THEN


v_message := 'Salariu mai mare de 1200';
ELSIF v_ename LIKE '%T%' THEN
v_message := 'Numele contine "T"';
ELSIF TO_CHAR(v_hiredate, 'MON') = 'DEC' THEN
v_message := 'Decembrie';
ELSE v_message := '** Nimic **';
END IF;
INSERT INTO messages (charcol1) values (v_message);
END;

33.
34.
35.
36.
37.
38.
39.
40.
41.

BEGIN
FOR v IN 1 .. 10
LOOP
UPDATE messages SET numcol2 = 100
WHERE numcol1 = v;
EXIT WHEN SQL%ROWCOUNT <> 1;
END LOOP;
END;

42.

250

CAPITOLUL 23
Tipuri de date compuse
In acest capitol se arata cum se declara si utilizeaza variabile compuse in PL/SQL. In mod
normal, inregistrarile permit aceasta facilitate, permitind reprezentarea unei linii de la o tabela
sau un view.

Inregistrari in PL/SQL
CE SUNT? - O variabila care poate tine citeva valori separate - O colectie de cimpuri
adresabile CUM SUNT DECLARATE INREGISTRARILE? - utlizand %ROWTYPE se
utlizand atribute declarate Single-row structura bazata pe o tabela,sau cursor

Inregistrari in PL/SQL
O inregistrare PL/SQL este o variabila care poate contine valori separate,fiecare adresabila
individual. Partile componente ale unei inregistrari se numesc campuri, si au nume care pot fi
referentiate in atribuiri sau expresii. Campurile dintr-o inregistare pot avea tipuri de date si
marimi diferite. Aceasta inseamna ca inregistrarile sunt foarte avaantajoase cand preluam o
linie dintr-un tabel pentru procesare intr-un program PL/SQL.

Atributul %ROWTYPE
Atributul ROWTYPE este folosit pentru declararea unei inregistrari bazata pe o colectie de
coloane in tabela de baze de date. Campurile cu inregistrarea isi vor obtine numele si tipul
datei lor de la coloanele din tabela sau view referit in declararea inregistrarii.
Cimpurile sint declarate intr-o sectiune bloc DECLARE impreuna cu celelalte tipuri de
variabile pe care le-am vazut.
Sintaxa:
identifier reference%ROWTYPE ;

Unde 'identifier' este numele ales pentru inregistrare ca un intreg, si reference este numele
unei tabele, view sau cursor pe care se bazeaza inregistrarea. Aceasta referinta trebuie sa vie
valida la momentul cind inregistrarea este declarata, adica trebuie sa existe.
Examplu:
DECLARE
emp_rec emp%ROWTYPE
BEGIN
SELECT * INTO emp_rec FROM emp WHERE empno = 7788;

251

In exemplul de deasupra, inregistrarile 'emp_rec'continind cimpuri bazate pe fiecare coloana


in tabla 'emp'. Cimpul va fi populat cu linia selectata de catre numele inregistrari din clauza
INTO a instructiunii SELECT.
Starea inregistrarii emp_rec este aratata mai jos:
Empno Ename Job ...
7788

SCOTT ANALYST ...

Cimpurile dintr-o inregistrare pot fi referite individual, atit in PL/SQL cit si in instructiunile
SQL care apar intr-un bloc.
Exemplu:
IF emp_rec.sal < 2000 AND emp_rec.job = 'MANAGER'
THEN underpaid := TRUE ;
END IF;

review_date := emp_rec.hiredate +90 ;

INSERT INTO emp_history(empno, job, sal, date_stamp)


VALUES (emp_rec.empno, emp_rec.job, emp_rec.sal, SYSDATE);

O intreaga inregistrare poate fi asignata ca valoare unei alte inregistrari, daca tabelele folosite
pentru definirea lor se potrivesc.
EXEMPLU:
DECLARE
record1 salgrade%ROWTYPE;
record2 salgrade%ROWTYPE;
BEGIN
.
record2:=record1;

O intrega inregistrare NU poate fi trecuta listei VALUES al instructiunii INSERT.Trebuie sa


parcurgeti fiecare camp separat.

252

EXEMPLU
INSERT INTO salgrade (grade,losal, hisal) VALUES(record1);-Illegal

INSERT INTO salgrade(grade, losal, hisal)


VALUES(record1.grade, record1.losal, record1.hisal);--legal

Si va vom arata in urmatorul capitol, ca atributul %ROWTYPE poate fi utilizat pentru a


declara inregistrari bazate pe cursoare explicite. Aceste inregistrari pot fi utilizate in
FETCHuri si in cicluri cu cursor FOR .

Inregistrari definite de utilizatori


Versiunea 2 PL/SQL permite deasemenea sa fie definite si crete independent tabela de
structuri. Aceste inregistrari definite de utilizator va permit sa numiti explicit campurile si sa
le definiti tipurile.
In anexa veti gasi informatii suplimentare.

MANIPULAREA %ROWTYPE INREGISTRARI SI CAMPURI


EXEMPLUL 1 -copierea intregilor inregistrari
DECLARE
record 1 salgrade%ROWTYPE;
record 2 salgrade%ROWTYPE;
BEGIN
.
record2:=record1;

EXEMPLU2 -- scrierea unei tabele


INSERT INTO emp_history(empno,job,sal,date_stamp)
VALUES(emp_rec.empno,emp_rec.job,emp_rec.sal.,SYSDATE);

253

CAPITOLUL 24
VIATA SECRETA A CURSOARELOR
Acest capitol va arata cum sa declarati si sa controlati explicit cursoarele, care va permit sa
multiplicati linii de interogare pentru a fi executate in PL/SQL. Ne vom ocupa de felul in care
liniile pot fi aduse de la cursor in interiorul unei bucle prin intermediul cursorului prin bucla.

Ce este un Cursor?
ORACLE foloseste arii de lucru private SQL ,arii care executa declaratii SQL si sa
memoreaza informatii de procesare. Cursorul este o constructie PL/SQL ,care iti permite sa
denumeste aceste arii de lucru si care acceseaza informatia.
Exista doua tipuri de cursor:
cursor implicit
declarand PL/SQL cursor implicit penru toate declaratiile DML si penntru toate
interogarile cu un singur rand
cursor explicit
declarand cursor explicit impreuna cu alti identificatori care sunt folositi in bloc si
manipuland prin declaratii specifice si blocuri excutabile de actiune. Cursoarele
explicite sunt numai interogari si va permit multiple linii care sa proceseze interogari.
Asa cum vedem , SELECT-uri care apar ca instructiuni separate in PL/SQL poat intoarce o
singura linie. Aceasta inseamna ca de fapt PL/SQL incearca sa extraga doua linii de la
cursorul implicit :una sa satisfaca interogarea , si a doua care sa vada daca viitoarele linii au
fost returnate .
Cursoarele explicite va permit sa evitati aceasta a doua extragere , aceasta imbunatatind
eficienta cand o interogare cu un singur rind este ceruta . Cursoarele explicite pot fi utilizate
pentru a rezolva multiple extrageri , si pentru a reexecuta cereri trecute din aria respectiva .
Restul acestui capitol va va explica mult mai pe larg aceste probleme , despre cursorul
explicit.

Controlul explicit al cursorului -pasii separati.


Cursorul explicit poate fi controlat prin 4 tipuri separate de actiuni:
DECLARE
numeste cursorul,si defineste structura interogarii care sa fie efectuate cu el. La acest
nivel,interogarea este parcursa(coloane,tabele etc) dar nu este executata.
OPEN
exercuta interogarea,legand orice variabila care a fost referentiata. Liniile intoarse de
interogare,numita "set-activ" sunt acum disponibile pentru extragere.
FETCH

254

memoreaza valorile din linia curenta in variabile.Linia curenta este linia la care
cursorul pointeaza. Fiecare FETCH produce mutarea cursorului sa indice la linia ur matoare in setul activ,si deci fiecare FETCH va accesa o linie diferita returnata de
interogare.
CLOSE
porneste un set de lucru de linii produse de OPENul cursorului. Este posibil sa
reOPEN (redeschideti) cursorul, stabilind astfel un set de lucru nou.

Instructiunea CURSOR
Este folosit pentru a declara un cursor explicit.Parametrii pot fi definiti pentru a permite
substitutia valorilor in interogare cand cursorul este OPEN.Variabilele pot fi deasemeni
referite in interogare ,dar trebuie sa fie declarate inaintea instructiunei CURSOR.
Sintaxa:
CURSOR identificator[( parameter details)] IS query-expression;

unde query-expression este o instructiune SELECT care poate include majoritatea clauzelor,
dar nu o clauza INTO. Nu trebuie definit NULL ca un obiect SELECT.
Exemplu

DECLARE
CURSOR c1 IS
SELECT ename, sal, hiredate FROM emp
WHERE deptno= 20 AND job= "ANALYST";
;
;

Instructiunea OPEN
Este utilizata in cadrul actiunilor executabile dintr-un bloc, ai stabileste un set activ de
rinduri.
Sintaxa:
OPEN cursor-identif [(lista argumente)] ;

Exemplu:
OPEN c1;

Cursorul va pointa catre primul rind in setul activ, ca de exemplu:


> SCOTT 3000 16-jan-90
FORD 3000 03-dec-81

De observat ca exceptiile nu sint lansate daca cererea nu intoarce nici un rind cind este
deschis cursorul. Starea cursorului poate, totusi, sa fie testata dupa un FETCH.

Instructiunea FETCH
Este utilizata pentru a extrage rindul curent intr-o variabila PL/SQL, sau intr-o variabila host,
inclusiv cimpurile ecran din SQL*forms. Trebuie amintit ca variabilele host necesita punctvirgula ca prefix, pentru a fi deosebite de variabilele PL/SQL.

255

Sintaxa:
FETCH cursor-id INTO var,var,... ;

Variabilele trebuie sa fie specificate pentru fiecare cimp selectat in cererea de cursor. O alta
posibilitate este definirea unei inregistrari pentru cursor, si transmiterea sa ca o clauza a
FETCH.
Exemplu:
FETCH c1 INTO v_ename, v_sat, v_hiredate;

Variabilele incarcate, care au fost declarate inainte de FETCH, pot fi manipulate de alte
instructiuni. FETCH-uri ulterioare vor achizitiona alte rinduri individuale din cerere. De notat
ca primul FETCH care nu obtine nimic, adica daca nu mai ramin rinduri, nu va cauza o
eroare. VAriabilele vor contine valori nule.

Instructiunea CLOSE
Inchide in mod explicit un cursor, permitind redeschiderea sa ulterioara. Aceasta inseamna ca
un set activ poate fi restabilit de mai multe ori.
Sintaxa:
CLOSE cursor-identif ;

Atribute explicite pentru cursoare


CA si la cursoarele implicite, exista 4 atribute pentru a obtine informatii de stare despre
cursoare. Cind sint utilizate, numele atributului este precedat de identificatorul cursorului.
%FOUND
Evaluat la TRUE daca ultimul FETCH din cursor a obtinut un nou rind, altfel FALSE
%NOTFOUND
Invers decit %FOUND
%ROWCOUNT
Numarul de rinduri preluate de la cursor pina acum
%ISOPEN
TRUE daca cursorul este deschis, FALSE daca a fost inchis sau nu a fost inca deschis.
Citeva exemple mai jos:
Exemple:
1. IF c1%ISOPEN THEN
FETCH c1 INTO v_ename, v_sal, v_hiredate ;
ELSE
OPEN c1;
2. LOOP
FETCH c1 INTO v_ename, v_sal, v_hiredate ;
EXIT WHEN c1%ROWCOUNT >10 ;
.

256

END LOOP;

Controlul extragerilor multiple din cursoare explicite


In mod normal, cind mai multe rinduri sint prelucrate dintr-un cursor explicit, un ciclu trebuie
definit pentru a executa FETCH la fiecare iteratie. Daca acest proces continua, se for prelucra
eventual toate rindurile. active. Cind un FETCH esueaza, atributul %NOTFOUND este
TRUE, si poate fi testat. Totusi, daca dupa aceasta se efectueaza un nou FETCH apare o
eroare:
ORA-1002: Fetch out of sequence

Aceasta eroare va termina blocul, eventual cu o exceptia netratata. Este deci important sa se
verifice succesul fiecarui FETCH inainte de alte referiri la cursor. (fie prin alte FETCH sau
comenzi SQL)
Exemplu:
OPEN cursor_1 ;
LOOP
FETCH cursor1 INTO a,b,c,d ;
EXIT WHEN cursor1%NOTFOUND ;
.
.
END LOOP;

Cursoarele si inregistrarile
Am vazut deja ca inregistrarile pot fi definite sa se potriveasca cu structura coloanelor unei
tabele. Este de asemenea posibil sa definim inregistrari bazat pe lista de coloane selectata
explicit de cursor. Aceasta este convenabil pentru prelucrarea rindurilor din setul activ, pentru
ca se poate extrage direct in inregistrare, si valorile rindului vor fi incarcate direct in
cimpurile corespunzatoare ale inregistrarii.
Exemplu:
DECLARE
CURSOR c1 IS
SELECT empno, sal, hiredate, rowid
FROM emp WHERE deptno = 20 AND job = 'ANALYST'
FOR UPDATE OF sal;
emp_record c1%ROWTYPE;
BEGIN
OPEN c1;
.
FETCH c1 INTO emp_record;
.
IF emp_record.sal <2000 THEN ...

De observat ca pseudo-coloana 'rowid' este valida ca articol selectabil, si deci va avea un


cimp corespunzator in inregistrarea 'emp_record'.
Exemplul de mai sus arata de asemenea utilizarea FOR UPDATE intr-o cerere cu cursor.
Aceasta inseamna ca rindurile intoarse de cerere sint blocate exclusiv cind instructiunea
257

OPEN este executata. Deoarece blocarile sint eliberate la sfirsitul unei tranzactii, nu trebuie
sa executati COMMIT intre extrageri dintr-un cursor explicit daca se foloseste FOR
UPDATE.

Folosirea clauzei WHERE CURRENT OF


Cind ne referim la rindul-curent dintr-un cursor explicit, comenzile SQL pot folosi WHERE
CURSOR OF, cu numele cursorului. Aceasta permite actualizarea sau stergera in punctul in
care ne aflam, fara a fi necesara folosirea explicita a Rowid. Trebuie totusi sa includeti FOR
UPDATE in cererea cursorului, astfel incit rindurile sa fie blocate la deschidere.
Exemplu:
FETCH c1 INTO emp_record ;
IF emp_record.ename = ' KING' THEN
DELETE FROM emp WHERE CURRENT OF c1;
;

Sa luam un exemplu comlet. In blocul de mai jos se prelucreaza fiecare rind din tabela 'dep',
mutind departamentul SALES in locatia Dallas, si celelalte departamente la New York. De
asemenea se tine un contor al departamentelor plasate in fiecare locatie.
DECLARE
CURSOR c1 IS
SELECT dname, loc FROM dept
FOR UPDATE OF loc ;
dept_rec
c1%ROWTYPE;
sales_count
NUMBER:=0 ;
non_sales
NUMBER := 0;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO dept_rec;
EXIT WHEN c1%NOTFOUND;
IF dept_rec.dname = 'SALES' AND dept_rec.loc !=
'DALLAS'
THEN
UPDATE dept SET loc = 'DALLAS' WHERE
CURRENT OF c1;
sales_count := sales_count + 1;
ELSIF dept_rec.dname != 'SALES' AND dept_rec.loc !=
'NEW YORK'
THEN
UPDATE dept SET loc = 'NEW YORK' WHERE
CURRENT OF c1;
non_sales := non_sales +1 ;
END IF;
END LOOP;
CLOSE c1;
INSERT INTO counts (sales_set, non_sales_set )
VALUES (sales_count, non_sales);
COMMIT;
END;

258

Cursoare cu parametrii

Parametrii permit transmiterea unor valori unui cursor cind acesta este
deschis, si utilizarea in cererile care se executa.
Aceasta inseamna ca un cursor explicit poate fi deschis de mai multe ori
intr-un bloc, intorcind seturi de lucru diferite cu fiecare ocazie.

Parametrii sint definite in instructiunea CURSOR astfel:


CURSOR identif ( param-name data-type,
param-name date-type, ... ) IS query-expresion;

Tipurile parametrilor sint aceleasi cu ale variabilelor scalare, dar nu


primesc dimensiune.
Numele parametrilor sint pentru referire in cadrul expresiei de cerere din
cadrul
cursorului, si pot fi tratate ca variabile PL/SQL.
Urmatorul exemplu arata numarul departamentului si tipul jobului care sint
transmise intr-o clauza WHERE
prin parametrii Param1 si Param2:
CURSOR c1 ( Param1 NUMBER,
Param2 CHAR ) IS SELECT ename, sal, hiredate
FROM emp
WHERE deptno = Param1
AND
job = Param2;

Cind cursorul este ulterior deschis, valorile sint transmise pt. fiecare
din parametrii in mod pozitional.
VAlorile din PL/SQL sau variabile host pot fi utilizate, si de asemenea
literali.

Exemplu:
OPEN c1 (30, 'ANALYST');

259

OPEN c1 (pl_num, 'CLERK');


OPEN c1 (10, job_type); -- job_type este o variabila PL/SQL

Cicluri LOOP cursor

PL/SQL ofera un tip special de ciclu FOR pentru a prelucra rindurile


intoarse in cursorul explicit.
Intr-un ciclu FOR cursor, un cursor declarat este deschis, se efectueaza
extrageri si este
inchis automat cind toate rindurile au fost prelucrate.
Fiecare iteratie a ciclului extrage un rind din setul activ intr-o
inregistrare,
care este declarata implicit pentru utilizare in cadrul ciclului.
Ciclul este terminat automat la sfirsitul iteratiei pentru ultimul rind
extras.

Ciclurile FOR cu cursor sint structurate astfel:


DECLARE
CURSOR cursor_name [ (parameters)] IS query-expresion;
BEGIN
FOR record-name IN cursor-name [ (parameters) ]
LOOP
--procesare valori din rindul curent.
.
END LOOP;

Inregistrarea numita in instructiunea FOR este declarata intern in ciclu si


valabilitatea
expira cind se termina ciclul.
Fiecare iteratie provoaca extragerea rindului urmator din inregistrare.
Deoarece cursorul este declarat explicit in bloc, atributele sale sint
disponibile in cadrul
ciclului pentru testare, daca este necesar.

260

Exemplu:
DECLARE
CURSOR c1 IS SELECT n1, n2, n3 FROM data_table;
result NUMBER;
BEGIN
FOR rec IN c1 LOOP
result := rec.n2 / (rec.n1 + rec.n3);
INSERT INTO temp_tab VALUES (result);
END LOOP;
COMMIT;
END;

Cicluri FOR cursor cu parametrii

Daca cursorul pe care il procesati intr-un ciclu FOR cursor a fost definit
cu
parametrii, valorile (parametrii actuali) sint date in paranteza, dupa
numele cursorului in instructiunea FOR.

CURSOR c1 (Param1 DATE ) IS


SELECT ename, job FROM emp
WHERE hiredate < Param1 ;
BEGIN
FOR emp_record IN c1 ('01-JAN-92')
LOOP
-- vor fi activi angajatii de dupa ian92
END LOOP;

Sub expresii select in ciclurile FOR

Am vazut ca ciclurile FOR cu cursor sint un mod convenabil de a prelucra


rinduri dintr-un cursor explicit declarat in program. Ciclurile FOR pot fi
de asmenea
utilizate pentru a prelucra cereri multi-rind, care sint definite la
inceputul ciclului.
Structura este aratata mai jos:

261

FOR rec-name IN (query-expresion)


LOOP
.
END LOOP;

Expresia cererii este considerata ca o sub-expresie si este prelucrata


intr-un cursor care este intern ciclului FOR.
Deoarece cursoarele nu sint declarate cu nume, atributele cursoarelor nu
sint disponibile pentru testare.
In afara ca este mai simplu de scris, aceasta metoda este si mult mai
eficienta.

Exemplu:
FOr rec IN (SELECT ename FROM emp WHERE deptno = 10 )
LOOP
IF rec.ename = 'JONES' THEN
.
END LOOP;

CIteva cuvinte despre eficienta


Toti factorii care influenteaza performanta unui program SQL se aplica si
la
PL/SQL.
Acestia includ:

Indexarea coloanelor folosite in WHERE si in join


Prefixarea coloanelor cu numele tabelei
In joinuri indexate, referirea la tabela cea mai mica la sfirsit

In plus, PL/SQL mai ofera functionalitate care face instructiuni SQL


nenecesare.

262

Nu accesati baza de date daca nu este necesar.

Daca toate datele de prelucrat sint stocate in variabile, atunci


folositi constructii PL/SQL ca atribuirea sau IF. Nu folositi
SELECT..FROM SYS.DUAL in mediul PL/SQL,
deoarece produce deschiderea unui cursor si transmiterea unor
cereri catre RDBMS.
Efectuati calcule in SELECT, daca este posibil.
DAca aveti de efectuat prelucrari este mult mai eficient sa le
efectuati
atunci cind SELECT-ati date, si evitati instructiuni ulterioare
care ar fi necesare.
Cursoarele explicite va permite evitarea unui FETCH ulterior.

Atunci cind un singur rind este necesar, cursoarele implicite


executa doua extrageri.
Un cursor explicit va permite sa efectuati o singura extragere.
Evitati treceri repetate prin tabele.

Prelucrarea procedurala permite un control puternic si flexibil al


rindurilor bazei de date,
dar trebuie sa tineti cont ca fiecare INSERT si UPDATE provoaca rescanarea tabelei; Daca prelucrati mai multe rinduri dintr-o tabela,
incercati sa o faceti intr-un singur pas.

Considerati situatia urmatoare. Dorim sa marim costul fiecarui


articol din tabel 'items', pe rind, pina cind suma depaseste 5000. In
primul exemplu, o scanare a tabelei este utilizata de fiecare data
pentru a recalcula totalul cind un articol este actual
izat:
WHILE total < 5000
LOOP
FETCH item_cursor INTO old_cost;
UPDATE items SET itemcost = itemcost *1.1
WHERE CURRENT OF item_cursor;
SELECT SUM(itemcost) INTO total FROM items;
END LOOP;

263

O atribuire ar putea evita 'SELECT SUM' la fiecare iteratie,


calculind cit
de mult totalul ar fi afectat de ultima actualizare:
WHILE total < 5000
LOOP
FETCH item_cursor INTO old_cost;
UPDATE items SET itemcost = itemcost *1.1
WHERE CURRENT OF item_cursor;
tottal := total + old_cost *0.1;
END LOOP;

O discutie mult mai detaliata despre eficienta poate fi gasita in


cartea
'Application Tuning for ORACLE Version 6' (cod AT6).

Exercitii

Exercitiul Demonstratie - utilizarea cursoarelor


explicite si a atributelor.

"Fair Deals" s.a. a decis sa recompenseze citiva angajati cu premii.


Ei intentioneaza sa mareasca salariul individual cu 10 % , incepind
cu cel mai prost platit muncitor sau grup.
Daca la orice moment suma totala depaseste 35000, nici un alt
salariat nu va mai primii cresteri.

Scrieti un bloc PL/SQL care sa efectueze aceste operatii in tabela


NEWEMP.
Blocul trebuie sa SELECT-eze suma salariilor doar o singura data, si
sa efectueze o singura trecere prin tabela.

Scrieti un rind in MESSAGES cu numarul de angajati actualizati, si


suma salariilor la sfirsitul blocului.

Nota: Blocul poate actualiza toate rindurile inainte de a atinge


totalul de 35000. Este acceptabil. Puteti rula din nou blocul pentru
cresteri ulterioare.

264

Utilizarea ciclurilor FOR cu cursor si inregistrare


Scrieti un bloc utilizeaza un ciclu FOR cu cursor care sa selecteze
primii 5 din tabela EMP, si sa scrie rezultatul in tabela MESSAGES.
REzultatul va fi de genul:
numcol1 numcol2 charcol1
-----------------------7839
5000
KING
...

Solutii
1.
DECLARE
CURSOR cur1 IS select sal from newemp
ORDER BY sal
FOR UPDATE OF sal;
v_count NUMBER := 0 ;
totsal NUMBER (9,2) := 0;
v_sal emp.sal%TYPE;
BEGIN
SELECT SUM(sal) INTO totsal FROM newemp;
OPEN cur1;
WHILE totsal <=35000
LOOP
FETCH cur1 INTO v_sal ;
EXIT WHEN cur1%NOTFOUND;
U
2.

265

CAPITOLUL 25
MAI MULTE DESPRE EXCEPTII
Am vazut deja cum exceptiile predefinite apar si cum le manuim. Acum vom consolida
aceste caracteristici uitandu-ne peste exceptiile definite de utilizator si cum le putem asocia
cu conditii interne.

CAND SUNT GENERATE EXCEPTIILE?


--printr-o conditie 'interna'
ex.:
Error- 1403 produce NO_DATA_FOUND

--prin generarea lor explicita


ex.:
RAISE my_exception;

Generarea exceptiilor
Exceptiile in general apar in doua moduri:
O eroare in ORACLE este asociata intern cu o exceptie.Aceasta exceptie este "ridicata"
automat ca un rezultat. De exemplu daca eroarea ORA-0001 apare cand scriem in baza de
date atunci exceptia DUP_VAL_ON_INDEX este ridicata de PL/SQL.
O exceptie este generata implicit prin declaratia RAISE in cadrul unui bloc.
Sintaxa :
RAISE exceptie_identificator;

Exceptia generata deliberat poate fi fie una definita de utlizator sau o exceptie interna
predefinita.
Este de dorit a genera o exceptie in conditii in care acea exceptie nu ar aparea normal . De
exemplu,sa presupunem ca o interogare particulara are nevoie sa produca o eroare daca
intoarce orice rand. In mod normal numai cand mai mult de un rand este intors apare exceptia
TOO_MANY_ROWS:
BEGIN
SELECT 'anything' INTO PLVAR FROM emp
WHERE deptno = dept_number;
IF SQL%FOUND THEN

266

RAISE TOO_MANY_ROWS;
END_IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;

Deasemenea observati cat timp 'NO_DATA_FOUND' este considerat normal pentru aceasta
interogare, declaratia SELECT poate sa primeasca un sub_block in care exceptia are un
identificator nul. Cealalta exceptie TOO_MANY_ROWS va fi transmisa la blocul exterior.

EXCEPTII DEFINITE DE UTILIZATOR


--nume declarate de utilizatori
--RAISE cand trebuie sa termini procesarea
--permite definirea propriilor conditii

SINTAXA
identifier EXCEPTION

EXEMPLU
DECLARE
credit_exceeded EXCEPTION;
BEGIN
IF stock_ordered>credit_limit THEN
RAISE credit_exceeded;
END IF

Exceptii definite de utilizator


Exceptiile pot fi declarate impreuna cu alti identificatori la inceputul unui bloc. Aceste
exceptii user_defined pot fi generate pentru situatii in care nici o procesare ulterioara a
actiunilor blocului nu trebuie sa apara. Exceptiile sunt declarate astfel :
identificator EXCEPTION;

267

Exceptiile user_defined ne permit sa definim identificatori convenabili pentru propriile


noastre conditii anormale. Cand apar aceste conditii exceptiile pot fi generate a.i . controlul
este trecut la un identificator exceptie la sfarsitul blocului:
DECLARE
credit_exceeded EXCEPTION;
BEGIN
IF stock_ordered> credit_limit THEN
END IF;

EXCEPTION
WHEN credit_exceeded THEN ...

Declararea numelor pentru exceptii interne


Sa ne amintim ca PL/SQL are nume predefinite pentru cateva dintre codurile exceptiilor
interne dar nu pentru toate . Se pot prinde exceptiile fara nume cu identificatorul WHEN
OTHERS, dar se poate dori declararea numelor propiilor exceptii pentru cateva coduri in mod
specific. PL/SQL furnizeaza o pragma numita EXCEPTION_INIT , care ne permite
specificarea unui nume de exceptie declarata, si numarul erorii ORACLE de care este legat.
Sintaxa:
PRAGMA EXCEPTION_INIT( exception-identifier, number) ;

`Exception-identifier` trebuie sa fi fost deja declarat in partea de declaratie a


blocului.`Number` se refera la un numar de eroare tip executie.
Exemplu:
DECLARE
fetch_failed EXCEPTION;
PRAGMA EXCEPTION_INIT (fetch_failed, -1002);
.
BEGIN
.
FETCH cursor1 INTO record1;
.
FETCH cursor1 INTO record1;
aici

268

/* Daca eroarea -1002 apare

atunci exceptia
fetch_failed
este ridicata
automat

*/

EXCEPTION
WHEN fetch_failed THEN ...

Mai multe despre tratarea exceptiilor


Cind controlul este trecut partii EXCEPTION a unui bloc, numai o exceptie va fi intr-o stare
`generata`. Se poate totusi dori definirea acelorasi actiuni pentru a minui mai mult de o
exceptie:
WHEN invalid_number OR value_error THEN
INSERT INTO problems (...)

Identificatorul WHEN OTHERS prinde toate exceptiile neincluse deja. Citeva instrumente
ORACLE ca SQL*Forms au exceptiile lor predefinite pe care le poti genera pentru a produce
evenimente. WHEN OTHERS le va prinde si pe acestea !

EXERCITII
1. Produceti un fisier SQL*Plus care accepta trei parametri (&1, &2, &3) reprezentind
numarul departamentului, numele departamentului si locatia. Blocul PL/SQL din acest fisier
trebuie sa produca o exceptie USER-DEFINED daca nr. departamentului este 33 inregistrind
un mesaj adecvat in MESSAGES. Daca nu este 33 atunci numarul, numele si locatia trebuie
sa fie inregistrate ca un rind in tabelul NEWDEPT (care are aceleasi coloane ca DEPT).
Fisierul trebuie sa fie executabil in urmatorul mod:
@FILENAME 50 TRAINING BRACKNELL

Daca aveti timp: 2. Produceti un bloc pentru a sterge toate rindurile din tabelul PROJECTS.
Definiti o exceptie care sa prinda eroarea interna -2292 (Integrity violation), si includeti un
identificator care trimite un mesaj tabelului MESSAGES daca aceasta exceptie apare.

SOLUTII
1.
DECLARE
v_deptno NUMBER := &1;
dept_33 EXCEPTION;
BEGIN
IF v_deptno=33 THENRAISE dept_33;

269

END IF;
INSERT INTO newdept (deptno, dname, loc)
VALUES (&1, `&2`, `&3`);
EXCEPTION
WHWN dept_33 THEN
INSERT INTO messages (charcoll)
VALUES ('Attempt to create Department 33!');
END;

2.
DECLARE
integ_error EXCEPTION;
PRAGMA EXCEPTION_INIT (integ_error, -2292);
BEGIN
DELETE FROM projects;
EXCEPTION
WHEN integ_error THEN
INSERT INTO messages (charcol1)
VALUES (`Integrity Error`);
END;

270

APPE N DIXA
Pseudo-coloane SQL
Urmatoarea tabela listeaza pseudo-coloanele SQL
CURRVAL
intoarce valoarea curenta in secventa specificata
NEXTVAL
intoarce urmatoarea valoare in secventa specificata
LEVEL
utilizat in comanda SELECT...CONNECT BY;intoarce 1 pentru nodul radacina,2
pentru nodul fiu,etc.
ROWIND
intoarce un sir hexazecimal care reprezinta adresa unui rand.
ROWNUM
intoarce un numar ce indica ordinea randului care a fost selectat din tabela.Primul
rand selectat are un ROWNUM de valoare 1,al doilea are 2,etc.
SYSDATE
intoarce data si timpul curent.
USER
intoarce numele de user al utilizatorului Oracle curent
UID
intoarce un intreg unic asignat fiecarui nume de user (exista un UID pentru fiecare
nume de user).

271

APPE N DIX- B
Cuvinte rezervate SQL
Urmatoarele cuvinte sunt rezervate SQL.Nu puteti sa le utilizati ca nume de obiecte de tip
baza de date daca nu sunt puse intre ghilimle.
Cuvintele urmate de un asterix(*) sunt de asemenea cuvinte ANSI rezervate.
ACCESS

DISTINCT*

ADD

DROP

IS*

ALL*

LEVEL*

ALTER

ELSE*

LIKE*

AND*

EXCLUSIVE

LOCK

ANY*

EXISTS*

LONG

ASC*

FILE

MAXEXTENTS

AUDIT

FLOAT*

MINUS

FOR*

MODE

FROM*

MODIFY*

AS*

BETWEEN*
BY*

NOAUDIT
GRANT*

CHAR*
CHECK*

NOCOMPRESS
GROUP

NOT

CLUSTER
COLUMN

NOWAIT
HAVING*

NULL*

COMMENT
COMPRESS

NUMBER
IDENTIFIED

CONNECT

OF*

CREATE*

IMMEDIATE*

OFFLINE

CURRENT*

IN*

ON*

INCREMENT

ONLINE

272

DATE

INDEX

OPTION*

DBA

INITIAL

OR*

DECIMAL*

INSERT*

ORDER*

DEFAULT*

INTEGER*

DELETE*

INTERSECT*

PCTFREE

DESC*

INTO*

PRIOR*

PRIVILEGES

TABLE*

PUBLIC*

THEN*
TO*

RAW

TRIGGER*

RENAME
RESOURCE

UID

REVOKE*

UNION*

ROW*

UNIQUE*

ROWID

UPDATE*

ROWNUM

USER*

ROWS*
ROWLABEL

VALIDATE

SELECT*

VALUES*

SESSION*

VARCHAR*

SET*

VARCHAR2

SHARE

VIEW*

SIZE
SMALLINT*

WHENEVER*

START

WHERE*

SUCCESSFUL

WITH*

SYNONYM
SYSDATE

273

Cuvinte cheie
Urmatoarele cuvinte cheie au o semnificatie speciala in limbajul SQL suportat de ORACLE
RDBMS dar nu sunt cuvinte rezervate si astfel pot fi folosite ca identificatori.Aceste cuvinte
pot deveni cuvinte rezervate in viitor.
Cuvintele rezervate ANSI sunt indicate printr-un *;cuvintele cheie adaugate in versiunea 6.0
sunt indicate prin +.
ARCHIVELOG+

END+

MXVALUE+

AUTHORIZATION*+

ESCAPE

MINEXTENTS

EVENTS+

MINVALUE

EXEC*+

MOUNT+

BACKUP+
BEGIN*+

MODULE+
FETCH*+

CACHE+

FOREIGN*+

NEXT*+

CHARACTER*+

FORTRAN*+

NOARCHIVELOG+

CLOSE*+

FOUND*+

NOCACHE+

COBOL*+

NOCYCLE+

COMMIT*+

GO*+

NOMAXVALUE+

CONSTRAIN*+

GOTO*+

NOMINVALUE+

CONTENTS+

NOORDER+

CONTINUE*+

INCLUDING+

NORMAL+

CONTROLFILE+

INDICATOR*+

NOSORT+

CRASH

INITRANS+

NUMERIC*+

CURSOR*+

INT*+
ONLY*+

CYCLE+

KEY*+

OPEN*+

DATABASE

LANGUAGE*+

DATAFILE+

LINK

PASCAL*+

DEC*+

LOGFILE+

PCTINCREASE+

DECLARE*+

PCTUSED+

DISMOUNT+

MAXDATAFILE+

PL1*+

DOUBLE*+

MAXINSTANCES+

PRECISION*+

274

MAXLOGFILES+

PRIMARY*+

MAXTRANS+

PROCEDURE*+

READ*+

SQLCOD*+

REAL*+

SQLERROR*+

REFERENCES*+

STATEMENT+

RELEASE+

STORAGE+

RESETLOGS

SWITCH+

REUSE+

SYSTEM+

ROLLBACK+

SAVEPOINT+

TABLES+

SCHEME

TABLESPACE+

SECTION*+

TEMPORARY*+

SEGMENT+

TEMPORARY*+

SEQUENCE+
SHARED+

USING*+

SOME*+
SORT+

WRITE*+

SPECIFIED+

WORK*+

SQL*+

PL/SQL Cuvinte rezervate


Urmatoarele cuvinte sunt rezervate si nu trebuie folosite ca nume pentru obiecte database sau
ca identificatori in PL/SQL.
ABORT
ACCEPT
ACCESSADD
ALL
ALTER
AND
ANY
ARRAY
AS
ASC
ASSERT
ASSIGN
AT

275

AUTHORIZATION
AVG
BEGIN
BETWEEN
BODY
BOOLEAN
BY
CASE
CHAR
CHAR_BASE
CHECK
CLOSE
CLUSTER
CLUSTERS
COLAUTH
COLUMNS
COMMIT
COMPRESS
CONNECT
CONSTANT
COUNT
CRASH

CREATE
CURRENT
CURSOR

DATA_BASE
DATABASE
DATE
DBA
DEBUGOFF
DEBUGON
DECLARE
DEFAULT
DEFINITION
DELAY
DELETE
DELTA
DESC
DIGITS
DISPOSE
DISTINCT
DO
Document Summary:
DROP
ELSE
ELSIF
END
ENTRY
EXCEPTION_INIT
EXCEPTION
EXISTS
EXIT
FALSE
FETCH
FOR
FORM
FROM
FUNCTION

276

GENERIC
GOTO
GRANT
GROUP
HAVING
IDENTIFIED
IF
IN
INDEX
INDEXES
INDICATOR
INSERT
INTERSECT
INTO
IS
LEVEL
LIKE
LIMITED
LOOP
MAX
MIN
MINUS
MOD
NEW
NOCOMPRESS
NOT
NULL
NUMBER
NUMBER_BASE
OF
ON
OPEN
OPTION
OR
ORDER
OTHERS
OUT

PACKAGE
PARTITION
PCTFREE
PRAGMA
PRIOR
PRIVATE
PROCEDURE
PUBLIC

RAISE
RANGE
RECORD
RELEASE
REM
RENAME
RESOURCE
RETURN

TABAUTH
TABLE
TABLES
TASK
TERMINATE
THEN
TO
TRUE
TIPE

UNION
UNIQUE
UPDATE
USE

VALUES

277

REVERSE
REVOKE
ROLLBACK
ROWNUM
ROWTYPE
RUN

SAVEPOINT
SCHEMA
SELECT
SEPARATE
SET
SIZE
SPACE
SQL
SQLCODE
SQLERRM
START
STATEMENT
STDDEV
SUBTYPE
SUM

VARCHAR
VARCHAR2
VARIANCE
VIEW
VIEWS

WHEN
WHERE
WHILE
WHILE
WITH
WITH
WORK

XOR

278

ANEXA C
Aceasta anexa furnizeaza o vedere generala asupra principalelor dife- rente dintre Oracle 7 si
Oracle versiunea 6.Diferentele sunt listate in ordinea capitolelor in care apar in acest manual.

Vedere generala asupra Oracle Versiunea 6


Oracle Versiunea 6 e disponibil in 2 forme:Oracle Versiunea 6 cu "Optiuni de procesare a
tranzactiilor"(Tranzaction Processing Options) (TPO) sau fara "Optiuni de procesare a
tranzactiilor" adauga la Oracle Versiunea 6 RDBMS furnizind un mecanism de nivel de
inchidere a sirurilor care inchide siruri in modul exclusiv in mod obisnuit si adaugind un
motor PL/SQL in database.

Capitolul 4
Oracle Versiunea 6 SQL-Functii numerice
In Oracle versiunea 6 , urmatoarele functii numerice nu sint accepta- te:
SIN,COS,TAN,SINH,COSH,TANH,EXP,LN, si LOG.
Functiile de putere nu admit exponenti neintegrabili.

Capitolul 6
Oracle Versiunea 6 -Formatul datelor
Codul Formatului Relativ de date (RR) nu e admis.
Pentru lucrul cu ani in orice secol altul decit al 20-lea trebuie folosita functia TO_DATE .

Capitolul 8
Oracle Versiunea 6 -Operatori
Operatorul UNION intoarce toate sirurile distincte obtinute dintr-o cerere.Aceasta a fost
marita in Oracle 7 cu operatorul UNION ALL pentru a include sirurile duplicate.
Sinonimul SOME nu e acceptat de operatorul ANY.

CAPITOLUL 12
Oracle 6 - Limbajul de definire a datelor si a structurilor de date
Unica constringere impusa de Oracle 6 RDBMS este NOT NULL;pentru toate celelalte
constringeri, sintaxa este acceptata si definitiile constringerilor sint stocate in dictionarul de
date, dar nu sint impuse pentru operatiile DML.

279

Clauza CONSTRAINT din comanda CREATE TABLE are diferite sintaxe.In Oracle 7
sintaxa este:
CREATE TABLE emp
(empno numar (4) CONSTRAINT nume_constringere cheie primara ...)

In Oracle Versiunea 6 sintaxa este:


CREATE TABLE emp
(empno numar (4) cheie primara CONSTRAINT nume_constringere ...)

In comenzile CREATE sau ALTER clauzele ENABLE si DISABLE nu sint valide.


Comanda DROP nu are optiunea CASCADE.
Comanda TRUNCATE nu este suportata.

Oracle 6 - Tipuri de date


Oracle 6 suporta un tip de date pentru siruri de caractere:
CHAR
Valorile acestui tip de date sint variabile siruri de carac- tere de lungime de maxim
255 caractere.Oracle Versiunea 6, de asemenea suporta urmatoarele variante pentru
tipul de date caracter:

CHARACTER
VARCHAR

In Oracle 6 tipul de date LONG este de asemenea suportat.Acesta este similar cu CHAR, dar
poate detine valori pina la lungimi de 65,535 caractere.

CAPITOLUL 15
Oracle 6 - Blocari
Modul in care Oracle 6 foloseste blocarile depinde de daca exista sau nu TPO.
Oracle 6 cu TPO foloseste blocarile in acelasi mod ca Oracle 7.
Oricum, in absenta TPO, doar un singur utilizator, la un moment dat, este capabil sa ceara sa
actualizeze o tabela din baza de date.O blocare exclusiva, ascunsa pe linii este plasata pe
tabela cind apare sau o declaratie INSERT, UPDATE sau o declaratie DELETE.Rezultatul
blocarii pe intrarea tabelei inter- zice altor utilizatori de cereri orice modificare de date pina

280

cind cel ce a blocat tabela nu o va debloca.Ceilalti utilizatori sint introdusi intr-o coada de
asteptare.

CAPITOLUL 16
Oracle 6 - Views (vederi)
Pentru a redefini o vedere este necesar sa o micsoram si apoi sa o refacem. De asemenea o
vedere nu poate fi creata pina cind tabelele pe care le folo- seste nu exista deja.In Oracle 7 atit
clauza OR REPLACE cit si clauza FORCE furnizeaza aceste inlesniri.

CAPITOLUL 17
Oracle 6 - Securitatea si administrarea
Comanda GRANT este folosita pentru a crea noi utilizatori si a le da drep- turi.Cele trei
drepturi de sistem disponibile sint:
CONNECT
capacitatea de a te loga la Oracle si a accesa orice obievte asupra carora ai
drepturi.Pot fi create vederi si sinonime.
RESOURCE
capacitatea de a crea tabele si indexari.
DBA
capacitatea de a crea alti utilizatori si de a ocoli accesul protejat.
ROLES, multimea de drepturi, nu este suportata.

CAPITOLUL 18
Oracle 6 - Indexari unice
Indexarile unice nu sint create automat cind sint specificate constringerile de integritate sau
cheia primara.Comanda CREATE UNIQUE INDEX trebuie sa fie data explicit.

CAPITOLUL 19
Oracle 6 - Generalitati
PL/SQL Versiunea 1 este motorul PL/SQL folosit de RDBMS.Astfel procedurile, functiile si
package-urile stocate si trigger-ele nu sint disponibile in Oracle Versiunea 6 RDBMS.Acestea
sint disponibile in PL/SQL Versiunea 2.

281

ANEXA D
ORDINEA DE COMPARATIE
Caracterele sint comparate conform cu ordinea de comparatie a calculatorului gazda.Un
caracter este mai mare decit altul daca apare dupa el in ordinea de comparatie.
Multe calculatoare folosesc una din cele doua ordini de comparatie, numite ASCII(American
Standard Code Decimal Interchange Code).Aceste ordini de comparatie sint prezentate mai
jos.
Observatie: Oracle foloseste ordinea de comparatie a calculatorului gazda.
Literele mari si mici nu sint echivalente.In ASCII, toate literele mici sint mai mari ca literele
mari.In EBCDIC, opusul este adevarat.
In ASCII, cifrele de la 0 la 9 sint inaintea literlor din alfabet.In EBCDIC, opusul este
adevarat.
In continuare sint prezentate ordinele de comparatie atit pentru ASCII cit si pentru EBCDIC.

Ordinea de comparatie ASCII :


Urmatorul tabel listeaza ordinea de comparatie ASCII :

Valoare zecimala
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48-57
58

Simbol
blank
!
"
#
$
%
&
'
(
)
*
+
,
.
/
0-9
:

Valoare zecimala
59
60
61
62
63
64
65-90
91
92
93
94
95
96
97-122
123
124
125
126

282

Simbol
;
<
=
>
?
@
A-Z
[
\
]
^
_
'
a-z
{
|
}
~

Ordinea de comparatie EBCDIC


Urmatorul tabel listeaza ordinea de comparatie EBCDIC :
Valoare zecimala
64
74
75
76
77
78
79
80
90
91
92
93
94
95
96
97
107

Simbol
blank
c
.
<
(
+
|
&
!
$
*
)
;

/
,

Valoare zecimala
108
109
110
111
122
123
124
125
126
127
129-137
145-153
162-169
193-201
209-217
226-233
240-249

283

Simbol
%
_
>
?
:
#
@
'
=
"
a-i
j-r
s-z
A-I
j-r
S-Z
0-9

ANEXA E
Crearea Obiectelor unei Baze de Date
Instructiunea CREATE este utilizata pentru crearea tabelelor si a altor obiecte ca de exemplu
INDEX-uri, DOMAIN, VIEWS. Restrictiile pot fi specificate de asemeni le createa tabelelor
( restricttile sunt implementate la nivelul bazei de date).

CREATE TABLE EMP


( EMPNO INTEGER (A) NOT NULL,
ENAME CHAR (10),
JOB CHAR (10),
MGR INTEGER (4),
HIREDATE DATE,
SAL INTEGER (7,2),
COMM INTEGER (7,2),
DEPTNO INTEGER (2) NOT NULL );

Cand se creaza tabela se poate specifica optional domeniul pentru coloana respectiva. In plus,
constrangerile pot fi specificate ca aplicandu-se asupra valorilor unei coloane sau saupra
intregii tabele. Restrictiile pot specifica faptul ca coloanele contin numai anumite valori,
valori unice sau nu pot fi nule. Restrictiile sunt implementate in cadrul bazei de date.
Comanda pentru tabela ALTER permite eliminarea unor coloane individuale.

ALTER TABLE EMP


DROP MGR;

Comanda DROP este utilizata pentu a elimina alte obiecte din baza de date.
De exemplu :
DROP TABLE DEPT;
DROP VIEW SALARY;

INGRES/SQL
INGRES/SQL este un produs al Relational Technology Inc. (RTI). SQL utilizat de INGRES
este acelasi din punct de vedere sintactic ca cel utili zat de alti producatori. Majoritatea
exemplelor de comenzi date pana acum se pot rula si sub INGRES.Oricum, INGRES/SQL nu
are operatorul LIKE.
INGRES suporta caractere speciale pentru utilizarea in comparatii ( in special operatorii de
egalitate ) pentru a indica potrivirile partiale intr-un sir de caractere. Caractere care permit
identificari pestiale sunt :

284

*
identifica orice sir de 0 sau mai multe caractere
?
identifica orice caracter
[..] identifica oricare din caracterele dintre parantezele patrate

INGRES permite ca oricare din aceste caractere speciale sa poata fi folosite singular sau in
combinatie pentru a specifica criteriul de identi ficare partiala:
ename='*'
identifica orice valoare in "ename"
ename='E*'
identifica orice valoare care incepe cu "E"
ename='*ein'
identifica orice valoare care se termina cu "ein"
ename='*[aeiou]*'
identifica orice valoare care are cel putin o vocala
ename='Br??'
identifica orice sir de 5 caractere care incepe cu "Br"
Semnificatia speciala a acestor caractere poate fi eliminata in comparatii de predicate prin
caracterul "backslash" (\). Astfel "\*" se refera la caracterul asterisc. Oricum, atunci cand se
fac atribuiri cu caractere speciale nu trebiue tratate cu specificatiile pentru ndetificarea
partiala:
jtitle='**accountant**'

Deoarece fragmentul de mai sus asigneaza "**accountant**" coloanei "jtitle", stelutele nu


necesita o tratare speciala cu backslash. Dar pentru a extrage o valoare asignata astfel este
necesara sintaxa urmatoare :
job.title='\*\*accountant\*\*'

Specificatiile de identificare patriala pot fi utilizate impreuna cu predicatele "between" si


"in".
INGRES nu accepta valori NULL. Daca nu se completeaza cu o valoare la inserarea unei
coloane atunci INGRES va depozita o valoare implicita in acel camp. In functie de tipul datei
dintr-o coloana valoarea impicita poate fi 0 sau spatii.
Tipurile de date disponibile in INGRES/SQL par a fi cea mai mare di ferenta fata de
majoritatea variantelor de SQL.
Tipurile de date sunt :
c1 - c255
vchar(1) - vchar(2000)

character
vchar

Un sir de 1..255 caractere


Un sir de 1..2000 caractere

285

integer1
integer2 (smallint)
integer4(integer)
float4

intreg de
intreg pe
intreg pe
real pe 4

float8(float)

real pe 8 bytes

date
(pentru

1 byte
2 bytes
4 bytes
bytes

data (12 byte)

-128 .. 127
-32,768 .. 32,767
-2,147,483,648 .. 2,147,483,647
-10**78 .. 10**75 precizie
7 zecimale
-10**78 .. 10**75 precizie
15 zecimale
1-ian-1582 .. 31-dec-2382
date absolute si -800 ani la

800
money

money8(byte)

ani (ptr. intervale de timp)


#-99999999999999.99 ..
#99999999999999.99

Destinatiile smallint, float, integer pot fi utilizate in locul notatiei integer2, float8, integer4
respectiv.
Astfel pentru a crea tabela EMP:

CREATE TABLE EMP


( EMPNO INTEGER2,
ENAME VCHAR(10),
JOB VCHAR (20),
MGR INTEGER2,
SAL MONEY,
COMM MONEY,
DEPTNO INTEGER1);
Tabelele SALGRADE si DEPT por fi create dupa cum urmeaza :
CREATE TABLE SALGRADE
( GRADE INTEGER1,
LOSAL MONEY,
HISAL MONEY);

CREATE TABLE DEPT


( DEPTNO INTEGER1,
DNAME VCHAR(10),
LOC VCHAR(10));

Comanda pentru utilizarea tabelelor este aceeasi ca cea a altor producatori (instructiunea
INSERT). Instructiunea DROP poate fi utilizata pentru a elimina obiecte din baza de date.

Vedere de ansamblu
O scurta vedere de ansamblu asupra SQL implementat in 3 RDBMS-uri -DB2, Rdbs si
Ingres.
SQL este limbajul standard pentru RDBMS-uri si toate RDBMS-urile majore suporta cateva
forme ale SQL.
Acest apendice furnizeaza o scurta vedere de ansamblu a SQL-ului imple- mentat in RDBMS
de catre trei furnizori proeminenti de RDBMS -DB2 al lui IBM, Rdb al DEC si Ingres al lui
Relational Technology . Informatia prezentata nu intentioneaza sa fie o comparatie
cuprinzatoare a acestor produse . Intentia mea este sa arat ca , de cand toate RDBS-urile
286

majore suporta SQL va puteti transfera priceperea pe care ati capatat-o in SQL de la un
RDBMS la altul.

DB2
Database 2 ( DB2 ) este RDBMS-ul IBM-ului pentru mediul MVS.
Implementarea DB2 a SQL-ului este identica cu SQL-ul ORACLE-ului . Intr-adevar SQL-ul
folosit pentru DB2 (si SQL/DS-RDBMS-ul IBM-ului pentru DOS/USE si mediul de operare
VM/SP) a format modelul pentru limbajul SQL . Reamintiti-va ca limbajul SQL a fost
dezvoltat de IBM pentru prototipul lor RDBMS-System R , dar ORACLE a intodus prima
implementare comerciala posibila a SQL-ului.

Sintaxa declaratiei SELECT


Clauzele de baza ale declaratiei SELECT sunt listate mai jos:
SELECT

[ALL/DISTINCT] { [Tabela articol(e)/expr [alias] }

FROM tabela(e) [alias]


[WHERE predicat]
[AND predicat]
[OR predicat]
GROUP BY coloana(e) ]
[HAVING predicat]
[ORDER BY coloana(e)]

Cateva exemple simple de comenzi SQL urmeaza:


EXEMPLE:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.

SELECT *
FROM EMP;
SELECT DISTINCT DEPTNO
FROM DEPT;
SELECT DEPTNO, ENAME
FROM EMP
WHERE JOB = 'CLERK'
ORDER BY JOB DESC;
SELECT EMPNO, ENAME, JOB, SAL
FROM EMP
WHERE ENAME LIKE 'S%';
SELECT ENAME, JOB, COMM

287

17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.

FROM EMP
WHERE COMM IS NULL;
SELECT E.EMPNO, E.ENAME, D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;
SELECT DEPTNO, DNAME
FROM EMP
WHERE NOT EXISTS
(SELECT DEPTNO
FROM EMP);
SELECT SUM(SAL), DEPTNO
FROM EMP
GROUP BY DEPTNO
HAVING SUM(SAL) 3500;

Ceea ce este mai sus , este doar un specimen simplu al comenzilor SQL care pot fi scrise
folosind SQL-ul lui DB2. Un rand intins ,de alti operatori este suportat de DB2; operatori de
comparatie, operatori booleeni (AND, OR, NOT) , operatori speciali (EXISTS, IN,
BETWEEN, LIKE, IS), operatorul pe multime UNION, etc...
DB2 nu suporta direct JOIN-ul extern. Deasemenea, operatorii INTERSECTION si
DIFFERENCE nu sunt suportati direct (operatorul UNINO ALL poate fi folosit pentru a
construi aceste trasaturi).
DB2 furnizeaza un numar de operatori si functii care pot fi folositi in constructia expresiilor.
Unele dintre aceste functii si operatori sunt rezu- mate mai jos.
Operator/functie
---------------+,-,*,/
impartire.

Descriere
--------Adunare, scadere, inmultire,
Pot fi folositi cu date, timpi si
timestamp-uri.

||

Concatenare-folosit pentru a alatura

2
siruri de caractere sau 2 siruri
grafice.
CHAR
timestamp

Converteste o data, timp sau


in reprezentarea sirului sau de

caractere.
DATE

Converteste o valoare scalara intr-o


data.

DAY/MONTH/YEAR

Extrage portiunea de zi, luna sau an


dintr-o data sau timestamp.

DAYS

Converteste o data sau un timestamp

288

intr-un numar de zile.


DIGITS

Converteste un numar intr-un sir de


caractere.

HOUR/MINUTE/SECOND

Extrage portiunea de ore, minute,secunde din timp sau timestamp.

LENGTH
oc-

Calculeaza lungimea unei valori in


teti.

SUBSTR
VALUE
ne-

Extrage un subsir dintr-un sir.


Converteste un null intr-o valoare
nula.

COUNT/AVG/
MAX/MIN/SUM

Functii combinate

DB2 nu suporta bogatul set de functii care sunt posibile cu ORACLE. Vezi capitolele 4, 5 si
6.
Intentia de aici, nu este de a furniza o comparatie de unu la unu a diferen- telor si
asemanarilor intre si SQL-ul ORACLE-ului. Mai degraba, telul este de a arata ca,
cunostintele dumneavoastra de SQL pot fi transferate de la un RDBMS la altul.

Crearea obiectelor bazei de date


Comanda CREATE TABLE are in esenta aceeasi sintaxa ca si SQL-ul ORACLE-ului,
oricum DB2 are ceva tipuri de date suplimentare:
Integer
Cuvant intreg binar, 31 biti si semn
Smallint
Jumatate de cuvant intreg binar, 15 biti si semn
Decimal (n,m)
Numar zecimal impachetat, n cifre si semn (0<n<="m<=n)"
Float(n) </n
Character(n)
Sir de caractere de 8 biti de lungime fixa (0<n
Varchar(n) </n
Lungimea variabila a celui de mai sus
Graphic(n)
Sir de caractere de 16 biti de lungime fixa (0<n
Vargraphic(n) </n
Lungimea variabila a celui de mai sus
Date
Data reprezentata ca o secventa de 8 cifre zecimale fara semn impachetate (yyyymmdd),
ocupand 4 octeti, valorile permise sunt in domeniul 1 Ianuarie AD pana la 31 Decembrie
9999 AD.
Time
289

Timpul, reprezentat ca o secventa de 6 cifre zecimale fara semn impachetate (hhmmss), ocupand 3 octeti, valorile permise fiind in domeniul miezul noptii pana la miezul noptii. De
exemplu : 000000 pana la 240000
Timestap
Combinatie de data si timp, reprezentata ca o secventa de 20 de cifre fara semn impachetate(yyyymmddhhmmssnnnnnn),ocupand 10 octeti, valorile permise fiind in domeniul
00010101000000000000 pana la 99991231240000000000
Aceste tipuri pot fi abreviate dupa cum urmeaza :
Int
pentru Integer
Decimal(n)
pentru Decimal(n,0)
Decimal
pentru Decimal(5)
Dec
pentru Decimal
Float
pentru Float(53)
Real
pentru Float(21)
Double Precision
pentru Float(53)
Character
pentru Character(1)
Char
pentru Character
Long Varchar
pentru Varchar(n)
Graphic
pentru Graphic(1)
Long Vargraphic
pentru Vargraphic(n)
Cand creati tabele, puteti specifica daca Null-urile sunt permise sau nu in acelasi mod ca si
ORACLE SQL cu o exceptie. DB2 permite declaratia NOT NULL WITH DEFAULT.
Aceasta inseamna ca o valoare nu este ceruta pentru aceasta coloana si va fi inlocuita cu o
valoare nula.
Zero pentru campuri numarice
Blank-uri pentru campuri cu siruri de lungime fixa
Gol (siruri de lungime zero) pentru campuri cu siruri de lungime variabila.Valoarea lui
CURRENT DATE sau CURRENT TIME sau CURRENT TIMESTAMP ,cat mai potrivit.
Deci, pentru a crea o tabela EMP:
CREATE TABLE EMP
( EMPNO INTEGER NOT NULL,
ENAME CHAR(10),

290

JOB CHAR(10),
MGR INTEGER,
HIREDATE DATE,
SAL DECIMAL(7,2),
COMM DECIMAL(7,2),
DEPTNO INTEGER NOT NULL);

Tabela DEPT si tabela SALGRADE pot fi create astfel:


CREATE TABLE DEPT
( DEPTNO INTEGER NOT NULL,
DNAME CHAR(15),
LOC CHAR(15));

CREATE TABLE SALGRADE


( GRADE INTEGER NOT NULL,
LOSAL INTEGER,
HISAL INTEGER);

Comanda ALTER TABLE si comenzile DROP TABLE sunt la fel ca ale lui ORACLE.
Comanda CREATE INDEX este aceeasi deasemenea.

NOTA:
Declaratia Crate Table SQL a lui ORACLE va accepta tipuri de date din DB2 si SQL/DS, si
le converteste intern in tipuri de date ORACLE, dupa cum urmeaza:
DB2 SQL/DS
ORACLE
SMALLINT
NUMBER(38)
INTEGER
NUMBER(38)
DECIMAL(M,N)
NUMBER(M,N)
FLOAT
NUMBER
VARCHAR(N)
CHAR(N)
LONG VARCHAR
LONG
Nu exista tipuri de date ORACLE care sa corespunda pentru GRAPHIC, VARGRAPHIC si
LONG VARGRAPHIC.

VAX Rdb/VMS
Rdb este RDBMS al lui DEC, care lucreaza in mediul VMS.
Urmeaza sintaxa pentru VAX SQL :
SELECT [DISTINCT]/[Tabela.] coloana/expr [alias]
FROM tabela(e) [alias]
[WHERE conditie]

291

[AND conditie]
[OR conditie]
[GROUP BY coloana(e)]
[HAVING conditie]
[ORDER BY coloana(e)]

Exemple:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

SELECT ENAME, SAL*1.1 FROM EMP


SELECT EMPNO, ENAME, JOB FROM EMP
WHERE EMPNO = 7369;
SELECT ENAME, HIREDATE, DEPTNO FROM EMP
WHERE JOB = "MANAGER"
ORDER BY ENAME;
SELECT DEPTNO, JOB FROM EMP
WHERE ENAME LIKE "% S%";

Dupa cum puteti vedea, sintaxa lui VAX SQL este foarte similara cu DB2 si
ORACLE SQL. Operatorul EXISTS ca si [NOT] NULL, [NOT] BETWEEN, ALL,
opera- tori booleeni, JOIN-uri, subcereri, etc sunt toate suportate.Functiile COUNT,
SUM, AVG, MIN, MAX, sunt deasemenea furnizate.

292

ANEXA G
Exportarea Continutului unei Tabele intr-un Fisier
Uneori este util sa avem valorile unei coloane dintr-o tabela intr-un fisier text care poate fi
rulat pentru a insera respectivele valori in tabela. De exemplu cand se distribuie sau se
instaleaza un sistem se doreste funniza rea unui fisier care sa contina informatiile de start-up
pentru o tabela. Asemenea fisier este furnizat odata cu ORACLE pentru tabelele de
demonstratie Emp, Dept si Salgrade.
Desi datele sunt existente in tabela, se poate dori existenta infor matiei in formatul "INSERT
INTO nume_tabela VALUES(,,,,);" SQL din SQL poate fi utilizat pentru a indeplini aceasta.
Urmatorul cod realizeaza blocul INSERT pentru tabela DEPT.

set
set
set
set
set

feed off
head off
pages 0
lines 75
verify off

spool insert.sql
select 'insert into dept', '
values (' ||
deptno || ',' ||
''''||dname||''''||','||
''''||loc||''''||');'
from dept;
spool off
set
set
set
set

feed on
head on
pages 24
verify on

start insert.sql

Pentru fiecare linie din tabela DEPT, codul de mai sus genereaza blocurile INSERT de mai
jos :
insert into dept
values (10,'ACCOUNTING','NEW YORK');
insert into dept
values (20,'RESEARCH','DALLAS');
insert into dept
values (30,'SALES','CHICAGO');
insert into dept
values (40,'OPERATIONS','BOSTON');

Aceste blocuri au fost "capturate" in fisierul "INSERT.SQL".

293

Poate ca ati observat numarul mare de apostrofuri din ultimul exemplu. Un set de 4
apostrofuri genereaza un singur apostrof in blocul final - RETINETI : Sirurile de caractere
trebuie incadrate de apostrofuri !

Astfel :
SELECT '''X'''
SELECT ''''
SELECT ''''||DNAME||''''

intoarce 'X'
intoarce '
intoarce 'BOSTON'

SQL din SQL este o tehnica ce poate fi utilizata pentru a mari tabelele cu valori stocate in
fisiere text. De asemeni pot fi folosite utilitarele IMPORT/EXPORT.
Generarea unor blocuri INSERT pentru o tabela cu multe coloane este costisitor sa generam
coloana cu coloana. In loc, putem extrage informatia din "Data Dictionary".
Intr-adevar, cand se genereaza SQL bazat pe date existente, "Data Dictionary" este locul de
start. Se poate utiliza acest dictionar pentru a furniza parametrii pentru orice bloc SQL.
Urmatorul exeplu utilizeaza infor- matia din "Data Dictionary" pentru a genera blocuri
CREATE TABLE pentru fiecare tabela a utilizatorului. Acest exemplu ilustreaza cateva
tehnici necesare pentru generarea unui SQL complex. SA NU VA INGRIJORATI CA VA
TREBUI SA UTILI- ZATI ACEST COD DE FIECARE DATA CAND DORITI SA
EXECUTATI UN BACK-UP AL TABE- LELOR DUMDEAVOASTRA ! ORACLE
FURNIZEAZA ALTE UTILITARE CARE EXECUTA ACEST LUCRU.

Crearea Tabelelor.
Este mereu o idee buna sa fiti capabili sa regenerati propriile tabele. Puteti sa lasati SQL sa
genereze blocuri CREATE TABLE pentru aceasta. Ecranul "Data Dictionary" user_tab_columns - contine tiate informatiile necesare.
SELECT TABLE_NAME, COLUMN_ID, COLUMN_NAME, DATA_TYPE, DATA_LENGHT,
DATA_PRECISION, DATA_SCALE, NULLABLE
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME IN ('DEPT','EMP','SALGRADE')
ORDER BY TABLE_NAME, COLUMN_ID;

TABLE_NAME COLUMN_ID COLUMN_NAME DATA_T DATA_LEN DATA_PREC DATA_SCALE


NULLABLE
---------- --------- ----------- ------ -------- --------- ---------- ------DEPT
1
DEPTNO
NUMBER
22
2
0
N
DEPT
2
DNAME
CHAR
14
Y
DEPT
3
LOC
CHAR
13
Y
EMP
1
EMPNO
NUMBER
22
4
0
N
EMP
2
ENAME
CHAR
10
Y
EMP
3
JOB
CHAR
9
Y
EMP
4
MGR
NUMBER
22
4
0
Y
EMP
5
HIREDATE DATE
7
Y
EMP
6
SAL
NUMBER
22
7
2
Y

294

EMP
EMP
SALGRADE
SALGRADE
SALGRADE

7
8
1
2
3

COMM
DEPTNO
GRADE
LOSAL
HISAL

NUMBER
NUMBER
NUMBER
NUMBER
NUMBER

295

22
22
22
22
22

7
2

2
0

Y
N
Y
Y
Y

Facilitati ale PL/SQL, versiunea 2


Introducere
PL/SQL adauga in versiunea 2 un numar de facilitati noi in limbaj, multe reflectind
imbunatatiri ale RDBMS Oracle, versiunea .7. Acesutea includ:

Salvarea subprogramelor PL/SQL


Tipuri noi de date
Tabele PL/SQL (variabile array)
Definirea mai flexibila a inregistrarilor

In plus, versiunea 2 a PL/SQL accepta toate noile functii SQL din Oracle7, si toti operatorii
SQL de comparare si setare (EXIST, UNION, etc)

Subprograme PL/SQL
In general versiunea 2 accepta doua tipuri de blocuri PL/SQL, 'blocul anonim' si
'subprogramele'.
Blocul anonim
Este un bloc fara nume. Blocurile anonime erau singurul tip de bloc in versiunea 1.
Aceste blocuri sint declarate in momentul in care sint rulate, si transmise motorului
PL/SQL pentru compilare inainte de a fi rulate.
Subprogramele
Sint blocuri PL/SQL cu nume. Pot fi declarate fie ca proceduri fie ca functii. In
ultimul caz vor intoarce o valoare atunci cind sint apelate.
Cu extinderea procedurala a RDMS, subprogramele pot fi stocate in dictionare de
date, de unde pot fi apelate apoi din mai multe aplicatii cind acel cod este necesar.
(Sint diferite de functiile si procedurile din Form-urile SQL)

Declararea variabilelor si constantelor


PL/SQL v2 accepta o mare varietate de tipuri de date, care pot fi utilizate pentru a declara
variabile si constante. Variabilele pot primii optional o valoare cind sint declarate, si este
permisa schimbarea valorii prin asignari mai tirziu, in cadrul blocului. Constantele sint
identificatori care pastreaza o valoare fixa care trebui atribuita cind constanta este declarata.

Tipuri scalare
Sint tipuri de date care reprezinta o singura valoare. Principalele tipuri sint cele care
corespund coloanelor din bazele de date ORACLE: NUMBER, DATE, CHAR,
VARCHAR2, RAW, ROWID. Exista totusi un numar de subtipuri pentru o definire mai
specifica a variabilelor. In PL/SQL sint permise variabilele Booleene.

Pentru variabile NUMBER


NUMBER

296

VAlori numerice cu precizia maxima de 38 digiti. Valorile sint rotunjite la un intreg,


exceptind cazul cind este data o scala. De exemplu NUMBER(7,2) inseamna 7 digiti,
cu 2 zecimale permise. Precizia implicita este 38.
Sinonime pentru NUMBER sint: DECIMAL, FLOAT, INTEGER, REAL si
SMALLINT. Aceste alternative sint pentru infrumusetare. De exemplu INTEGER(4)
poate fi considerat mult mai descriptiv decit NUMBER(4).

Pentru datele BINARY_INTEGER


BINARY_INTEGER
Este stocat ca un numar binar cu semn, este mult mai eficient pentru intregii folositi in
expresii. Pot avea valori intre -2147483648 si +2147483647.
NATURAL
Acest subtip al BinaryInteger nu permite numere negative.
positive
La fel ca NATURAL, dar nu accepta valoarea zero

Pentru date CHAR


CHAR
Este utilizat pentru a stoca date caracter cu lungime fixa (la fel cu coloanele CHAR
din Oracle7). Lungimea implicita este 1 caracter, maximul permis este 32767. De
exemplu CHAR(20).
Nota: Cind variabile CHAR sint comparate, sint evaluate folosind blankuri pentru
umplere.
VARCHAR2
Se foloseste pentru date cu lungime variabila. Lungimea maxima este cea de la
CHAR, dar valorile VARCHAr sint comparate fara umplere cu spatii.
VARCHAR
La fel, dar semnificatia comparatiei se poate schimba intr-o versiune ulterioara.

Date Booleene
Boolean
Pentru a pastra valorile TRUE si FALSE. Rezultatul expresiilor Booleene pot fi
atribuite acestor variabile, si testate apoi in instructiuni conditionale.

Tipul DATE
DATE
Date valide, ca si coloanele ORACLE tip DATE. Domeniu inter 4712bc si 4712ad.

Tipul RAW
RAW
Pentru a stoca date binare, ca si coloanele RAW ale bazelor de date. Lungimea
maxima este 32767.

Date ROWID
ROWID
Pentru a stoca adrese ROWID in formatul international ROWID. (adica fara conversia
dinamica la date character)

297

De notat ca unele din tipurile de date acceptate de PL/SQL permit lungimi care sint mai mari
decit cele din coloanele corespunzatoare. VARCHAR2 si RAW, ca coloane, permit
maximum 2000 octeti. Coloanele CHAR au maximum 255. Datele caracter din PL/SQL pot
fi totusi scrise in coloane LONG ale bazelor de date daca valoarea lor este prea mare.

Cuvintul cheie DEFAULT


In PL/SQL v2 cuvintul rezervat DEFAULT poate fi optional folosit in atribuiri (:=) pentru a
definii valori initiale pentru variabile si constante. De exemplu, expresia:
tax_year SMALLINT :=92;

Poate fi rescrisa:
tax_year SMALLINT DEFAULT 92;

Cuvintul DEFAULT poate de asemenea sa fie utilizat laparametrii subprogramelor, la


parametrii cursoarelor, si cimpurile inregistrarilor utilizator.

Tipuri noi de date compuse


In PL/SQL v1, atributul %ROWTYPE permitea crearea de variabile bazate pe coloanele unei
tabele, sau a unor coloane selectate dintr-un cursor explicit. In versiunea 2, sint 2 noi tipuri
compuse, numite inregistrari definite de utilizator si tabele PL/SQL.

Inregistrari definite de utilizator


Spre deosebire de inregistrarile create cu atributul %ROWTYPE, inregistrarile definite de
utilizator permit definirea cimpurilor individual intr-o inregistrare. Aceasta se face in 2 etape;
intii definiti tipul inregistrare si apoi puteti declara inregistrari bazate pe acest tip.
Tipul inregistrare este definit cu instructiunea TYPE:
TYPE type-id IS RECORD
(field-name1 field-type [NOT NULL] [:=valoare],
field-name2 field-type [NOT NULL] [:=valoare], ... );

unde valoare este valoarea initiala a cimpului respectiv.


Inregistrarile pot fi declarate apoi bazat pe aceasta structura:
record-id record-type ;

Exemplu:
DECLARE
TYPe time_type IS RECORD (second INTEGER(2) := 0 ,

298

minute INTEGER(2) := 0 ,
hour INTEGER(2) := 0 ) ;
time_rec time_type;

Inregistrarea 'time_rec' va contine acum cimpurile 'second', 'minute', 'hour'. Fiecare va fi


initializat cu 0.
Inregistrarile definite de utilizator si cimpurile lor pot primii valori si pot fi foosite in expresii
in acelasi fel ca si inregistrarile create cu atributul %ROWTYPE. In plus, o inregistrare
definita poate fi utilizata ca tip de date pentru parametrii formali ai unui subprogram.
Inregistrarile pot fi imbricate. Adica, o inregistrare definita anterior poate fi tip de data a unui
cimp dintr-un alt tip de date inregistrare, producind inregistrari in inregistrari.

Tabele PL/SQL
Daca inregistrarile pot reflecta un rind unic, cu mai multe cimpuri, o tabela PL/SQL contine o
structura cu un singur cimp, dar cu rinduri multiple. O tabela PL/SQL este bazata pe un tip de
coloana, dar permite stocarea unui tabel de valori si accesarea lor printr-o cheie primara
(numarul rindului)
Ca si inregistrarile definite, o tabela PL/SQL este definita in 2 pasi.Mai intii se defineste un
tip bazat pe un tip de coloana, si apoi se declara o tabela cu acest tip.
Sintaxa:
TYPE type-id IS TABLE OF col-type [NOT NULL]
INDEX BY BINARY_INTEGER

Unde tipul coloanei poate fi fie un tip utilizat pentru coloane (de exemplu VARCHAR2), sau
o referire la o baza de date cu atributul %TYPE.
Exemplu:
DECLARE
TYPE ename_type IS TABLE OF CHAR(10)
INDEX BY BINARY_INTEGER;

Puteti declara o tabela bazata pe tipul ename_type:


ename_array ename_type;

299

Atribuire de valori unei tablele


Numarul de rinduri dintr-o tabela poate creste si descreste dinamic, in functie de numarul de
valori asignate. Puteti atribui mai mmulte valori de rind intr-o singura atribuire:
ename_array := ('Jean Luc' , 'Kirk' , 'Scott' );

sau individual prin indici:


ename_array(4) := 'troy';

De notat ca rindurile dintr-o baza de date pot fi extrase in rindurile unei tabele PL/SQL sau
invers, dar aceasta trebuie facut pe rind, intr-un ciclu. Daca un rind dintr-o tabela este referit
intr-o variabila acesta trebuie declarat ca BINARY_INTEGER.
Exemplu:
DECLARE
i BINARY_INTEGER := 0;
BEGIN
FOR rec1 IN (select ename from emp)
LOOP
i:=i+1;
ename_array := rec1.ename;
END LOOP;
.
.

-- Tabela ename_array incarcata si gata de actiune

.
END;

300

Anexa
Acestia sunt pasii ce trebuie urmati :

1. Generati prima parte a comenzii CREATE TABLE. Retineti ca de asemenea noi


selectam numele tabelei si o constanta. Aceste doua coloane vor fi folosite numai
pentru a realiza sortarea. Ele nu vor mai fi tiparite la ultimul pas.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.

EX.
set feedback off
set echo off
set head off
select distinct table_name sort1,
0
sort2,
'CREATE TABLE '|| table_name ||' ('
from use_tab_columns
/
DEPT
0
EMP
0
SALGRADE 0

CREATE TABLE DEPT (


CREATE TABLE EMP (
CREATE TABLE SALGRADE (

18. Acum obtinem definitia completa a fiecarei coloane pentru fiecare tabla.
19. EX.
20.
21. break on sort1 skip 1
22. select table_name sort1,
23.
column_id sort2,
24.
' ' ||
25.
column_name ||
26.
decode(data_type, 'DATE',' DATE',
27.
'LONG',' LONG'
28.
'CHAR',' CHAR('||data_length||')',
29.
'VARCHAR','VARCHAR('||data_length
30.
||')',
31.
'NUMBER',
32.
decode(data_precision,null,' NUMBER',
33.
' NUMBER('||data_precision||','||
34.
data_scale||') '),
35.
'*********** INVALID DATA TYPE
**************')||
36.
decode(nulltable ,'N',' NOT NULL',null)||','
37.
from user_tab_columns
38.
order by table_name,column_id
39. /
40.

41. Acum sa urmarim un exemplu complet. El consta din trei SELECT-uri combinate cu
operatorul UNION. Primul genereaza comanda "CREATE TABLE" ,al doilea

301

defineste coloanele pentru fiecare tabela mai putin ultima intrare si ultimul selecteaza
ultima coloana . Tiparirea primei si celei de-a doua coloane ('sort1' si 'sort2') a fost
eliminata folosind optiunea NOPRINT a comenzii COLUMN.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.

EX.
set feedback off echo off head off
set pagesize 9999
col sort1 noprint
col sort2 noprint
break on sort1 skip 1
spool sqlcreates.sql
select distinct table_name sort1,
0
sort2,
'CREATE TABLE '||table_name||' ('
from user_tab_columns
union
select table_name sort1,
column_id sort2,
' '||
column_name||
decode(data_type,'DATE',' DATE',
'LONG',' LONG',
'CHAR',' CHAR('||data_length||')',
'VARCHAR', 'VARCHAR('||data_length||')',
'NUMBER',
decode(data_precision,null,
'NUMBER',

67.
'NUMBER('||data_precision||','||
68.
data_scale||') '),
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.

'******** INVALID DATA TYPE ********')||


decode(nullable,'N',' NOT NULL',null)||','
from user_tab_columns c
where column_id <(select max(column_id)
from user_tab_columns
where table_name = c.table_name)
union
select table_nae sort1,
column_id sort2,
' '||
column_table||
decode(data_type,'DATE',' DATE',
'LONG',' LONG',
'CHAR',' CHAR('||data_length||')',
'VARCHAR', 'VARCHAR('||data_length||')',
'NUMBER',
decode(data_precision,null,
'NUMBER',

86.
'NUMBER('||data_precision||','||
87.
data_scale||') '),
88.
'******** INVALID DATA TYPE ********')||
89.
decode(nullable,'N',' NOT NULL',null)||','
90. /'
91. from user_tab_columns c
92. where column_id = (select max(column_id)

302

93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.

from user_tab_columns
where table_name = c.table_name)
order by 1,2
/
spool off
col sort1 clear
col sort2 clear
set head on feedback on echo on
set pagesize 24
Acest exemplu, relativ complicat produce urmatorul fisier :
CREATE TABLE DEPT (
DEPTNO NUMBER (2,0) NOT NULL,
DNAME CHAR (14) ,
LOC CHAR (13) )
/
CREATE TABLE EMP (
EMPNO NUMBER (4,0) NOT NULL,
ENAME CHAR (10) ,
JOB
CHAR (9),
MGR NUMBER (4,0) ,
HIREDATE DAATE,
SAL NUMBER (7,2),
COMM NUMBER (7,2),
DEPTNO NUMBER (2,0) NOT NULL)
/
CREATE TABLE SALGRADE (
GRADE NUMBER (1,0) NOT NULL,
LOSAL NUMBER (5,0),
HISAL NUMBER (5,0) )
/

GENERARE de Predicate "dinamice"

Este posibil sa capturam clauza "WHERE" intr-o substituire de variabila utilizind optiunea
"NEW_VALUE" a comenzii "COLUMN". Exemplul permite utilizatorului sa genereze un
raport al angajatilor din cadrul unui departament si/sau incepind cu o anumita data.
EX.
Contens of dynamic.SQL
accept deptno char prompt 'Enter deptno; for all'
accept hiredate char prompt 'Enter date ; for all'
set termout off
col c1 new_value where_clause
select decode('&hiredate',
null,' ',
'where hiredate = '''||'&hiredate'||''''
),

303

decode('&hiredate',
numm,'where deptno = '||'||
' and hiredate = '''||'&hiredate'||''''
)
) c1
from sys.dual
/
set verify on
set termout on
select ename from emp &where_clause
/

start dynamic.sql
Enter deptno; for all
Enter hiredate; for all 4-jun-94
SQL> select ename
2 from emp &where_clause
3
SQL> /
old 2: from emp &where_clause
new 2: from emp where hiredate = '4-jun-94'
ENAME
---------TURNER
ADAMS

start dynamic.sql
Enter deptno; for all
Enter hiredate; for all 4-jun-94
SQL> select ename
2 from emp &where_clause
3
SQL> /
old 2: from emp &where_clause
new 2: from emp where deptno = 20

ENAME
-----------------SMITH
JONES
SCOTT
ADAMS

Aceasta tehnica poate fi utilizata de asemenea pentru a permite unui

304

utilizator in timpul rularii sa specifice coloana dupa care sa se ordoneze


fisierul de raport.

Retineti ca pentru a selecta un apostrof trebuie sa folositi doua.

Autori:
Traducere:
Ristoscu Liviu
Tancu Mihaela
Petre Irina
Vasiliu Bogdan
Ivan Laur
Manolache Costin
Pandelea Daniel
HTML:
Vlas Sergiu
Popescu Florin

Traducerea s-a efectuat cu acordul reprezentantei Oracle in Romania, dupa manualul de


training:
Introduction to ORACLE: SQL, SQL*PLUS and PL/SQL, Edition 2.1, Course code:
SPL, Part number: 72101.
@Copyright 1992 Oracle Corporation UK Limited.
Autor: Glenn Maslen
Contributii: Rosaleen Bloomfield, JackieCollins, Jim Dunn, Richard Leech
Toate drepturile sunt rezervate. Aceasta publicatie nu poate fi total sau partial
reprodusa, inregistrata intr-un sistem de stocare a informatiei sau transmisa in nici o
forma si cu nici un sistem electronic, mecanic, fotocopiere, inregistrare sau in alt mod
fara permisiunea prealabila a detinatorului copyright-ului.

305

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