Funcții SQL

Excepție

Funcțiile care nu urmează ultima regulă sunt CONCAT, NVL, REPLACE.

Pot fi clasificate în următoarele categorii:

Funcții single-row

Returnează câte o singură linie rezultat pentru fiecare linie a tabelului sau vizualizării interogate.

Ele pot apărea în:

Tip

Pentru a testa funcțiile, cea mai ușoară metodă este:

SELECT functie(...) FROM DUAL;

Funcții de conversie

Funcție Descriere Exemplu
TO_CHAR convertește/formatează un număr/dată calendaristică în șir de caractere TO_CHAR(7) = '7'

TO_CHAR(SYSDATE, 'DD-MM-YYYY') = '03-03-2025'
TO_DATE convertește număr/șir de caractere la dată calendaristică TO_DATE('22-04-2024','DD-MM-YYYY')
TO_NUMBER convertește șir de caractere la număr TO_NUMBER('-23.799', 99.999) = -23.799
Observație

Există două tipuri conversie:

Conversii implicite

Funcții pentru prelucrarea caracterelor

Vezi exerciții.

Funcție Descriere Exemplu
LENGTH(STR) lungimea unui string LENGTH('Informatica') = 11
SUBSTR(str, start [,n]) subșirul unui string care începe la poziția start și are lungime n (opțional). n neprecizat -> până la final SUBSTR('Informatica', 1, 4) = 'Info'
LTRIM(str [,chars]) șterge din stânga unui string orice caracter care apare în chars. Implicit, se șterg spațiile libere. LTRIM(' ab') = 'ab'

