Sunteți pe pagina 1din 8

Baze de date-Anul 2

Laborator 2 SQL
Funcii SQL. Cereri multi-relaie (introducere)
I. [Funcii SQL]
Funciile SQL sunt predefinite n sistemul Oracle i pot fi utilizate n instruciuni SQL.
Ele nu trebuie confundate cu funciile definite de utilizator, scrise n PL/SQL.
Dac o funcie SQL este apelat cu un argument avnd un alt tip de date dect cel
ateptat, sistemul convertete implicit argumentul nainte s evalueze funcia.
Dac o funcie SQL este apelat cu un argument null, ea returneaz automat valoarea
null. Singurele funcii care nu urmeaz aceast regul sunt CONCAT, NVL i REPLACE.
Principalele funcii SQL pot fi clasificate n urmtoarele categorii:
Funcii single-row
Funcii multiple-row (funcii agregat)
1. Funciile single row returneaz cte o singur linie rezultat pentru fiecare linie a tabelului
sau vizualizrii interogate. Aceste funcii pot aprea n listele SELECT, clauzele WHERE,
START WITH, CONNECT BY i HAVING. n ceea ce privete tipul argumentelor asupra
crora opereaz i al rezultatelor furnizate, funciile single row pot fi clasificate n clase
corespunztoare.

Funciile de conversie cele mai importante sunt:


Funcie

TO_CHAR

TO_DATE

TO_NUMBER

Descriere

Exemplu conversie

convertete (sau formateaz) un TO_CHAR(7) = ' 7'