LTRIM('aabea', 'ab') = 'ea'
RTRIM(str [,chars]) la fel, dar pe dreapta -
TRIM(TRAILING\LEADING\BOTH chars FROM expresie) elimină caracterele chars de la început/final/ambele dintr-un șir. TRIM(BOTH 'a' FROM 'abXa') = 'bX')
LPAD(str, length [, chars] adaugă chars la stânga șirului până când lungimea noului șir devine lenght LPAD('info', 6) = ' info'
RPAD(str, length [, chars] la fel, pe dreapta -
REPLACE(str1, str2 [, str3]) întoarce str1 cu toate aparițiile lui str2 înlocuite cu str3. (Implicit se șterg) REPLACE('b$bb$$', '$', 'a') = 'babbaa')
UPPER(str) transformă toate literele în majuscule UPPER('aBna') = 'ABNA'
LOWER(str) transformă toate literele în minuscule -
INITCAP(str) prima litera majusculă, următoarele minuscule INITCAP('aiE') = 'Aie'
INSTR(str, substr [, start [, n]]) caută într-un string, de la start a n-a apariție a unui substring. INSTR('abcab', 'ab', 1, 2) = '4'
ASCII(char) codul ASCII al primului caracter al unui șir. ASCII('abc') = ASCII('a') = 97
CHR(n) caracterul corespunzător codului ASCII specificat. CHR(97) = 'a'
CONCAT(str1, str2) concatenează două șiruri de caractere CONCAT('ab', 'cd') = 'abcd'
TRANSLATE(str, src, dest) fiecare caracter care apare în string-urile str și src este transformat în caracterul corespunzător din dest TRANSLATE('$a$aa', '$', 'b') = 'babaa'

TRANSLATE('$a$aa', '$a', 'bc') = 'bcbcc'

Funcții aritmetice

Vezi exerciții.

Funcția Descriere
ABS modulul unui numar
CEIL partea întreagă + 1
FLOOR partea întreagă
ROUND(n [, decimals]) rotunjire cu n zecimale
TRUNC(n [, decimals]) trunchiere cu n zecimale
EXP ridicarea la putere a lui e
LN logaritm natural
LOG(base, n) logaritm în baza base,
MOD(n1, n2) restul împărțirii lui n1 la n2
POWER(n, pow) npow
SIGN semnul unui număr
COS cosinus
COSH cosinus hiperbolic
SIN sinus
SINH sinus hiperbolic
SQRT n
TAN tangentă
TANH tangentă hiperbolică
LEAST(n1, ... , nk) cel mai mic număr dintr-o listă
GREATEST(n1, ..., nk) cel mai mare număr dintr-o listă

Funcții pentru prelucrarea datelor calendaristice

Vezi exerciții.

Funcție Descriere Exemplu
SYSDATE întoarce data și timpul curent ex. 13
ADD_MONTHS(date, nr_months) întoarce data care este după nr_months de la data date. ADD_MONTHS('06-MAR-2025', 3) = '06-JUN-2025'
NEXT_DAY(date, day) întoarce următoarea dată după date în care ziua săptămânii este cea modificată prin șirul day NEXT_DAY('03-JUN-2025', 'Monday') = '09-JUN-2025'
LAST_DAY(date) data corespunzătoare ultimei zile a lunii din care date face parte LAST_DAY('03-JUN-2025') = 2025-06-30
MONTHS_BETWEEN(date1, date2) numărul de luni dintre două date MONTHS_BETWEEN('10-FEB-2020', '31-MAR-2005') = -36.90322
TRUNC(date) data, dar cu timpul setat la 12:00 AM. -
ROUND(expr_date) dacă este o dată înainte de miezul zilei, se întoarce ziua cu timpul setat la 12 AM, dacă nu, următoarea zi cu timpul setat la 12 AM. -
LEAST(date1, ... , datek) prima dată în ordine cronologică -
GREATEST(date1, ... , datek) ultima dată în ordine cronologică -

Operațiile pe date calendaristice

Funcții diverse

Vezi exerciții.

Funcție Descriere Exemplu
DECODE(value, if1, then1, if2, then2, ... ifN, thenN, else) returnează elseI dacă valoarea este idI. Dacă nu este egală cu niciun if, returnează else DECODE('a', 'a', 'b', 'c') = 'b'

DECODE('b', 'a', 'b', 'c') = 'c'
NVL(e1, e2) dacă e1 e NULL, întoarce e2. Dacă nu, întoarce e1

!! Cele două tipuri trebuie să fie valide/să poată fi convertite
NVL(NULL, 1) = 1

NVL(1, 2) = 2

NVL('a', 1) = a

NVL(1, 'a') nu merge!
NVL2(e1, e2, e2) dacă e1 este NULL, întoarce e2, altfel întoarce e3 NVL(1, 2, 3) = 2

NVL(NULL, 2, 3) = 3
NULLIF(e1, e2) dacă e1 = e2 întoarce NULL, altfel întoarce e1 NULLIF(1,1) = NULL
COALESCE(e1, ... , en) returnează prima expresie NOT NULL din listă COALESCE(NULL, NULL, 1, 2) = 1
UID, USER întorc id-ul, respectiv username-ul utilizatorului Oracle curent SELECT USER FROM DUAL;
VSIZE(expr) întoarce numărul de bytes ai unei expresii de tipul NUMBER, VARCHAR2, DATE. SELECT VSIZE(SALARY) FROM EMPLOYEES WHERE EMPLOYEE_ID = 20;
Case

Utilizarea DECODE este echivalentă cu utilizarea clauzei CASE

Case:

CASE expr
WHEN e1 THEN val1
[WHEN e2 THEN val2]
...
[ELSE val]
END

Funcțiile multiple-row

Sunt funcțiile care calculează o valoare pe baza mai multor rânduri dintr-un tabel.

Exemple:

Tipuri de date acceptate:

Notă:

Toate funcțiile grup, cu excepția lui COUNT(*), ignoră valorile null.

Când este utilizată clauza GROUP BY, server-ul sortează implicit mulțimea rezultată în
ordinea crescătoare a valorilor coloanelor după care se realizează gruparea.

Exerciții

Exerciții cu funcții pe șiruri de caractere

Vezi teorie.

Exercițiul 1

Scrieți o cerere care are următorul rezultat pentru fiecare angajat:
<prenume angajat> <nume angajat> câștigă <salariu> lunar dar dorește <salariu de 3 ori mai mare>. Etichetați coloana “Salariu ideal”. Pentru concatenare, utilizați atât funcția
CONCAT cât ți operatorul “||”.

Soluție

SELECT CONCAT(LAST_NAME || ' ', FIRST_NAME) || ' castiga ' ||
       SALARY || ' dar doreste ' || (SALARY * 3) "Salariu ideal"
FROM EMPLOYEES;

Exercițiul 2

Scrieți o cerere prin care să se afișeze prenumele salariatului cu prima litera majusculă
și toate celelalte litere minuscule, numele acestuia cu majuscule și lungimea
numelui, pentru angajații al căror nume începe cu J sau M sau care au a treia literă din
nume A. Rezultatul va fi ordonat descrescător după lungimea numelui. Se vor eticheta
coloanele corespunzător. Se cer 2 soluţii (cu operatorul LIKE și funcția SUBSTR).

Soluție cu LIKE

SELECT INITCAP(FIRST_NAME),
       UPPER(LAST_NAME),
       LENGTH(LAST_NAME)
FROM EMPLOYEES
WHERE UPPER(LAST_NAME) LIKE 'J%' OR
      UPPER(LAST_NAME) LIKE 'M%' OR
      UPPER(LAST_NAME) LIKE '__A%'
ORDER BY LENGTH(LAST_NAME);

Soluție cu SUBSTR

SELECT INITCAP(FIRST_NAME),
       UPPER(LAST_NAME),
       LENGTH(LAST_NAME)
FROM EMPLOYEES
WHERE SUBSTR(UPPER(LAST_NAME), 1, 1) = 'M' OR
      SUBSTR(UPPER(LAST_NAME), 1, 1) = 'J' OR
      SUBSTR(UPPER(LAST_NAME), 3, 1) = 'A'
ORDER BY LENGTH(LAST_NAME);

Exercițiul 3

Să se afișeze, pentru angajații cu prenumele „Steven”, codul și numele acestora, precum
și codul departamentului în care lucrează. Căutarea trebuie să nu fie case-sensitive, iar
eventualele blank-uri care preced sau urmează numelui trebuie ignorate.

Soluție

SELECT EMPLOYEE_ID, LAST_NAME, DEPARTMENT_ID
FROM EMPLOYEES
WHERE INITCAP(TRIM(BOTH FROM FIRST_NAME)) = 'Steven';

Exercițiul 4

Să se afișeze pentru toți angajații al căror nume se termină cu litera 'e', codul, numele,
lungimea numelui și poziția din nume în care apare prima data litera 'A'. Utilizați alias-uri
corespunzătoare pentru coloane.

Soluție

SELECT EMPLOYEE_ID, LAST_NAME,
       LENGTH(LAST_NAME) "Lungimea numelui",
       INSTR(UPPER(LAST_NAME), 'A', 1, 1) "Prima aparitie 'A'"
FROM EMPLOYEES
WHERE SUBSTR(UPPER(LAST_NAME), -1) = 'E';

Exerciții cu funcții aritmetice

Vezi teoria.

Exercițiul 5

Să se afișeze detalii despre salariații care au lucrat un număr întreg de săptămâni până
la data curentă.

SELECT *
FROM EMPLOYEES
WHERE (SYSDATE - HIRE_DATE) / 7  = ROUND((SYSDATE - HIRE_DATE)/7);

Exercițiul 6

Să se afișeze codul salariatului, numele, salariul, salariul mărit cu 15%, exprimat cu
două zecimale și numărul de sute al salariului nou rotunjit la 2 zecimale. Etichetați
ultimele două coloane “Salariu nou”, respectiv “Numar sute”. Se vor lua în considerare
salariații al căror salariu nu este divizibil cu 1000.

SELECT EMPLOYEE_ID, LAST_NAME, SALARY,
       ROUND(SALARY * 1.15, 2) "Salariu Nou",
       ROUND((SALARY * 1.15)/100, 2) "Numar sute"
FROM EMPLOYEES
WHERE MOD(SALARY, 1000) != 0;

Exercițiul 7

Să se listeze numele și data angajării salariaților care câștigă comision. Să se
eticheteze coloanele „Nume angajat”, „Data angajarii”. Utilizați funcția RPAD pentru a
determina ca data angajării să aibă lungimea de 20 de caractere.

SELECT LAST_NAME "Nume Angajat",
       RPAD(HIRE_DATE, 20) "Data Angajarii"
FROM EMPLOYEES
WHERE COMMISSION_PCT IS NOT NULL;

Exerciții cu funcții pe date calendaristice

Vezi teorie.

Exercițiul 8

Să se afișeze data (numele lunii, ziua, anul, ora, minutul și secunda) de peste 30 zile.

Soluție

SELECT TO_CHAR(SYSDATE + 30, 'Month DD, YYYY HH24:MI:SS') "Data viitoare"
FROM DUAL;

Exercițiul 9

Să se afișeze numărul de zile rămase până la sfârșitul anului.

Soluție

SELECT TO_DATE('31-12-2025', 'DD-MM-YYYY') - SYSDATE
FROM DUAL;

Exercițiul 10

a) Să se afișeze data de peste 12 ore.

Soluție

SELECT TO_CHAR(SYSDATE + 1/2, 'DD-MM-YYYY')
FROM DUAL;

b) Să se afișeze data de peste 5 minute

Soluție

SELECT TO_CHAR(SYSDATE + 5/(24*60), 'DD/MM HH24:MI:SS')
FROM DUAL;

Pentru că

5 min1 zi=5 min24 (h)60 min

Exercițiul 11

Să se afișeze numele și prenumele angajatului (într-o singură coloană), data angajării și
data negocierii salariului, care este prima zi de Luni după 6 luni de serviciu. Etichetați
această coloană “Negociere”.

Soluție

SELECT LAST_NAME || ' ' || FIRST_NAME "Nume Complet",
       HIRE_DATE,
       NEXT_DAY(ADD_MONTHS(HIRE_DATE, 6), 'Monday') "Data Negocierii Salariului"
FROM EMPLOYEES;

Exercițiul 12

Pentru fiecare angajat să se afișeze numele și numărul de luni de la data angajării.
Etichetați coloana “Luni lucrate”. Să se ordoneze rezultatul după numărul de luni lucrate.
Se va rotunji numărul de luni la cel mai apropiat număr întreg.

Soluție

SELECT LAST_NAME,
       ROUND(MONTHS_BETWEEN(SYSDATE, HIRE_DATE)) "Luni lucrate"