numr sau o dat calendaristic n ir TO_CHAR(-7) = '-7'
de caractere
TO_CHAR(SYSDATE,
'DD/MM/YYYY') = ' 02/12/2005'
TO_DATE('02-DEC-2005','ddconvertete (sau formateaz) un
mon-yyyy')
numr sau un ir de caractere n dat
calendaristic
convertete (sau formateaz) un ir TO_NUMBER ('-25789',
de caractere n numr
'S99,999') = -25,789

Obs: Exist dou tipuri de conversii:


-

implicite, realizate de sistem atunci cnd este necesar;


explicite, indicate de utilizator prin intermediul funciilor de conversie.

Conversiile implicite asigurate de server-ul Oracle sunt:


- de la VARCHAR2 sau CHAR la NUMBER;
- de la VARCHAR2 sau CHAR la DATE;
- de la NUMBER la VARCHAR2 sau CHAR;
- de la DATE la VARCHAR2 sau CHAR.

Funciile pentru prelucrarea caracterelor sunt prezentate n urmtorul tabel:


Funcie

Descriere

ntoarce lungimea irului de


caractere string
ntoarce subirul lui string care
SUBSTR(string, start
ncepe pe poziia start i are
[,n])
lungimea n; dac n nu este
specificat, subirul se termin la
sfritul lui string;
LENGTH(string)

LTRIM(string
[,chars])

RTRIM(string
[,chars])
TRIM (LEADING |
TRAILING | BOTH
chars FROM
expresie)

Exemplu
LENGTH(Informatica)=11

SUBSTR(Informatica, 1, 4) =
Info
SUBSTR(Informatica, 6) =
matica
SUBSTR(Informatica, -5) =
matica (ultimele 5 caractere)
terge din stnga irului string orice LTRIM (' info') = 'info'
caracter care apare n chars, pn
la gsirea primului caracter care nu
este n chars; n cazul n care chars
nu este specificat, se terg spaiile
libere din stnga lui string;
este similar funciei LTRIM, cu RTRIM ('infoXXXX', 'X') =
excepia faptului c tergerea se 'info'
face la dreapta irului de caractere;
elimin caracterele specificate
TRIM (LEADING 'X' FROM
(chars) de la nceputul (leading) ,
'XXXInfoXXX') = 'InfoXXX'
sfritul (trailing) sau din ambele
pri, dintr-o expresie caracter dat. TRIM (TRAILING 'X' FROM
'XXXInfoXXX') = 'XXXInfo'
TRIM ( BOTH 'X' FROM
'XXXInfoXXX') = 'Info'

TRIM ( BOTH FROM ' Info


') = 'Info'
adaug chars la stnga irului de LPAD (LOWER('iNfO'),6)
LPAD(string, length
caractere
string
pn
cnd
= ' info'
[,chars])
lungimea noului ir devine length;
n cazul n care chars nu este
specificat, atunci se adaug spaii
libere la stnga lui string;
este similar funciei LPAD, dar RPAD (LOWER('InfO'), 6, 'X')
RPAD(string, length
adugarea de caractere se face la = 'infoXX'
[,chars])
dreapta irului;
ntoarce string1 cu toate apariiile
REPLACE ('$b$bb','$','a') =
REPLACE(string1,
lui string2 nlocuite prin string3;
'ababb'
string2 [,string3])
dac string3 nu este specificat,
atunci toate apariiile lui string2 sunt REPLACE ('$b$bb','$b','ad') =
'adadb'
terse;
REPLACE ('$a$aa','$') = 'aaa'
transform toate literele irului de LOWER ('InFo') = 'info'
UPPER(string),
caractere string n majuscule, UPPER ('iNfO') = 'INFO'
LOWER(string)
respectiv minuscule;
transform primul caracter al irului INITCAP ('iNfO') = 'Info'
INITCAP(string)
n majuscul, restul caracterelor

3
fiind transformate n minuscule
caut n string, ncepnd de de la INSTR (LOWER('AbC aBcDe'),
INSTR(string, chars
poziia start, a n-a apariie a 'ab', 5, 2)
[,start [,n]])
secvenei chars i ntoarce poziia = 0
respectiv; dac start nu este INSTR (LOWER('AbCdE
specificat, cutarea se face de la aBcDe'), 'ab', 5)
=
nceputul irului; dac n nu este 7
specificat, se caut prima apariie a
secvenei chars;
furnizeaz codul ASCII al primului ASCII ('alfa') = ASCII ('a') = 97
ASCII(char)
caracter al unui ir
ntoarce caracterul corespunztor CHR(97)= 'a'
CHR(num)
codului ASCII specificat
realizeaz concatenarea a dou CONCAT ('In', 'fo') = 'Info'
CONCAT(string1,
iruri de caractere
string2)
fiecare caracter care apare n
TRANSLATE('$a$aa','$','b') =
TRANSLATE(string,
irurile de caractere string i source
'babaa'
source, destination)
este transformat n caracterul
corespunztor (aflat pe aceeai TRANSLATE('$a$aaa','$a','bc')
poziie ca i n source) din irul de = 'bcbccc'
caractere destination
Obs: Testarea funciilor prezentate se face de maniera : SELECT apel_functie FROM dual; astfel c vom omite
comanda SELECT i vom da numai apelul funciei i rezultatul returnat.

Funciile aritmetice single-row pot opera asupra:


- unei singure valori, i aceste funcii sunt: ABS (valoarea absolut), CEIL (partea
ntreag superioar), FLOOR (partea ntreag inferioar), ROUND (rotunjire cu un numr
specificat de zecimale), TRUNC (trunchiere cu un numr specificat de zecimale), EXP
(ridicarea la putere a lui e), LN (logaritm natural), LOG (logaritm ntr-o baz specificat), MOD
(restul mpririi a dou numere specificate), POWER (ridicarea la putere), SIGN (semnul unui
numr), COS (cosinus), COSH (cosinus hiperbolic), SIN (sinus), SINH (sinus hiperbolic),
SQRT (rdcina ptrat), TAN (tangent), TANH (tangent hiperbolic);
- unei liste de valori, iar acestea sunt funciile LEAST i GREATEST, care ntorc cea
mai mic, respectiv cea mai mare valoare a unei liste de expresii.

Funciile pentru prelucrarea datelor calendaristice sunt:


Funcie

Descriere

Exemplu

SYSDATE

ntoarce data i timpul curent

ADD_MONTHS(
expr_date, nr_luni)

ntoarce data care este dup ADD_MONTHS(02-DECnr_luni luni de la data 2005, 3) = 02-MAR-2006.
expr_date;

NEXT_DAY(expr_date,
day)

ntoarce urmtoarea dat dup NEXT_DAY(02-DEC-2005,


data expr_date, a crei zi a Monday) = 05-DEC-2005
sptmnii este cea specificat

SELECT SYSDATE
FROM dual;
(de revzut utilizarea acestei
funcii mpreun cu
TO_CHAR n cadrul
laboratorului 1)

4
prin irul de caractere day
LAST_DAY(expr_date)

ntoarce data corespunztoare LAST_DAY(02-DEC-2005) =


ultimei zile a lunii din care data 31-DEC-2005
expr_date face parte

MONTHS_BETWEEN(ex
pr_date2, expr_date1)

ntoarce numrul de luni dintre


cele dou date calendaristice
specificate. Data cea mai
recent trebuie specificat n
primul argument, altfel rezultatul
este negativ.

MONTHS_BETWEEN(02DEC-2005, 10-OCT-2002) =
37.7419355
MONTHS_BETWEEN(10OCT-2002, 02-DEC-2005) =
-37.7419355

TRUNC(expr_date)

ntoarce data expr_date, dar cu TO_CHAR(TRUNC(SYSDAT


timpul setat la ora 12:00 AM E), dd/mm/yy HH24:MI) =
(miezul nopii)
02/12/05 00:00

ROUND(expr_date)

dac data expr_date este TO_CHAR(ROUND(SYSDAT


nainte de miezul zilei, ntoarce E), dd/mm/yy hh24:mi am) =
data d cu timpul setat la ora 03/12/05 00:00 AM
12:00 AM; altfel, este returnat
data
corespunztoare
zilei
urmtoare, cu timpul setat la
ora 12:00 AM

LEAST(d1, d2, , dn), dintr-o


list
de
date LEAST(SYSDATE, SYSDATE
GREATEST(d1, d2, , calendaristice, funciile ntorc + 3, SYSDATE 5) =
prima, respectiv ultima dat n SYSDATE-5
dn)
ordine cronologic
GREATEST(SYSDATE,
SYSDATE + 3, SYSDATE
5) = SYSDATE + 3
Operaiile care se pot efectua asupra datelor calendaristice sunt urmtoarele:
Tipul de date al
Descriere
Operaie
rezultatului
Scade/adun un numr de zile dintr-o / la o dat.
expr_date -/+
Date
Numrul de zile poate sa nu fie ntreg (putem aduga,
expr_number
de exemplu, un numr de minute sau de ore).
expr_date1
Intoarce numrul de zile dintre dou date
Number
expr_date2
calendaristice. Data expr_date1 trebuie s fie mai
recent dect expr_date2, altfel rezultatul este negativ.

Funcii diverse:
Funcie

Descriere
returneaz then1 dac value este
DECODE(value,
if1,
egal cu if1, then2 dac value este
then1, if2, then2, , ifN,
egal cu if2 etc.; dac value nu
thenN, else)
este egal cu nici una din valorile
if, atunci funcia ntoarce valoarea

Exemplu
DECODE (a, a, b, c) =
b
DECODE (b, a, b, c) =
c
DECODE (c, a, b, c) =

5
else;
dac expr_1 este NULL, ntoarce
expr_2; altfel, ntoarce expr_1.
Tipurile celor dou expresii trebuie
s fie compatibile sau expr_2 s
poat fi convertit implicit la expr_1

NVL(NULL, 1) = 1
NVL(2, 1) = 2
NVL('a', 1) = 'a' -- conversie
implicit
NVL(1, 'a') -- eroare
--nu
are
loc
conversia implicit
dac expr_1 este NOT NULL, NVL2(1, 2, 3) = 2
NVL2(expr_1,
expr_2,
ntoarce expr_2, altfel ntoarce NVL2 (NULL, 1, 2) = 2
expr_3)
expr_3
NULLIF (1, 2) = 1
NULLIF (expr_1, expr_2) Daca expr_1 = expr_2 atunci
funcia returneaz NULL, altfel
NULLIF (1,1) = NULL
returneaz expresia expr_1.
Echivalent cu
CASE WHEN expr1 = expr2 THEN
NULL ELSE expr1 END
Returneaz prima expresie NOT
COALESCE (expr_1,
COALESCE (NULL, NULL,
NULL din lista de argumente.
expr_2, ... , expr_n)
1, 2, NULL) = 1
ntorc ID-ul, respectiv username-ul SELECT USER
UID, USER
utilizatorului ORACLE curent
FROM dual;
ntoarce numrul de octei ai unei SELECT VSIZE(salary)
VSIZE(expr)
expresii de tip DATE, NUMBER FROM employees
sau VARCHAR2
WHERE employee_id=200;
NVL(expr_1, expr_2)

Utilizarea funciei DECODE este echivalent cu utilizarea clauzei CASE (ntr-o comand
SQL). O form a acestei clause este:
n funcie de valoarea expresiei expr returneaz
CASE expr
valoare_i corespunztoare primei clauze WHEN ..
WHEN expr_1 THEN
THEN pentru care expr = expresie_i; dac nu
valoare_1
corespunde cu nici o clauz WHEN atunci returneaz
[WHEN expr_2 THEN
valoarea din ELSE. Nu se poate specifica NULL pentru
valoare_2
toate valorile de returnat. Toate valorile trebuie s aib
...
acelai tip de date.
WHEN expr_n THEN
valoare_n ]
[ELSE valoare]
END
2. Funciile multiple-row (agregat) pot fi utilizate pentru a returna informaia
corespunztoare fiecruia dinte grupurile obinute n urma divizrii liniilor tabelului cu ajutorul
clauzei GROUP BY. Ele pot aprea n clauzele SELECT, ORDER BY i HAVING. Server-ul
Oracle aplic aceste funcii fiecrui grup de linii i returneaz un singur rezultat pentru fiecare
mulime.
Dintre funciile grup definite n sistemul Oracle, se pot enumera: AVG, SUM, MAX,
MIN, COUNT, STDDEV, VARIANCE etc. Tipurile de date ale argumentelor funciilor grup pot
fi CHAR, VARCHAR2, NUMBER sau DATE. Funciile AVG, SUM, STDDEV i VARIANCE
opereaz numai asupra valorilor numerice. Funciile MAX i MIN pot opera asupra valorilor
numerice, caracter sau dat calendaristic.
Toate funciile grup, cu excepia lui COUNT(*), ignor valorile null. COUNT(expresie)
returneaz numrul de linii pentru care expresia dat nu are valoarea null. Funcia COUNT

6
returneaz un numr mai mare sau egal cu zero i nu ntoarce niciodat valoarea null.
Cnd este utilizat clauza GROUP BY, server-ul sorteaz implicit mulimea rezultat n
ordinea cresctoare a valorilor coloanelor dup care se realizeaz gruparea.

II. [Join]
Join-ul este operaia de regsire a datelor din dou sau mai multe tabele, pe baza
valorilor comune ale unor coloane. De obicei, aceste coloane reprezint cheia primar,
respectiv cheia extern a tabelelor.
Condiia de join se scrie n clauza WHERE a instruciunii SELECT. ntr-o instruciune
SELECT care unete tabele prin operaia de join, se recomand ca numele coloanelor s fie
precedate de numele sau alias-urile tabelelor pentru claritate i pentru mbuntirea timpului
de acces la baza de date. Dac acelai nume de coloan apare n mai mult de dou tabele,
atunci numele coloanei se prefixeaz obligatoriu cu numele sau alias-ul tabelului
corespunztor. Pentru a realiza un join ntre n tabele, va fi nevoie de cel puin n 1 condiii
de join.
Inner join (equijoin, join simplu) corespunde situaiei n care valorile de pe
coloanele ce apar n condiia de join trebuie s fie egale.
Operaia va fi reluat i completat n cadrul laboratorului 3.

III. [Exerciii]
[Funcii pe iruri de caractere]
1. Scriei o cerere care are urmtorul rezultat pentru fiecare angajat:
<prenume angajat> <nume angajat> castiga <salariu> lunar dar doreste <salariu de 3 ori
mai mare>. Etichetati coloana Salariu ideal. Pentru concatenare, utilizai att funcia
CONCAT ct i operatorul ||.
2. Scriei o cerere prin care s se afieze prenumele salariatului cu prima litera majuscul i
toate celelalte litere mici, numele acestuia cu majuscule i lungimea numelui, pentru
angajaii al cror nume ncepe cu J sau M sau care au a treia liter din nume A. Rezultatul
va fi ordonat descresctor dup lungimea numelui. Se vor eticheta coloanele
corespunztor. Se cer 2 soluii (cu operatorul LIKE i funcia SUBSTR).
3. S se afieze pentru angajaii cu prenumele Steven, codul, numele i codul
departamentului n care lucreaz. Cutarea trebuie s nu fie case-sensitive, iar
eventualele blank-uri care preced sau urmeaz numelui trebuie ignorate.
4. S se afieze pentru toi angajaii al cror nume se termin cu litera 'e', codul, numele,
lungimea numelui i poziia din nume n care apare prima data litera 'a'. Utilizai alias-uri
corespunztoare pentru coloane.
[Funcii aritmetice]
5. S se afieze detalii despre salariaii care au lucrat un numr ntreg de sptmni pn la
data curent.
6. S se afieze codul salariatului, numele, salariul, salariul mrit cu 15%, exprimat cu dou
zecimale i numrul de sute al salariului nou rotunjit la 2 zecimale. Etichetai ultimele dou
coloane Salariu nou, respectiv Numar sute. Se vor lua n considerare salariaii al cror
salariu nu este divizibil cu 1000.

7
7. S se listeze numele i data angajrii salariailor care ctig comision. S se eticheteze
coloanele Nume angajat, Data angajarii. Pentru a nu obine alias-ul datei angajrii
trunchiat, utilizai funcia RPAD.

[Funcii i operaii cu date calendaristice]


8. S se afieze data (numele lunii, ziua, anul, ora, minutul si secunda) de peste 30 zile.
9. S se afieze numrul de zile rmase pn la sfritul anului.
10. a) S se afieze data de peste 12 ore.
b) S se afieze data de peste 5 minute.
11. S se afieze numele i prenumele angajatului (ntr-o singur coloan), data angajrii i
data negocierii salariului, care este prima zi de Luni dup 6 luni de serviciu. Etichetai
aceast coloan Negociere.
12. Pentru fiecare angajat s se afieze numele i numrul de luni de la data angajrii.
Etichetai coloana Luni lucrate. S se ordoneze rezultatul dup numrul de luni lucrate.
Se va rotunji numrul de luni la cel mai apropiat numr ntreg.
13. S se afieze numele, data angajrii i ziua sptmnii n care a nceput lucrul fiecare
salariat. Etichetai coloana Zi. Ordonai rezultatul dup ziua sptmnii, ncepnd cu
Luni.
[Funcii diverse]
14. S se afieze numele angajailor i comisionul. Dac un angajat nu ctig comision, s
se scrie Fara comision. Etichetai coloana Comision.
15. S se listeze numele, salariul i comisionul tuturor angajailor al cror venit lunar
depete 10000$.
[Instruciunea CASE, comanda DECODE]
16. S se afieze numele, codul job-ului, salariul i o coloan care s arate salariul dup
mrire. Se presupune c pentru IT_PROG are loc o mrire de 20%, pentru SA_REP
creterea este de 25%, iar pentru SA_MAN are loc o mrire de 35%. Pentru ceilali
angajai nu se acord mrire. S se denumeasc coloana "Salariu renegociat".

[Join]
17. S se afieze numele salariatului, codul i numele departamentului pentru toi angajaii.
Obs: Numele sau alias-urile tabelelor sunt obligatorii n dreptul coloanelor care au acelai
nume n mai multe tabele. Altfel, nu sunt necesare dar este recomandat utilizarea lor pentru
o mai bun claritate a cererii.
18. S se listeze titlurile job-urile care exist n departamentul 30.
19. S se afieze numele angajatului, numele departamentului i locatia pentru toi angajaii
care ctig comision.

8
20. S se afieze numele salariatului i numele departamentului pentru toi salariaii care au
litera A inclus n nume.
21. S se afieze numele, job-ul, codul i numele departamentului pentru toi angajaii care
lucreaz n Oxford.
22. S se afieze codul angajatului i numele acestuia, mpreun cu numele i codul efului
su direct. Se vor eticheta coloanele Ang#, Angajat, Mgr#, Manager.
23. S se modifice cererea precedenta pentru a afia toi salariaii, inclusiv cei care nu au ef.
24. Creai o cerere care s afieze numele angajatului, codul departamentului i toi salariaii
care lucreaz n acelai departament cu el. Se vor eticheta coloanele corespunztor.
25. S se listeze structura tabelului JOBS. Creai o cerere prin care s se afieze numele,
codul job-ului, titlul job-ului, numele departamentului i salariul angajailor.
26. S se afieze numele i data angajrii pentru salariaii care au fost angajai dup Gates.
27. S se afieze numele salariatului i data angajrii mpreun cu numele i data angajrii
efului direct pentru salariaii care au fost angajai naintea efilor lor. Se vor eticheta
coloanele Angajat, Data_ang, Manager si Data_mgr.