FROM EMPLOYEES
ORDER BY "Luni lucrate";

Alte moduri de a ordona:

ORDER BY ROUND(MONTHS_BETWEEN(SYSDATE, HIRE_DATE));
ORDER BY 2; -- a doua coloana

Exerciții cu funcții diverse

Vezi teoria.

Exercițiul 13

Să se afișeze numele angajaților și comisionul. Dacă un angajat nu câștigă comision, să
se scrie “Fara comision”. Etichetați coloana “Comision”

SELECT LAST_NAME,
       NVL(TO_CHAR(COMMISSION_PCT), 'Nu are comision') "Comision"
FROM EMPLOYEES;

Exercițiul 14

Să se listeze numele, salariul și comisionul tuturor angajaților al căror venit lunar
(salariu + valoare comision) depășește 10 000.

SELECT LAST_NAME, SALARY, COMMISSION_PCT
FROM EMPLOYEES
WHERE SALARY * (1 + NVL(COMMISSION_PCT, 0)) > 10000;

Pentru că pot exista salarii > 10000, dar comisionul să nu existe (i.e., e NULL).

Dar 1 + NULL -> NULL, și Salary * NULL -> NULL.

Deci trebuie NVL ca să seteze valoarea comisionului la 0 atunci când e NULL.

Exercițiul 15

Să se afișeze numele, codul funcției, salariul și o coloana care să arate salariul după
mărire. Se știe că pentru IT_PROG are loc o mărire de 10%, pentru ST_CLERK 15%, iar
pentru SA_REP o mărire de 20%. Pentru ceilalți angajați nu se acordă mărire. Să se
denumească coloana "Salariu renegociat".

Soluție

Cu DECODE:

SELECT LAST_NAME, JOB_ID, SALARY,
       DECODE(JOB_ID,
           'IT_PROG', SALARY * 1.1,
           'ST_CLERK', SALARY * 1.15,
           'SA_REP', SALARY * 1.2,
            SALARY) "Salariu renegociat"
FROM EMPLOYEES;

Cu CASE:

SELECT LAST_NAME, JOB_ID, SALARY,
       CASE WHEN JOB_ID = 'IT_PROG' THEN SALARY * 1.1
            WHEN JOB_ID = 'ST_CLERK' THEN SALARY * 1.15
            WHEN JOB_ID = 'SA_REP' THEN SALARY * 1.2
            ELSE SALARY
        END "Salariu renegociat"
FROM EMPLOYEES;