curs sinteza sql

166
UNIVERSITATEA SPIRU HARET FACULTATEA DE MATEMATICĂ - INFORMATICĂ CURS: Baze de Date TIP CURS : Obligatoriu la Secţia de matematică Informatică, Anul III, Semestrul I, la toate formele de învăţământ DURATA: Semestrul I , 2 curs, 2 laborator Titular: Lector Dr. FLORENTINA Rodica Niculescu E-MAIL: [email protected] I. CONŢINUTUL TEMATIC AL DISCIPLINEI Notiuni introductive în domeniul bazelor de date (entitate, relatie, atribut, limbaje pentru baze de date, componenete şi arhitectura unui sistem de gestiune a bazelor de date (SGBD), evoluţia SGBD-urilor) Proiectarea bazelor de date simple Proiectarea bazelor de date relaţionale (modelarea Entitate-Relaţie, diagrama E/R, modelul relational, regulile lui Codd, caracteristicile modelului relational, normalizare, forme normale, dependenţe funcţionale) Limbaje de manipulare a datelor relaţionale Limbajul SQL MODUL DE STABILIRE A NOTEI FINALE: Nota de la testul grilă (pe calculator) mărită cu două puncte pentru studenţii care au fost prezenţ i la orele de laborator şi care au rezolvat temele de laborator. SINTEZE ASUPRA PROGRAMEI ANALITICE Materialul este structurat în 2 părţi, astfel: Partea I. Concepte ale bazelor de date relaţionale Partea a_II_a. SQL Partea I. Concepte ale bazelor de date relaţionale În această parte se face o prezentare generală a conceptelor bazelor de date relaţionale. O bază de date este o colecţie de informaţii interrelaţionate gestionate ca o singură unitate. A ceastă definiţie este foarte largă, deoarece există mari diferenţe între concepţiile diferiţilor producători care pun la dispoziţie sisteme de baze de date. De exemplu, Oracle Corporation defineşte o bază de date ca fiind o colecţie de fişiere fizice gestionate de o singură instanţă (copie) a produsului software pentru baze de date, în timp ce Microsoft defineşte o bază de date SQL Server ca fiind o colecţie de date şi alte obiecte.

Upload: osadrian

Post on 27-Jun-2015

722 views

Category:

Documents


9 download

TRANSCRIPT

Page 1: Curs Sinteza SQL

UNIVERSITATEA SPIRU HARET FACULTATEA DE MATEMATICĂ - INFORMATICĂ

CURS: Baze de Date TIP CURS : Obligatoriu la Secţia de matematică Informatică,

Anul III, Semestrul I, la toate formele de

învăţământ

DURATA: Semestrul I , 2 curs, 2 laborator

Titular: Lector Dr. FLORENTINA Rodica Niculescu

E-MAIL: [email protected]

I. CONŢINUTUL TEMATIC AL DISCIPLINEI

Notiuni introductive în domeniul bazelor de date (entitate, relatie, atribut, limbaje

pentru baze de date, componenete şi arhitectura unui sistem de gestiune a bazelor de date

(SGBD), evoluţia SGBD-urilor) Proiectarea bazelor de date simple Proiectarea bazelor de date relaţionale (modelarea

Entitate-Relaţie, diagrama E/R, modelul relational, regulile lui Codd, caracteristicile

modelului relational, normalizare, forme normale, dependenţe funcţionale) Limbaje de manipulare a datelor relaţionale

Limbajul SQL

MODUL DE STABILIRE A NOTEI FINALE:

Nota de la testul grilă (pe calculator) mărită cu două puncte pentru studenţii

care au fost prezenţi la orele de laborator şi care au rezolvat temele de laborator.

SINTEZE ASUPRA PROGRAMEI ANALITICE

Materialul este structurat în 2 părţi, astfel:

Partea I. Concepte ale bazelor de date relaţionale

Partea a_II_a. SQL

Partea I. Concepte ale bazelor de date relaţionale

În această parte se face o prezentare generală a conceptelor bazelor de date

relaţionale.

O bază de date este o colecţie de informaţii interrelaţionate gestionate ca o

singură unitate. A ceastă definiţie este foarte largă, deoarece există mari diferenţe

între concepţiile diferiţilor producători care pun la dispoziţie sisteme de baze de date.

De exemplu, Oracle Corporation defineşte o bază de date ca fiind o colecţie de

fişiere fizice gestionate de o singură instanţă (copie) a produsului software pentru

baze de date, în timp ce Microsoft defineşte o bază de date SQL Server ca fiind o

colecţie de date şi alte obiecte.

Page 2: Curs Sinteza SQL

Un obiect al bazei de date este o structură de date denumită, stocată în bază de

date, cum ar fi un tabel, o vizualizare sau un index.

Există mari diferenţe între implementările furnizorilor de baze de date. În

majoritatea sistemelor de baze de date, datele sunt stocate în mai multe fişiere fizice,

dar în Microsoft Access toate obiectele bazei de date, împreună cu datele care aparţin

unei baze de date sunt stocate într-un singur fişier fizic.(Un fişier este o colecţie de

înregistrări înrudite stocate ca o singură untiate de sistemul de operare al

calculatorului.) Totuşi, unul dintre principalele avantaje ale bazelor de date relaţionale

este faptul că detaliile de implementare fizică sunt separate de definiţiile logice ale

obiectelor bazei de date, astfel încât majoritatea utilizatorilor bazei de date nu au

nevoie să ştie unde (şi cum) sunt stocate obiectele bazei de date în sistemul de fişiere

al calculatorului. De fapt , pe măsură ce veţi învăţa limbajul SQL , veţi vedea că nu

este nevoie să specificaţi numele unui fişier fizic într-o instrucţiune SQL decât atunci

când definiţi sau modificaţi chiar obiectele bazei de date.

Sistem de gestionare a bazei de date (DBMS)

Un sistem de gestionare a bazei de date (DBMS database management system)

este un produs software furnizat de producătorul bazei de date. Produse software

precum Microsoft Access, Microsoft SQL Server, Oracle Database,Sybase,

DB2,INGRES, MySQL şi Postgre SQL fac parte din categoria DBMS sau, mai corect,

DBMS relaţionale (RDBMS).

RDBMS-urile sunt cunoscute şi sub numele de SGBD-uri. Ambele prescurtări

vor fi folosite în acestă expunere.

Bazele de date relaţionale sunt definite şi prezentate în secţiunea următoare a

acestu capitol.

Sistemul DBMS pune la dispoziţie toate serviciile de bază necesare pentru

organizarea şi întreţinerea bazei de date, inclusiv următoarele:

Transferarea datelor în şi din fişierele fizice de date, în funcţie de cerinţe.

Gestionarea accesului concurenţial la date al mai multor utilizatori , inclusiv

prevenirea conflictelor care ar putea fi cauzate de actualizările simultane.

Gestionarea tranzacţiilor, astfel încât toate modificările făcute asupra bazei de

date printr-o tranzacţie să fie executate ca o singură unitate.Cu alte cuvinte, dacă

tranzacţia reuşeşte, toate modificările efectuate de tranzacţie sunt înregistrate în bază

de date; dacă tranzacţia eşuează, nici una dintre modificări nu este înregistrată în bază

de date.Totuşi, reţineţi ca unele sisteme RDBMS nu asigură suportul pentru tranzacţii.

Acceptă un limbaj de interogare, care reprezintă sistemul de comenzi folosit

de utilizator pentru a obţine date din bază de date.SQL este principalul limbaj folosit

pentru sistemele DBMS relaţionale şi subiectul principal al aceste cărţi.

Funcţii pentru salvarea bazei de date şi pentru refacerea bazei de date în urma

erorilor.

Mecanisme de securitate pentru împiedicarea accesului neautorizat la date şi

modificarea acestora.

Bază de date relaţională

O bază de date relaţională este o bază de date care respectă modelul relaţional,

dezvoltat de Dr.E.F.Codd. Modelul relaţional prezintă datele sub forma familiarelor

Page 3: Curs Sinteza SQL

tabele bidimensionale, similar cu o foaie de calcul tabelar. Spre deosebire de o foaie

de calcul tabelar, nu este obligatoriu ca datele să fie stocate într-o formă tabelară, iar

modelul permite şi combinarea tabelelor (crearea uniunilor (joining), în terminologia

relaţională) pentru formarea vizualizarilor, care sunt prezentate tot ca tabele

bidimensionale. Flexibilitatea extraordinară a bazelor de date relaţionale este dată de

posibilitatea de a folosi tabelele independent sau în combinaţii, fără nici o ierarhie sau

secvenţa predefinita în care trebuie să se facă accesul la date.

Un model este o reprezentare a obiectelor şi evenimentelor lumii reale şi a

asocierilor dintre ele. De fapt, el reprezintă o abstracţie asupra aspectelor

semnificative ale unei „întreprinderi―, ale unui sistem real, ignorând proprietăţile

accidentale. Modelul este cel pe care utilizatorii trebuie să-l cunoască; implementarea

unui model este cea pe care utilizatorii nu este necesar să o cunoască. Diferenţa dintre

model şi implementare este, de fapt, un caz special şi important al deosebirii uzuale

dintre logic şi fizic.

Modelele se impun prin sintaxa şi prin semantica lor şi, din acest punct de

vedere, există trei tipuri fundamentale de modele:

modele care descriu aspectele statice ale procesului modelat;

modele care descriu aspectele dinamice ale procesului modelat;

modele care descriu aspectele funcţionale ale procesului modelat.

Un model de date reprezintă o colecţie integrată de concepte necesare

descrierii:

datelor,

relaţiilor dintre ele,

constrângerilor existente asupra datelor sistemului real analizat.

Modelarea unei baze de date permite trecerea de la percepţia unor fapte din

lumea reală la reprezentarea lor prin date. Modelul de date trebuie să reflecte fidel

fenomene ale lumii reale, să urmărească evoluţia acestei lumi şi comunicarea dintre

fenomenele lumii reale.

Modelul trebuie să asigure conceptele de bază care permit proiectantului bazei

de date şi utilizatorilor să comunice, fără ambiguităţi, cunoştinţele lor privind

funcţionarea şi organizarea modelului real analizat. Prin urmare, un model de date

trebuie să reprezinte datele şi să le facă înţelese.

În esenţă, modelul de date are trei componente:

mulţime de reguli conform cărora sunt construite bazele de date (partea

structurală);

mulţime de operaţii permise asupra datelor, care sunt utilizate pentru

reactualizarea sau regăsirea datelor (partea de prelucrare);

mulţime de reguli de integritate, care asigură coerenţa datelor.

Abordarea generală a problemei modelării semantice a datelor se face în

patru etape.

Se identifică o mulţime de concepte semantice care sunt utile în descrierea

lumii reale. Se presupune că lumea reală (modelul real analizat) este

formată din entităţi care au anumite proprietăţi, că fiecare entitate are o

identitate, că există legături, corelaţii între entităţi. Conceptul de corelaţie,

ca şi cel de entitate, este util, în mod intuitiv, la descrierea modelului.

Se caută o mulţime de obiecte formale, simbolice care sunt utilizate pentru

reprezentarea conceptelor semantice anterioare.

Page 4: Curs Sinteza SQL

Se dau reguli de integritate formale şi generale (constrângeri) care să

reflecte restricţiile la care este supus modelul.

Se defineşte o mulţime de operatori formali prin care pot fi prelucrate şi

analizate obiectele formale.

Modelul entitate-relaţie

Una dintre cele mai cunoscute abordări ale modelării semantice (cu siguranţă

una dintre cele mai utilizate) este cea bazată pe modelul entitate-relaţie (E/R).

Acesta a fost introdus de către P.P. Chen în 1976 şi rafinat de atunci în diverse moduri

de către acesta şi de mulţi alţi cercetători, ca un model de date conceptual, pentru a

uşura proiectarea bazelor de date. Pentru reprezentarea grafică a modelului sunt

utilizate diagramele E/R, care sunt modele neformalizate pentru reprezentarea unui

model, unui sistem din lumea reală.

Diagramele E/R constituie o tehnică de reprezentare a structurii logice a bazei

de date, într-o manieră grafică. Aceste diagrame oferă un mijloc simplu şi inteligibil

de comunicare a caracteristicilor importante ale designului unei anumite baze de date.

Diagrama E/R este un model de date conceptual de nivel înalt, independent de

platforma hardware utilizată şi de tipul SGBD-ului. Modelul este constituit din

concepte care descriu structura bazei de date şi tranzacţiile de regăsire sau

reactualzare asociate.

Popularitatea modelului E/R ca modalitate de abordare a proiectării bazelor de

date poate fi atribuită în principal tehnicii de realizare a diagramelor E/R. Această

tehnică, ca şi modelul E/R însuşi, a evoluat de-a lungul timpului datorită noilor

problematici care au apărut în proiectarea bazelor de date.

Baza de date poate fi definită ca o mulţime de date ce modelează un sistem

real. Acest sistem este format din obiecte legate între ele. Modelul E/R împarte

elementele unui sistem real în două categorii: entităţi şi relaţii (legături, asocieri)

între aceste entităţi. Entităţiile şi legăturile au anumite caracteristici, numite atribute.

Nu trebuie confundat conceptul de relaţie, în sensul de asociere, care intervine în

definirea diagramei E/R cu conceptul de relaţie care este specific modelului relaţional.

Entitate

Entitatea este un obiect sau un concept, care este semnificativ pentru modelul real analizat. O entitate poate fi dependentă (slabă), existenţa sa depinzând de altă entitate sau independentă (tare), caz în care ea nu depinde de existenţa altei entităţi.

Entitatea poate fi persoană, loc, concept, activitate etc. Prin urmare, ea poate fi un obiect cu existenţă fizică, reală sau poate fi un obiect cu existenţă conceptuală, abstractă.

Cheia primară este un identificator unic în cadrul entităţii, făcând distincţie

între valori diferite ale acesteia.

Cheia primară:

trebuie să fie unică şi cunoscută la orice moment;

trebuie să fie controlată de administratorul bazei;

trebuie să nu conţină informaţii descriptive, să fie simplă, fără ambiguităţi;

Page 5: Curs Sinteza SQL

să fie stabilă;

să fie familiară utilizatorului.

Observaţii

Entităţile devin tabele în modelele relaţionale.

În general, entităţile se scriu cu litere mari.

Entităţile sunt substantive, dar nu orice substantiv este o entitate. Trebuie ignorate substantivele nerelevante.

Pentru fiecare entitate este obligatoriu să se dea o descriere detaliată.

Nu pot exista, în aceeaşi diagramă, două entităţi cu acelaşi nume, sau o aceeaşi

entitate cu nume diferite.

lucreaza_in conduce

apartine_la

atasat_la

Relaţie

Relaţia (asocierea) este o comunicare între două sau mai multe entităţi. O

valoare a unei relaţii este o comunicare între valorile entităţilor pe care le leagă.

Relaţia exprimă un raport care există între aceste entităţi. Gradul unei relaţii

este dat de numărul de entităţi participante într-o relaţie (de exemplu, relaţie binară,

ternară, cvadruplă, n-ară).

Existenţa unei relaţii este subordonată existenţei entităţilor pe care le leagă.

Între două entităţi pot exista mai multe relaţii.

O relaţie în care aceeaşi entitate participă mai mult decât o dată în diferite

roluri defineşte o relaţie recursivă. Uneori, aceste relaţii sunt numite unare.

Observaţii:

În modelul relaţional, relaţiile devin tabele speciale sau coloane speciale

care referă chei primare.

Relaţiile sunt verbe, dar nu orice verb este o relaţie.

Pentru fiecare relaţie este important să se dea o descriere detaliată.

În aceeaşi diagramă pot exista relaţii diferite cu acelaşi nume. În acest caz,

ele sunt diferenţiate de către entităţile care sunt asociate prin relaţia

respectivă.

Pentru fiecare relaţie trebuie stabilită cardinalitatea (maximă şi minimă)

relaţiei, adică numărul de tupluri ce aparţin relaţiei.

poate (cardinalitate maximă) trebuie (cardinalitate minima)

EXEMPLE:

Câţi salariaţi pot lucra într-un departament? Mulţi!

În câte departamente poate lucra un salariat? In cel mult unul!

DEPARTAMENT

SALARIAT

SARCINA

PROIECT

Page 6: Curs Sinteza SQL

Relaţia SALARIAT_lucreaza_in_DEPARTAMENT are cardinalitatea

maximă many-one (n:1).

Exemplu:

Câţi salariaţi trebuie să conducă un departament? Cel puţin unul!

Câte departamente trebuie să conducă un salariat? Zero!

Relaţia SALARIAT_conduce_DEPARTAMENT are cardinalitatea minimă

one-zero (1:0).

Asupra entităţilor participante într-o relaţie pot fi impuse constrângeri care

trebuie să reflecte restricţiile care există în lumea reală asupra relaţiilor. O clasă de

constrângeri, numite constrângeri de cardinalitate, este definită de numărul de

înregistrări posibile pentru fiecare entitate participantă (raport de cardinalitate). Cel

mai întâlnit tip de relaţii este cel binar, iar în acest caz rapoartele de cardinalitate sunt,

în general, one-to-one (1:1), one-to-many (1:n) sau many-to-many (m:n).

Atribut

Atributul este o proprietate descriptivă a unei entităţi sau a unei relaţii. De exemplu, numele , genul unei film, sunt atribute al entităţii FILM.

Atributele pot fi simple (pretul de închiriere a unui film), compuse (de exemplu, numele filmului), cu valori multiple (de exemplu, limbile în care e tradus un film), derivate (de exemplu, vârsta unei persoane se obţine din data naşterii).

Observaţii

Trebuie făcută distincţia între atribut care uzual devine coloană în modelele relaţionale şi valoarea acestuia, care devine valoare în coloane.

Atributele sunt substantive, dar nu orice substantiv este atribut.

Fiecărui atribut trebuie să i se dea o descriere completă în specificaţiile modelului (exemple, contraexemple, caracteristici).

Pentru fiecare atribut trebuie specificat numele, tipul fizic (integer, float, char etc.), valori posibile, valori implicite, reguli de validare, constrângeri, tipuri compuse.

Diagrama entitate- relaţie

Pentru proiectarea diagramei entitate-relaţie au fost stabilite anumite reguli

entităţile sunt reprezentate prin dreptunghiuri;

relaţiile dintre entităţi sunt reprezentate prin arce neorientate;

atributele care reprezintă chei primare trebuie subliniate sau marcate prin

simbolul „#― sau (pk), plasat la sfârşitul numelui acestor atribute;

cardinalitatea minimă este indicată în paranteze, iar cardinalitatea maximă

se scrie fără paranteze;

nu este necesar să fie specificate, în cadrul diagramei, toate atributele.

1

lucreaza_in

apartine_la

SALARIAT cod_salariat nume prenume

sex

salariu

PROIECT nr_proiect descriere buget_alocat

DEPARTAMENT cod_departament nume nr_cladire

SARCINA nr_proiect nr_sarcina data_inceperii

atasat_la

data_initiala

functia

1

1

11

M

M(0)

1

1(0)

M

1

M

M(0)

M

M(0)

M

Page 7: Curs Sinteza SQL

Diagrama Entitate/relaţie

Cazuri speciale de entităţi, relaţii, atribute şi modul lor de

reprezentare în cadrul diagramei entitate-relaţie.

1. Entitate dependentă – nu poate exista în mod independent (SARCINA

depinde de PROIECT). Cheia primară a unei entităţi dependente include

cheia primară a sursei (nr_proiect) şi cel puţin o descriere a entităţii

(nr_sarcina). Entitatea dependentă se desenează prin dreptunghiuri cu linii mai

subţiri.

2. Moştenirea atributelor. Subentitate (subclasă) – submulţime a unei alte

entităţi, numită superentitate (superclasă) (SALARIAT < –– >

PROGRAMATOR). Subentitatea se desenează prin dreptunghiuri incluse în

superentitate. Există o relaţie între o subentitate şi o superentitate, numită

ISA, care are cardinalitatea maximă 1:1 şi minimă 1:0. Cheile primare,

atributele şi relaţiile unei superentităţi sunt valabile pentru orice subentitate.

Afirmaţia reciprocă este falsă.

3. Într-o diagramă E/R se pot defini relaţii recursive.

4. Relaţie sau atribut? Dacă un atribut al unei entităţi reprezintă cheia primară a

unei alte entităţi, atunci el referă o relaţie (cod_departament în tabelul

SALARIAT).

5. Entitate sau relaţie? Se cercetează cheia primară. Dacă aceasta combină cheile

primare a două entităţi, atunci este vorba de o relaţie. (cheia primară a relaţiei

asociat_la combină cod_salariat cu nr_proiect, prin urmare,

SALARIAT_asociat la_PROIECT va defini o relaţie şi nu o entitate).

Probleme 1.Să se creeze modelul E/R pentru gestiunea activităţilor de împrumut dintr-o

bibliotecă S-a presupus (restrictiv) că într-o zi un cititor nu poate împrumuta, de

mai multe ori, aceeaşi carte. Entităţile şi relaţiile care intervin în acest model sunt următoarele:

1. CARTE (entitate independentă) – orice carte care se găseşte în inventarul

bibliotecii. Cheia primară este atributul codel.

2. CITITOR (entitate independentă) – orice cititor care poate împrumuta

cărţi. Cheia primară este atributul codec.

1

1(0)

conduce

Page 8: Curs Sinteza SQL

3. DOMENIU (entitate independenta) – domeniul căruia îi aparţine o carte.

Cheia primară este atributul coded.

4. IMPRUMUTA – relaţie având cardinalitatea m:m care leagă entităţile

CITITOR şi CARTE.

5. APARTINE – relaţie care leagă atributele CARTE şi DOMENIU. Relaţia

are cardinalitatea maximă m:1, iar cardinalitatea minimă 1:1.

2.Evidenţa şcolilor de şoferi din Romania. Completaţi relaţiile (lucreaza_la,

conduce, sustine, asista, instruieste) dintre entităţi şi specificaţi cardinalitatea!

CIT

ITOR codec#

nume

dep

CAR

TE codel#

titlu

autor

pret

nrex

DOM

ENIU coded#

intdom

imprumuta

apartine

M(1) M(0)

M(0) 1

SCOALA

cod_scoala# CLIENT

cod_client#

INSTRUCTOR

cod_instructor#

MASINA

cod_masina#

EXAMEN

cod_examen#

EXAMINATOR

cod_examinator#

Page 9: Curs Sinteza SQL

3. Campionatele de fotbal ale diferitelor ţări

M(1) sustine M(1) M(1)

2

joaca

M(1)

M(1)

apartine_de

1

M(1)

atasata_la

1

Modelul relaţional

Modelul relaţional a fost conceput şi dezvoltat de E.F. Codd. El este un model

formal de organizare conceptuală a datelor, destinat reprezentării legăturilor dintre

date, bazat pe teoria matematică a relaţiilor. Modelul relaţional este alcătuit numai din

relaţii şi prin urmare, orice interogare asupra bazei de date este tot o relaţie.

Cercetarea în domeniu 3 mari proiecte (System R, INGRES, PRTV)

ECHIPA

Cod_echipa#

Nume

Oras

SPONSOR

Cod_sponsor#

Nume

MECI

Tara#

Nr_etapa#

Cod_meci#

ETAPA

Tara

Nr_etapa

CAMPIONAT

Tara#

Page 10: Curs Sinteza SQL

Calităţi:

este simplu;

riguros din punct de vedere matematic;

nu este orientat spre sistemul de calcul.

Modalităţi pentru definirea unui SGBD relaţional:

prezentarea datelor în tabele supuse anumitor operaţii de tip proiecţie,

selecţie, reuniune, compunere, intersecţie etc.

un sistem de baze de date ce suportă un limbaj de tip SQL – Structured

Query Language;

un sistem de baze de date care respectă principiile modelului relaţional

introdus de E.F. Codd.

Caracteristicile unui model relaţional:

structura relaţională a datelor;

operatorii modelului relaţional;

regulile de integritate care guvernează folosirea cheilor în model.

Aceste trei elemente corespund celor trei componente ale ingineriei software:

informaţie, proces, integritate.

Structura datelor

Definirea noţiunilor de domeniu, relaţie, schemă relaţională, valoare null şi

tabel vizualizare (view).

Conceptele utilizate pentru a descrie formal, uzual sau fizic elementele de bază

ale organizării datelor sunt date în următorul tabel:

Formal Uzual Fizic

relaţie

tuplu

atribut

domeniu

tablou

linie

coloană

tip de dată

fişier

înregistrare

câmp

tip de dată

Reguli de integritate sunt aserţiuni pe care datele conţinute în baza de date trebuie să le satisfacă.

Există trei tipuri de constrângeri structurale (de cheie, de referinţă, de entitate) ce constituie mulţimea minimală de reguli de integritate pe care trebuie să le respecte un SGBD relaţional. Restricţiile de integritate minimale sunt definite în raport cu noţiunea de cheie a unei relaţii.

O mulţime minimală de atribute ale căror valori identifică unic un tuplu într-o relaţie reprezintă o cheie pentru relaţia respectivă.

Fiecare relaţie are cel puţin o cheie. Una dintre cheile candidat va fi aleasă pentru a identifica efectiv tupluri şi ea va primi numele de cheie primară. Cheia primară nu poate fi reactualizată. Atributele care reprezintă cheia primară sunt fie

subliniate, fie urmate de semnul #.

Page 11: Curs Sinteza SQL

O cheie identifică linii şi este diferită de un index care localizează liniile. O

cheie secundară este folosită ca index pentru a accesa tupluri. Un grup de atribute din

cadrul unei relaţii care conţine o cheie a relaţiei poartă numele de supercheie.

Fie schemele relaţionale R1(P1, S1) şi R2(S1, S2), unde P1 este cheie primară

pentru R1, S1 este cheie secundară pentru R1, iar S1 este cheie primară pentru R2. În

acest caz, vom spune că S1 este cheie externă (cheie străină) pentru R1.

Modelul relaţional respectă trei reguli de integritate structurală.

Regula 1 – unicitatea cheii. Cheia primară trebuie să fie unică şi

minimală.

Regula 2 – integritatea entităţii. Atributele cheii primare trebuie să fie

diferite de valoarea null.

Regula 3 – integritatea referirii. O cheie externă trebuie să fie ori null în

întregime, ori să corespundă unei valori a cheii primare asociate.

Transformarea entităţilor

Entităţile independente devin tabele independente. Cheia primară nu

conţine chei externe.

Entităţile dependente devin tabele dependente. Cheia primară a

entităţilor dependente conţine cheia primară a entităţii de care depinde

(cheie externă) plus unul sau mai multe atribute adiţionale.

Subentităţile devin subtabele. Cheia externă se referă la supertabel, iar

cheia primară este această cheie externă (cheia primară a subentităţii

PROGRAMATOR este cod_salariat care este o cheie externă).

Transformarea relaţiilor

Relaţiile 1:1 şi 1:n devin chei externe. Relaţia conduce devine coloană în

tabelul DEPARTAMENT, iar relaţia lucreaza_in devine coloană în tabelul

SALARIAT. Simbolul „ ― indică plasamentul cheii externe, iar simbolul

„ ― exprimă faptul că această cheie externă este conţinută în cheia primară.

Relaţia 1:1 plasează cheia externă în tabelul cu mai puţine linii.

Relaţia m:n devine un tabel special, numit tabel asociativ, care are două

chei externe pentru cele două tabele asociate. Cheia primară este

compunerea acestor două chei externe plus eventuale coloane adiţionale.

Tabelul se desenează punctat.

Relaţiile de tip trei devin tabele asociative. Cheia primară este

compunerea a trei chei externe plus eventuale coloane adiţionale.

Transformarea atributelor

Un atribut singular devine o coloană.

Page 12: Curs Sinteza SQL

Atributele multiple devin tabele dependendente ce conţin cheia primară a

entităţii şi atributul multiplu. Cheia primară este o cheie externă, plus una

sau mai multe coloane adiţionale.

Entităţile devin tabele, iar atributele lor devin coloane în aceste tabele. Ce

devin atributele relaţiilor? Pentru relaţii 1:1 şi 1:n, atributele relaţiilor vor aparţine

tabelului care conţine cheia externă, iar pentru relaţii m:n şi de tipul trei, atributele vor

fi plasate în tabelele asociative.

Schemele relaţionale corespunzătoare acestei diagrame conceptuale sunt

următoarele:

– SALARIAT(cod_salariat#, nume, prenume, sex, job_cod, cod_sot,

forma_plata, nr_depart);

– DEPARTAMENT(cod_departament#, nume, numar_cladire, cod_sal);

– ATASAT_LA(cod_salariat#, nr_proiect#, functia);

– PROIECT(nr_proiect#, descriere, buget_alocat);

– SARCINA(nr_proiect#, nr_sarcina, data_inceperii, stare);

PROIECT

nr_proiect

descriere

buget_alocat

SARCINA

nr_proiect

nr_sarcina

data_inceperii

stare

DEPARTAMENT

cod_departament

nume nr_cladire

cod_salariat

AGENT_TERITORIAL zona

comision

PROGRAMATOR limbaj

nivel

SALARIAT

cod_salariat

salariu

nume

sex

job_cod

conduce lucreaza_in

apartine_la

ATASAT_LA

cod_salariat

nr_proiect

functie

TELFON

cod_salariat

nr_telefon

casatorit

Page 13: Curs Sinteza SQL

– AGENT_TERITORIAL(cod_salariat#, zona, comision);

– PROGRAMATOR(cod_salariat#, limbaj, nivel);

– TELEFON(cod_salariat#, nr_telefon#).

Regulile lui Codd

Caracteristici ale modelului relaţional:

nu există tupluri identice;

ordinea liniilor şi a coloanelor este arbitrară;

articolele unui domeniu sunt omogene;

fiecare coloană defineşte un domeniu distinct şi nu se poate repeta în cadrul

aceleiaşi relaţii;

toate valorile unui domeniu corespunzătoare tuturor cazurilor nu mai pot fi

descompuse în alte valori (sunt atomice).

Avantajele modelului relaţional:

fundamentare matematică riguroasă;

independenţă fizică a datelor;

posibilitatea filtrărilor;

existenţa unor structuri de date simple;

realizarea unei redundanţe minime;

supleţe în comunicarea cu utilizatorul neinformatician.

Ca limite ale modelului relaţional putem menţiona:

rămâne totuşi redundanţă,

ocupă spaţiu,

apar fenomene de inconsistenţă,

nu există mecanisme pentru tratarea optimă a cererilor recursive,

nu lucrează cu obiecte complexe,

nu există mijloace perfecţionate pentru exprimarea constrângerilor de

integritate,

nu realizează gestiunea totala a datelor distribuite,

nu realizează gestiunea cunoştinţelor.

În anul 1985, E.F. Codd a publicat un set de 13 reguli în raport cu care un

sistem de gestiune a bazelor de date poate fi apreciat ca relaţional. Nici un sistem de

gestiune a bazelor de date pus în vânzare pe piaţa comercială nu respectă absolut toate

regulile definite de Codd, dar acest lucru nu împiedică etichetarea acestor sisteme

drept relaţionale.

Nu trebuie apreciat un SGBD ca fiind relaţional sau nu, ci măsura în care

acesta este relaţional, deci numărul regulilor lui Codd pe care le respectă.

Regula 1 – regula gestionării datelor. Un SGBD relaţional trebuie să fie

capabil să gestioneze o bază de date numai prin posibilităţile sale relaţionale.

Page 14: Curs Sinteza SQL

Regula 2 – regula reprezentării informaţiei. Într-o bază de date relaţională,

informaţia este reprezentată la nivel logic sub forma unor tabele ce poartă numele de

relaţii.

Regula 3 – regula accesului garantat la date. Fiecare valoare dintr-o bază de

date relaţională trebuie să poată fi adresată în mod logic printr-o combinaţie formată

din numele relaţiei, valoarea cheii primare şi numele atributului.

Regula 4 – regula reprezentării informaţiei necunoscute. Un sistem relaţional

trebuie să permită utilizatorului definirea unui tip de date numit „null“ pentru

reprezentarea unei informaţii necunoscute la momentul respectiv.

Regula 5 – regula dicţionarelor de date. Asupra descrierii bazelor de date

(informaţii relative la relaţii, vizualizări, indecşi etc.) trebuie să se poată aplica

aceleaşi operaţii ca şi asupra datelor din baza de date.

Regula 6 – regula limbajului de interogare. Trebuie să existe cel puţin un

limbaj pentru prelucrarea bazei de date.

Regula 7 – regula de actualizare a vizualizării. Un SGBD trebuie să poată

determina dacă o vizualizare poate fi actualizată şi să stocheze rezultatul interogării

într-un dicţionar de tipul unui catalog de sistem.

Regula 8 – regula limbajului de nivel înalt. Regulile de prelucrare asupra

unei relaţii luată ca întreg sunt valabile atât pentru operaţiile de regăsire a datelor,

cât şi asupra operaţiilor de inserare, actualizare şi ştergere a datelor.

Regula 9 – regula independenţei fizice a datelor: Programele de aplicaţie şi

activităţile utilizatorilor nu depind de modul de depunere a datelor sau de modul de

acces la date.

Regula 10 – regula independenţei logice a datelor. Programele de aplicaţie

trebuie să fie transparente la modificările de orice tip efectuate asupra datelor.

Regula 11 – regula independenţei datelor din punct de vedere al integrităţii.

Regulile de integritate trebuie să fie definite într-un sublimbaj relaţional, nu în

programul de aplicaţie.

Regula 12 – regula independenţei datelor din punct de vedere al distribuirii.

Distribuirea datelor pe mai multe calculatoare dintr-o reţea de comunicaţii de date,

nu trebuie să afecteze programele de aplicaţie.

Regula 13 – regula versiunii procedurale a unui SGBD. Orice componentă

procedurală a unui SGBD trebuie să respecte aceleaşi restricţii de integritate ca şi

componenta relaţională.

Deoarece regulile lui Codd sunt prea severe pentru a fi respectate de un

SGBD operaţional, s-au formulat criterii minimale de definire a unui sistem de

gestiune relaţional.

Un SGBD este minimal relaţional dacă:

toate datele din cadrul bazei sunt reprezentate prin valori în tabele;

nu există pointeri observabili de către utilizator;

sistemul suportă operatorii relaţionali de proiecţie, selecţie şi compunere

naturală, fără limitări impuse din considerente interne.

Un SGBD este complet relaţional dacă este minimal relaţional şi satisface în

plus condiţiile:

Page 15: Curs Sinteza SQL

sistemul suportă restricţiile de integritate de bază (unicitatea cheii primare,

constrângerile referenţiale, integritatea entităţii).

sistemul suportă toate operaţiile de bază ale algebrei relaţionale.

Exemplu pentru însuşirea formelor normale şi a instrucţiunilor

SQL

Componentelor fundamentale ale bazelor de date relaţionale sunt utilizate

pentru a construi obiectele bazelor de dae pe care le vom folosi .

Instrucţiunile SQL folosite pentru crearea acestor componente ale bazei de

date sunt prezentate în parte.

Tabele Unitatea primară de stocare a datelor într-o bază de date relaţională este

tabelul, care este o structură bidimensională compusă din rânduri şi coloane. Fiecare

tabel reprezintă o entitate, ceea ce înseamnă o persoană, un loc sau un lucru care

trebuie să fie reprezentat în baza de date, cum ar fi un client, un cont bancar sau o

tranzacţie bancară. Fiecare rând al tabelului reprezintă o apariţie a entităţii. Figura 1-1

reprezintă listingul parţial al unui tabel numit FILM(filme).

Tabelul FILM este parte a unei baze de date pentru un magazin de produse

video, folosit ca exemplu în toată aceast curs. Tabelul FILM conţine date care descriu

filmele disponibile în magazinul de produse video. Fiecare rând din tabel reprezintă

un film, iar fiecare coloană reprezintă o caracteristică a filmului respectiv, cum ar fi

titlul filmului sau categoria MPAA(Motion Picture Associationof America care a fost

fondată în 1972 în America ca asociaţie a producătorilor de film pe lângă industria

cinematografică)

FILM_I

D

FILM_C

OD_GE

N

MPA

A_CO

DRAT

ING

FILM_NUME PRET_INCHIR

_VHS

PRET_INCHIR

_DVD

AN_P

RODU

S

1 Drama R Mystic River 58.97 19.96 2003

2 ActAv R The Last Samurai 15.95 19.96 2003

3 Comedie PG-13 Something`s Gotta

Give

14.95 29.99 2003

4 ActAv PG-13 The Italian Job 11.95 19.99 2003

5 ActAv R Kill Bill: Vol 1 24.99 29.99 2003

6 ActAv PG-13 Pirates of the

Caraibbean: The

Curse of the Black

Pearl

29.99 29.99 2003

7 Drama PG-13 Big Fish 14.95 19.94 2003

8 ActAv R Man on Fire 50.99 29.98 2004

9 ActAv PG-13 Master and Commander: The Far

Side of the World

12.98 39.99 2003

10 Drama R Lost in translation 49.99 14.98 2003

11 Romantic PG-13 Two Weeks Notice 6.93 14.97 2002

12 Comedie PG-13 50 First Dates 9.95 19.94 2004

Page 16: Curs Sinteza SQL

13 Comedie PG-13 Matchstick Men 6.93 19.97 2003

14 Drama R Could Mountain 24.99 29.99 2003

15 Drama R Road to Perdition 9.99 14.99

16 Comedie PG-13 The School of Rock 11.69 29.99 2003

17 Romantic PG-13 13 Going on 30 14.94 28.95 2004

18 Drama R Monster 24.99 29.99 2003

19 ActAv PG-13 The Day After

Tomorrow

12.98 29.98 2004

20 Strain R Das Boot 17.99 19.94 1981

Figura 1-1 Listingul tabelului FILM

Se poate observa asemănarea dintre tabelele bazelor de date relaţionale şi foile

de calcul tabelar. Totuşi, bazele de date relaţionale oferă o flexibilitate mult mai mare

în organizarea şi afişarea informaţiilor.

Relaţii Relaţiile reprezintă asocierile dintre tabelele bazelor de date relaţionale. Deşi

fiecare tabel relaţional poate exista independent, esenţa bazelor de date este tocmai

stocarea informaţiilor între care există legături. De exemplu, pe lângă filmele propriu-

zise, puteţi stoca informaţii despre categoriile folosite de magazin pentru organizarea

inventarelor de filme. În acelaşi timp, puteţi stoca şi informaţii despre copiile fiecărui

film, inclusiv data la care a fost primită copia şi formatul acesteia, cum ar fi DVD sau

VHS. Prin folosirea realaţiilor, puteţi asocia tabelele înrudite, într-un mod formal,

uşor de folosit astfel încât puteţi să combinaţi date din tabele multiple în aceeaşi

interogare a bazei de date, dar păstrând flexibilitatea de a include numai informaţiile

care vă interesează.Posibilitatea de a selecta din baza de date numai informaţiile care

vă interesează vă permite să ajustaţi informaţiile din bază de date în funcţie de

cerinţele specifice ale persoanelor sau aplicaţiilor care au acces la baza de date.

Figura 1-2 prezinta patru tabele din baza de date a magazinului de produse

video si relaţiile dintre acestea, într-un format cunoscut sub numele de diagrama de

relatii a entitatilor (ERD – Entity Relationship Diagram). Fiecare dreptunghi din

diagrama reprezintă un tabel relaţional, cu numele tabelului scris deasupra liniei

orizontale si coloanele tabelului enumerate pe verticala , in portiunea principala a

dreptunghiului.

Relaţiile sunt implementate folosind coloane corespondente din cele două

tabele participante. În diagrama ERD coloana sau coloanele subliniate din fiecare

tabel. UN tabel poate avea o singură cheie primară. Totuşi , o cheie primară poate fi

compusă din mai multe coloane, dacă aceasta este calea de formare a unei chei unice.

Dacă o cheie primară este folosită într-un alt tabel pentru stabilirea unei relaţii, poartă

numele de chieie externă. În figură 1-2, observaţi coloanele cheie externă folosite în

tabelul FILM pentru crearea relaţiilor cu tabelele FILM_GENRE şi MPAA_RATING

şi marcate cu identificatoarele „<fk1>‖ şi „<fk2‖> în dreapta numelui coloanei cheie

externă. Şi coloana COD_LIMBA este marcată drept cheie externă , dar tabelul

LANGUAGE şi relaţia acestuia cu tabelul FILM au fost omise din figura de mai sus.

Cheile primare şi cheile externe sunt blocuri de construcţie fundamentale ale

modelului relaţional, deoarece stabilesc relaţii şi permit crearea legăturilor între date,

atunci când este necesar. Trebuie să înţelegeţi acest concept pentru a putea înţelege

cum funcţionează bazele de date relaţionale.

Page 17: Curs Sinteza SQL

Figura 1-2 Diagrama ERD a bazei de date (prezentare parţială)

Restricţii O restricţie este o regulă specificată pentru un obiect al bazei de date (de

obicei un table sau o coloană), având rolul de a limita într-un mod oarecare domeniul

de valori permise pentru obiectul respectiv al bazei de date.După ce sunt specificate,

restricţiile sunt impuse automat de sistemul DBMS şi nu pot fi ocolite decât dacă o

persoană autorizata le dezactivează sau le şterge(le elimină).Fiecare restricţie primeşte

un nume unic, astfel încât să poată fi referită în mesajele de eroare şi în comenzile

folosite ulterior în bază de date.Este recomandabil ca proiectanţii bazei de date să

denumească restricţiile, deoarece numele generate automat de bază de date nu sunt

foare descriptive. Totuşi , nu am denumit restricţiile din baza de date folosită ca

exemplu în această carte, deoarece, din păcate, nu toate produsele RDBMS

disponibile în prezent acceptă restricţiile denumite.

Există mai multe tipuri de restricţii pentru baze de date:

Restricţia NOT NULL Poate fi plasată pe o coloană pentru a împiedica

folosirea valorilor nule.O valoare nulă (null) este o modalitate specială prin care

sistemul RDBMS tratează valoarea unei coloane pentru a indica faptul că valoarea

coloanei respective nu este cunoscută. O valoare nulă nu este acelaşi lucru un un

spaţiu liber, un şir vid sau valoarea zero şi este o valoare specială care nu este egală cu

nimic altceva.

Restricţia cheie primară (primary key) Definită pe coloana (coloanele)

cheie primară ale unui tabel pentru a garanta că valorile cheie primară sunt

întotdeauna unice în întreg tabelul.Atunci când cheia primară este definită pe mai

multe coloane, combinaţia valorilor acelor coloane trebuie să fie unică în tabel - o

coloană care reprezintă doar o parte a valorii cheii primare poate conţine valori

duplicate în tabel. Restricţiile cheie primară sunt aproape inttotdeauna implementate

de RDBMS prin folosirea unui index.Indexul este un tip special de obiect al unei baze

FILM

FILM_ID <pk>

MPAA_RATING FILM_COD_GEN <fk1> FILM_GEN

MPAA_COD_RATING <pk> MPAA_COD_RATING <fk2> FILM_COD_GEN <pk>

MPAA_DESCRIERE_RATING FILM_NUME FILM_DESCRIERE_GEN

RETAIL_PRET_VHS

RETAIL_PRET_DVD

AN_PRODUS

FILM_COPII

FILM_ID <pk, fk>>

NUMAR_COPIE <pk>

DATA_CUMPARARE

DATA_VANZARE

FORMAT_MEDIA

Page 18: Curs Sinteza SQL

dedate care permite efectuarea căutărilor rapide în valorile coloanei.Atunci când în

tabele sunt înserate rânduri noi, sistemul RDBMS verifică automat indexul pentru a se

asigura că cheia primară a noului rând nu este deja folosită în tabel şi , dacă se

întâmplă acest lucru , respinge cererea de inserare. Căutarea în indexuri se face mult

mai repede decât căutarea în tabel;ca urmare, indexarea cheii primare este esenţială

pentru orice tabel, indiferent de dimensiunea acestuia, astfel încât căutarea cheilor

duplicate la fiecare inserare să nu ducă la o reducere semnificativă a performanţelor.

O caracteristică suplimentară a cheilor primare este faptul că nu pot fi definite decât

pe coloane pentru care a fost definită şi restricţia NOT NULL.

Restricţia de unicitate (unique) Definită pe o coloană sau un set de

coloane care trebuie să conţină valori unice ale tabelului. Ca şi în cazul cheilor

primare, sistemul RDBMS foloseşte aproape întotdeauna un index ca modalitate de

impunere eficientă a restricţiei.Totuşi, spre deosebire de cheile primare, un tabel poate

avea definite mai multe restricţii de unicitate, iar coloanele care participă la o

restricţie de unicitate pot conţine ( în cele mai multe sisteme RDBMS ) şi valori nule.

Restricţia referenţială (numită uneori restricţie de integritate

referenţială) O restricţie care impune o relaţie între două tabele dintr-o bază de date

relaţională. Prin „impunere‖ se înţelege că sistemul RDBMS se asigură întotdeauna,

în mod automat, că fiecărei valori a cheii externe îi corespunde o valoarea a cheii

primare în tabelul părinte.În tabelul FILM, sistemul RDBMS nu-mi permite să inserez

o înregistrare cu valoarea „M‖ în coloana MPAA_COD_RATING, deoarece „M‖ nu

este o valoarea MPAA_COD_RATING validă şi , ca urmare, nu apare ca valoare a

cheii primare din tabelul MPAA_RATING. În sens invers, sistemul RDBMS nu-mi

permite să şterg din tabelul MPAA_RATING rândul cu cheia primară „PG-13‖ ,

deoarece valoarea respectivă este folosită ca valoare a cheii externe pentru cel puţin

una din înregistrările din tabelul FILM. Pe scurt , restricţia referenţială garantează că

relaţia dintre cele două tabele şi valorile corespondente ale cheii primare şi cheii

externe îşi păstrează logica în orice moment.

Restricţia CHECK Foloseşte o instrucţiune logică simplă (scrisă în SQL)

pentru a valida valoarea unei coloane.Rezultatul instrucţiunii trebuie să fie o valoare

logică de adevărat (true) sau fals (false), astfel încât un rezultat adevărat să permită

înserarea în tabel a valorii coloanei, iar un rezultat fals să ducă la rejectarea valorii

coloanei , cu mesajul de eroare corespunzător.

Index

Un index reprezintă o cale rapidă de localizare şi sortare a Inregistrarilor dintr-

o tabelă prin gruparea tuturor înregistrărilor pentru un anumit atribur sau grup de

atribute. Indexarea este utilizată în două scopuri principale:

accelerarea căutărilor în baya de date

asigurarea unicităţii înregistrărilor

De exemplu, dacă ne intereayă anumite nume dintr-o tabelă Studenţi, putem

crea un index pentru coloana NumeSt, pentru a regăsi mai repede studenţii cu un

anmit nume de familie..

Page 19: Curs Sinteza SQL

Putem indexa şi mai multe coloane, de exemplu creem un index cu numele

NUME , pentru coloanele NumeSt şi PrenumeSt.

Deşi accelerează procesul de regăsire a datelor , indecşii îngreunează

actualizarea lor.Dupa fiecare operaţie de actualiyare)inserare, modificare, ştergere,

trebuie verificaţi şi actualiyaţi indecşii.Folosirea lor trebuie bine întemeiată altfel

măresc timpul de răspuns al sistemuluişi ocupă spaţiul suplimentar pe disc .

In Partea a-II-aAccess , se prezintă modul de creare a indecşilor şi în Partea

III, la DDL, create index.

Observaţie:

Cheia primară a unei tabele este indexaţa automat.

Nu pot fi indexate coloane de tipul :Memo, Hyperlinksau OLE

Când o coloană face parte din cheia primară a unei tabele, proprietatea

Indexed are valoarea Yes(No Duplicates), şi proprietatea Required

primeşte valoarea Yes, deoarece cheia primară nu poate conţine valoarea

null.

Vizualizări

O vizualizare (view) este o interogare stocată în baza de date şi pune la

dispoziţia utilizatorului un subset personalizat al datelor din unul sau mai multe tabele

ale bazei de date. Cu alte cuvinte, o vizualizare este un tabel virtual, deoarece arată ca

un tabel şi în cele mai multe privinţe se comportă că un tabel, dar nu stochează date (

nu este stocată decât interogarea SQL care defineşte vizualizarea).

Vizualizările au mai multe funcţii utile:

Maschează radurile pe care utilizatorul nu este nevoie să le vadă (sau nu-i

este permis să le vadă).

Maschează coloanele pe care utilizatorul nu are nevoie să le vadă (sau nu-i

este permis să le vadă).

Maschează operaţiile complexe efectuate în baza de date, cum ar fi

uniunile de tabele (respectiv combinarea coloanelor din tabele multiple

într-o singură interogare a bazei de date).

Îmbunătăţeşte performanţele interogărilor (în unele sisteme RDBMS,

precum Microsoft SQL Server).

Page 20: Curs Sinteza SQL

Proiectate bazele de date relaţionale

Această secţiune prezintă, foarte pe scurt, procesul general de proiectare a

bazelor de date. Atunci când aţi văzut pentru prima dată figură 1-2 , mai devreme în

acestă lecţie probabil v-aţi întrebat de ce coloanele au fost plasate în tabele multiple şi

de ce o anumită coloană a fost inclusă într-un anumit tabel şi nu în altul. Scopul

acestei secţiuni este de a vă ajuta să răspundeţi la întrebările de mai sus şi de a vă oferi

un punct de plecare, dacă decideţi să proiectaţi propriile baze de date pe măsură ce

învăţaţi limbajul SQL. Totuşi proiectarea bazelor de date este un domeniu mult mai

larg.

În 1972, Dr.E.F.Codd, părintele bazelor de date relaţionale, a pus la punct

un set de reguli care trebuie respectate (organizate în trei „forme normale‖) şi un

poroces numit normalizare, care este o tehinca pentru producerea unui set de relaţii

(termenul folosit de Dr. Codd pentru tabele) cu proprietăţile dorite.

Necesitatea normalizării

Normalizarea este procesul reversibil de transformare a unei relaţii, în relaţii

de structură mai simplă. Procesul este reversibil în sensul că nici o informaţie nu este

pierdută în timpul transformării. O relaţie este într-o formă normală particulară dacă

ea satisface o mulţime specificată de constrângeri.

Procesul normalizării se realizează plecând de la o relaţie universală ce

conţine toate atributele sistemului de modelat, plus o mulţime de anomalii. Orice

formă normală se obţine aplicând o schemă de descompunere. Există două tipuri de

descompuneri.

Descompuneri ce conservă dependenţele. Această descompunere

presupune desfacerea relaţiei R în proiecţiile R1, R2, ..., Rk, astfel încât

dependenţele lui R sunt echivalente (au închideri pseudo-tranzitive

identice) cu reuniunea dependenţelor lui R1, R2, ..., Rk.

Descompuneri fără pierderi de informaţie. Această descompunere

presupune desfacerea relaţiei R într-o mulţime de proiecţii R1, R2, ..., Rj,

astfel încât pentru orice realizare a lui R este adevărată relaţia:

O descompunere fără pierdere de informaţie, utilizată în procesul normalizării,

este dată de regula Casey-Delobel:

Fie R(A) o schemă relaţională şi fie α, β, γ o partiţie a lui A. Presupunem că α

determină funcţional pe β. Atunci:

α β mulţimea atributelor care intervin în dependenţele funcţionale;

α γ reprezintă reuniunea determinantului cu restul atributelor lui A.

Tabelul de mai jos prezintă tabelul FILM fără normalizare, aşa cum ar arăta

dacă toate informaţiile despre filme ar fi colectate într-un singur tabel.Acest exemplu

va fi folosit pentru ilustrarea procesului de normalizare. În general, numele coloanelor

din tabelele relaţionale folosesc liniuţe de subliniere pentru separarea cuvintelor. În

discuţia despre normalizare am eliminat aceste liniuţe din figuri, pentru a face textul

mai uşor de citit.

Page 21: Curs Sinteza SQL

Anomaliile care apar în lucrul cu baza de date se produc datorită

dependenţelor care există între datele din cadrul relaţiilor bazei de date.

Dependenţele sunt plasate greşit în tabele!

Există trei probleme care pot apărea în tabelele fără normalizare şi toate trei

există în tabelul de mai jos. Scopul procesului de normalizare este de a elimina aceste

probleme (anomalii) din proiectul bazei de date.

Figura 1-3 Tabelul FILM fară normalizare

Anomalia de inserare

Anomalia de inserare se referă la o situaţie în care nu puteţi insera date în baza

de date din cauza unei dependenţe artificiale dintre coloanele unui tabel.

Să presupunem că vreti să adăugaţi în baza de date a magazinului un nou gen

de film care urmează a fi folosit pentru clasificarea filmelor.Tabelul de mai sus nu

permite acest lucru decât dacă aveţi un film care să fie plasat în categoria respectivasi

pe care va trebui să-l adăugaţi în tabelul FILM în acelaşi timp.Ar fi mult mai bine

dacă aţi putea adauga noile genuri înainte de primirea filmelor în magazin.

FILM

_ID

G

E

N_

C

O

D

GE

N_

DE

SC

RIE

RE

LAN

G_

COD

E

MPAA

_COD

_RATI

NG

MPAA_RATIN

G_DESC

FILM_NUM

E

AN

_P

RO

DU

S

DATA_CUM

PARARE

DAT

A_VA

NZA

RE

MEDIA

_FORM

AT

PRET-

INCHI

RIERE

1 Dr

am

a

Dra

ma

en, fr R Sub 17 ani

necesita

prezenta

parintilor sau a

unui adult

Mystic River 200

3

01/01/2005 DVD 19.96

2 Ac

lA

d

Act

Av

si

ave

ntur

a

en, fr,

es

R Sub 17 ani

necesita

prezenta

parintilor sau a

unui adult

The Last

Samurai

200

3

01/10/2005 DVD 19.96

2 Ac

tA

v

Acti

une

si

ave

ntur

a

en, fr,

es

R Sub 17 ani

necesita

prezenta

parintilor sau a

unui adult

The Last

Samurai

200

3

01/10/2005 VHS 15.95

3 Co

me

die

Co

med

ie

en PG-13 Parintii sunt

avertizati

Something's

Gotta Give

200

3

01/10/2005 1/30/2

005

DVD 29.99

3 Co

me

die

Co

med

ie

en PG-13 Parintii sunt

avertizati

Something's

Gotta Give

200

3

2/15/2005 DVD 29.99

4 Ac

tA

v

Acti

une

si

ave

ntur

a

en, fr PG-13 Parintii sunt

avertizati

The Italian

Job

200

3

2/15/2005 DVD 19.99

Page 22: Curs Sinteza SQL

Anomalia de ştergere

Anomalia de ştergere este inversul anomaliei de inserare. Se referă la situaţia

în care ştergerea unor date duce la pierderea neintenţionată a altor date. De exemplu

dacă primul film din tabel este singurul rând din tabelul FILM pentru care coloana

GEN_COD are valoarea „Drama‖ , şi este şters, se pierde informaţia că a existat

vreodată un gen numit „Drama”

Anomalia de actualizare

Anomalia de actualizare se referă la o situaţie în care actualizarea unei singure

valori necesită actualizarea mai multor rânduri. De exemplu , dacă în tabelul prezentat

mai sus trebuie să modificaţi descrierea codului MPAA_COD_RATING „R‖, trebuie

să modificaţi şi toate rândurile din tabel pentru filmele cu codul respectiv. Probleme

similare apar şi pentru coloana GEN_DESCRIERERIPTION. Chiar şi coloana

PRET_INCHIR are această problemă, deoarece toate copiile aceluiaşi film (cu aceeaşi

valoare FILM_ID ) pe acelaşi mediu (DVD sau VHS) ar trebui să aibă acelaşi preţ.

Un alt pericol legat de această anomalie este faptul că stocarea unor date redundante

poate aduce la posibilitatea de actualiza numai o parte a copiilor respectivelor date,

ceea ce ar avea ca rezultat apariţia inconsecvenţelor în baza de date.

Aplicarea procesului de normalizare

De obicei, normalizarea începe de la mijloacele de redare a datelor care sunt

(sau vor fi) prezentate utilizatorilor, cum ar fi pagini web, ecrane ale aplicaţiilor,

rapoarte şi aşa mai departe. Colectiv, acestea sunt numite vizualizări de utilizator

(user views). Poate părea ciudat la prima vedere, dar este ceva obişnuit ca proiectarea

unui sistem de prelucrare a datelor să înceapă de la rezultatele pe care le va vedea

utilizatorul, parcurgând apoi drumul înapoi către mijloacele folosite pentru obţinerea

rezultatelor dorite. În timpul proiectării bazei de date, procesul de normalizare este

aplicat fiecărei vizualizări , iar rezultatul este un set de relaţii normalizate care pot fi

apoi direct implementate ca tabele ale bazei de date relaţionale.

Stăpânirea procesului de normalizare cere timp şi exerciţiu, în specia deoarece

impune prouectantului să se gândească într-un mod conceptual la datele şi relaţiile pe

care intenţionează să le folosească. În timpul normalizării , consideraţi ca fiecare

vizualizare este o relaţie.

Cu alte cuvinte, conceptualizaţi fiecare vizualizare ca şi cum ar fi deja un tabel

bidimensional .

De asemenea , este nevoie de timp pentru a va obişnui cu terminologia folosită

în procesul de normalizare. În timpul acestui proces, majoritatea proiectanţilor evită

folosirea unor termeni fizici, precum tabel, coloană şi cheie primară.

Deşi relaţia pe cale de a fi normalizată reprezintă o propunere de tabel , încă

nu există ca tabel fizic, aşa că termenul nu este foarte exact.

Procesul de normalizare este aplicat sistematic fiecărei vizualizări. Cel puţin

la început este mai uşor să reprezentaţi fiecare vizualizare ca un tabel bidimensional,

conţinând date repetitive, aşa cum am făcut în figura 1-3. Pe măsură ce parcurgeţi

procesul de normalizare, veţi rescrie relaţiile existente şi veţi crea altele. Rescrierea

vizualizărilor în relaţii (tabele) cu date reprezentative este un proces obositor şi

Page 23: Curs Sinteza SQL

consumator de timp. Trebuie să fiţi foarte atent ca exemplele de date folosite pentru

luarea deciziilor în procesul de normalizare să fie cu adevărat reprezentative pentru

tipurile de valori care vor apărea în datele reale. Aşa cum probabil vă aşteptaţi,

exemple prost alese duc deseori la proiectarea eronată a bazei de date.

Scopul procesului de normalizare este eliminarea anomaliilor de inserare,

actualizare si ştergere. Procesul determină crearea unui număr mai mare de relaţii

decât aţi avea într-un model fără normalizare. Relaţiile suplimentare sunt necesare

pentru eliminarea anomaliilor, dar împărţirea datelor în mai multe relaţii face ca

extragerea datelor stocate să fie puţin mai dificilă.

Alegerea unui identificator unic

Primul pas al procesului de normalizare constă în alegerea unui identificator

unic (unique identifier), care este un atribut (o coloană) sau un set de atribute care

identifică în mod unic fiecare rând de date dintr-o relaţie.

Identificatorul unic va deveni ulterior cheia primară a tabelului creat din

relaţia normalizată. Pentru normalizare, este obligatoriu ca fiecare relaţie să aibă un

identificator unic. In multe cazuri, puteţi găsi un atribut care identifică în mod unic

datele din fiecare rând al relaţiei pe care vreţi să o normalizaţi. Atunci când nu puteţi

găsi un singur atribut care să poată fi folosit ca identificator unic, este posibil să găsiţi

mai multe atribute care pot fi concatenate (combinate) pentru a forma un identificator

unic. Atunci când identificatoarele unice sunt formate din atribute multiple, fiecare

atribut rămâne pe propria lui coloană - nu faceţi decât să definiţi un identificator unic

format din mai multe coloane, în foarte puţine cazuri, într-o relaţie nu există un set

rezonabil de atribute care să poată fi folosit ca identificator unic. Atunci când se

întâmplă acest lucru, trebuie să inventaţi un identificator unic, deseori cu valori

atribuite secvenţial sau aleatoriu pe măsură ce noile rânduri de date sunt adăugate în

tabelul bazei de date. Această tehnică este sursa unor identificatoare unice, precum

numărul de asigurări sociale folosit în Statele Unite, numerele de identificare ale

angajaţilor sau numerele de înmatriculare ale maşinilor.

Relaţia FILM din figura 1-3 ne pune o problemă în privinţa găsirii unui

identificator unic. La prima vedere, ar părea că atributul FILM_ID este cel mai

potrivit în acest scop. Totuşi, observaţi că valorile FILM_ID „2" şi „3" apar de câte

două ori, aşa că, fără nici un dubiu, această valoare nu este unică. Problema este că

valoarea FILM_ID identifică în mod unic fiecare titlu, dar magazinul urmăreşte

separat fiecare copie a filmelor pe care le are în stoc Cauza este faptul că magazinul se

ocupă şi de închirierea filmelor şi vrea să se asigure că fiecare client returnează exact

copia pe care a închiriat-o. După inspectarea datelor folosite ca exemplu şi o scurtă

discuţie cu proprietarul magazinului, ajungeţi la concluzia că în relaţia FILM nu

există nici o combinaţie de atribute care să identifice în mod unic fiecare copie a unui

film, aşa că inventaţi un atribut numit NR_ COPIE şi-1 adăugaţi în relaţie. Ori de câte

ori inventaţi un identificator unic (sau o parte a unui identificator) este foarte

important ca toţi să înţeleagă valorile pe care le va lua acest identificator. In acest caz,

proprietarul magazinului decide ca valorile NR_ COPIE să reînceapă de la 1 pentru

fiecare valoare FILM_ID, ceea ce înseamnă că valorile NR_ COPIE sunt unice numai

în combinaţie cu valorile FILM_ID. Relaţia rezultată este prezentată în figura 1 –4

Page 24: Curs Sinteza SQL

Prima formă normală: eliminarea datelor repetate

O relaţie este în prima formă normală atunci când nu conţine atribute cu

valori multiple (atribute mulţi valoare), adică atribute care au mai multe valori

pentru acelaşi rând de date. Într-o relaţie, orice intersecţie a unui rând cu o coloană

trebuie să conţină cel mult o valoare pentru ca relaţia să fie în prima formă normală.

în figura 1-4, atributul pentru limbă (COD_LIMBA) conţine mai multe valori pentru

unele dintre filme, aşa că-l puteţi considera un atribut cu valori multiple. Atributele de

acest tip sunt mai greu de întreţinut, deoarece valorile din listă trebuie să fie mai întâi

separate, astfel încât valorile individuale să poată fi modificate fară a le afecta pe

celelalte.

Uneori, un atribut multivaloare este deghizat sub forma atributelor multiple.

De exemplu, figura 14 ar putea fi modificată astfel încât să conţină atribute (coloane)

separate pentru cel mult trei limbi corespunzătoare fiecărui film, numite Language 1,

Language 2 şi Language 3. Totuşi, si acestea ar fi considerate atribute multivaloare,

dar într-o forma specială, numită grup repetitiv, care nu este acceptat în prima formă

normală. Din punct de vedere logic, un grup repetitiv nu este diferit de un atribut

multivaloare. De fapt, grupurile repetitive prezintă deseori chiar mai multe probleme

decât atributele multivaloare, deoarece trebuie să adăugaţi o nouă coloană în tabel ori

de câte ori vreţi să adăugaţi mai multe valori decât a prevăzut iniţial proiectantul bazei

de date (cum ar fi o a patra limbă pentru un film). Bazele de date relaţionale cer ca

toate rândurile dintr-un tabel să aibă acelaşi număr de coloane, dar un tabel poate

conţine orice număr de rânduri

Figura 1-4 Relaţia FILM

.

Ca urmare, procesul de normalizare pentru obţinerea primei forme normale

cere să transformaţi coloanele repetate şi valorile repetate din coloane în rânduri

repetate într-un tabel separat .

FIL

M_I

D

N

R

_

C

O

PI

E

GEN_

COD

GEN_

DESC

RIERE

CO

D_L

IMB

A

MPA

A_C

OD_

RAT

ING

MPAA_RATING

_DESC

FILM_NU

ME

A

N_

PR

O

D

US

DATA_

CUMPA

RARE

DA

TA_

VA

NZ

AR

E

MEDI

A

FORM

AT

PRET

_INC

HIR

1 1 Dram

a

Drama en,

fr

R Sub 17 ani

necesita prezenta

parintilor sau a

unui adult

Mystic

River

20

03

01/01/20

05

DVD 19.96

2 1 AclA

d

Actiune

si

aventur

a

en,

fr, es

R Sub 17 ani

necesita prezenta

parintilor sau a

unui adult

The Last

Samurai

20

03

01/10/20

05

DVD 19.96

2 2 ActA

v

Actiune

si

aventur

a

en,

fr, es

R Sub 17 ani

necesita prezenta

parintilor sau a

unui adult

The Last

Samurai

20

03

01/10/20

05

VHS 15.95

3 1 Come

die

Comedi

e

en PG-

13

Parintii sunt

avertizati

Something'

s Gotta

Give

20

03

01/10/20

05

1/30

/200

5

DVD 29.99

3 2 Come

die

Comedi

e

en PG-

13

Parintii sunt

avertizati

Something'

s Gotta

Give

20

03

2/15/200

5

DVD 29.99

4 1 ActA

v

Actiune

si

aventur

a

en,

fr

PG-

13

Parintii sunt

avertizati

The Italian

Job

20

03

2/15/200

5

DVD 19.99

Page 25: Curs Sinteza SQL

Pentru transformarea relaţiilor ne-normalizate în prima formă normală,

trebuie să mutaţi atributele multivaloare şi grupurile repetitive în noi relaţii.

Deoarece grupurile repetitive reprezintă un set de atribute care se repetă împreună,

toate atributele dintr-un grup repetitiv ar trebui mutate în aceeaşi relaţie. Pe de altă

parte, un atribut multivaloare (un atribut individual care are valori multiple) ar trebui

să fie mutat într-o nouă relaţie proprie, nu să fie combinat cu alte atribute multivaloare

în noua relaţie.

Procedura de mutare a unui atribut multivaloare sau a unui grup repetitiv într-o

nouă relaţie constă în următoarele etape:

1. Creaţi o nouă relaţie, cu un nume sugestiv. Deseori, este bine să includeţi

numele relaţiei originale, parţial sau în întregime, în numele noii relaţii.

2. Copiaţi identificatorul unic din prima relaţie în noua relaţie. Datele depind

de acest identificator în relaţia originală, aşa că trebuie să depindă de aceeaşi cheie şi

în noua relaţie. Identificatorul copiat va deveni cheie externă în noua relaţie.

3. Mutaţi grupul repetitiv sau atributul multivaloare în noua relaţie. (Am

folosit aici verbul a muta, deoarece aceste atribute sunt şterse din relaţia originală.)

4. Formaţi un identificator unic în noua relaţie, adăugând atribute la

identificatorul unic copiat din relaţia originală. Ca întotdeauna, asiguraţi-vă că

identificatorul unic nou format conţine numai numărul minim de atribute necesar

pentru a-1 face unic. Dacă mutaţi un atribut multivaloare, care, în esenţă, este un grup

repetitiv cu un singur atribut, este adăugat atributul respectiv pentru formarea

identificatorului unic. Poate părea ciudat la prima vedere, dar identificatorul unic

copiat din relaţia originală nu este doar o cheie externă, ci, de obicei, şi o parte a

identificatorului unic (cheia primară) a noii relaţii. Acest lucru este absolut normal.

De asemenea, este perfect acceptabil să avem o relaţie în care toate atributele fac parte

din identificatorul unic (adică nu există atribute care să nu facă parte din cheie).

5. Opţional, puteţi să înlocuiţi cheia primară cu un singur atribut surogat

pentru cheie. Dacă faceţi acest lucru, trebuie să păstraţi şi atributele care compun

cheia primară naturală, formată la paşii 2 şi 4.

Figura 1-5 prezintă rezultatul aducerii relaţiei din figura 1-4 la prima formă

normală. Observaţi următoarele:

Page 26: Curs Sinteza SQL

• Am folosit o mică scurtătură în cazul identificatorului unic în noua relaţie

FILM Language. Limba în care este disponibil un film se aplică filmului, în general,

nu copiilor individuale. Observaţi în figura 1-4 că lista de limbi disponibile nu se

schimbă între rândurile duplicate ale aceluiaşi film. Ca urmare, partea NR_ COPIE a

identificatorului unic din relaţia FILM nu a fost copiată în noua relaţie FILM

Language. Dacă aş fi făcut acest lucru, aş fi creat în noua relaţie o problemă specifică

celei de-a doua forme normale, pe care ar fi trebuit să o rezolv în următoarea etapă a

procesului de normalizare. Veţi descoperi că, deseori, proiectanţii experimentaţi de

baze de date sintetizează cele trei forme normale şi rescriu relaţiile originale direct în

a treia formă normală. Exersând, veţi putea şi dumneavoastră să faceţi acelaşi lucru.

Figura 1-5 Soluţia primei forme normale

• Atributul FILM_ID a fost copiat din relaţia originală (FILM) în noua relaţie

(FILM Language).

• Atributul multivaloare COD_LIMBA a fost mutat din relaţia FILM în relaţia

FILM Language, cu numele Language Code. (Numele abreviate ale atributelor din

FIL

M_I

D

NR

_C

OPI

E

GEN

_CO

D

GEN_D

ESCRIE

RE

MPA

A_CO

D_RA

TING

MPAA_RATING_

DESC

FILM_NUME A

N

_

P

R

O

D

U

S

DATA

_CUM

PARA

RE

DAT

A_VA

NZAR

E

MEDIA

FORMAT

PRET

_INC

HIR

1 1 Dram

a

Drama R Sub 17 ani necesita

prezenta parintilor

sau a unui adult

Mystic River 2

0

0

3

01/01/

2005

DVD 19.96

2 1 AclA

d

Actiune

si

aventura

R Sub 17 ani necesita

prezenta parintilor

sau a unui adult

The Last

Samurai

2

0

0

3

01/10/

2005

DVD 19.96

2 2 ActA

v

Actiune

si

aventura

R Sub 17 ani necesita

prezenta parintilor

sau a unui adult

The Last

Samurai

2

0

0

3

01/10/

2005

VHS 15.95

3 1 Come

die

Comedie PG-13 Parintii sunt

avertizati

Something's

Gotta Give

2

0

0

3

01/10/

2005

1/30/2

005

DVD 29.99

3 2 Come

die

Comedie PG-13 Parintii sunt

avertizati

Something's

Gotta Give

2

0

0

3

2/15/2

005

DVD 29.99

4 1 ActA

v

Actiune

si

aventura

PG-13 Parintii sunt

avertizati

The Italian Job 2

0

0

3

2/15/2

005

DVD 19.99

FILM_ID COD_LIMBA

1 en

1 fr

2 en

2 fr

2 es

3 en

4 en

4 fr

Page 27: Curs Sinteza SQL

figura 1-4 au fost folosite doar pentru ilustrare - este recomandabil să prescurtaţi

numele numai dacă este absolut necesar.)

• Identificatorul unic din relaţia FILM Language este format prin combinarea

atributelor FILM_ID şi Language Code, adică din toate atributele relaţiei.

• Nici FILM, nici FILM Language din figura 1-5 nu conţin grupuri repetitive

sau atribute multivaloare, aşa că ambele relaţii sunt în prima formă normală.

A doua formă normală: eliminarea dependenţelor parţiale

Înainte de a explora a doua formă normală, trebuie definit conceptul de

dependenţă funcţională. Pentru această definiţie, voi folosi două atribute arbitrare,

inteligent denumite „A" şi „B". Atributul B este dependent funcţional de atributul A

dacă în nici un moment nu există mai mult de o valoare a atributului B asociată cu o

valoare dată a atributului A. In primul rând, a spune că atributul B este funcţional

dependent de atributul A înseamnă şi că atributul A determină atributul B sau că A

este un determinant (identificator unic) pentru atributul B.

În al doilea rând, să ne mai uităm o dată la relaţiile din figura 1-5.

În relaţia FILM, puteţi să vă daţi seama cu uşurinţă că atributul FILM_NUME

este dependent funcţional de atributul FILM_ID, deoarece, în orice moment, poate

exista o singură valoare FILM_NUME pentru o valoare FILM_ID dată. Chiar faptul

că valoarea FILM_ID defineşte în mod unic valoarea FILM_NUME în relaţie

înseamnă că FILM_NUME este dependent funcţional de FILM_ID.

Se spune că o relaţie este în a doua formă normală dacă îndeplineşte

următoarele criterii:

• Relaţia este în prima formă normală.

• Toate atributele non-cheie sunt dependente funcţional de identificatorul

unic (cheia primară), luat ca întreg.

Aplicând aceste criterii relaţiei FILM din figura 1 -5, este clar că avem câteva

probleme. Identificatorul unic este o combinaţie a atributelor FILM_ID şi NR_

COPIE. Totuşi, numai atributele DATA_CUMPARARE, DATA_VANZARE,

MEDIA FORMAT şi PRET_INCHIR depind de întregul identificator. Şi este logic să

fie aşa. Indiferent câte copii ale unui film avem în baza de date, toate au aceleaşi

valori pentru gen, categorie MPAA, TITLU şi AN_PRODUS.

Unele atribute descriu filmul în sine, în timp ce altele descriu copiile pe care le

deţine (sau le-a deţinut) magazinul din filmul respectiv. In esenţă, am amestecat

atribute care descriu în aceeaşi relaţie două lucruri (entităţi) diferite (deşi înrudite) din

lumea reală.

A doua formă normală se aplică numai relaţiilor care au identificatoare unice

concatenate (adică formate din atribute multiple). într-o relaţie care are un singur

atribut ca identificator unic, este imposibil ca un alt atribut să depindă de o parte a

identificatorului unic, deoarece acesta, fiind format dintr-un singur atribut, nu are părţi

componente. Ca urmare, orice relaţie în prima formă normală care are cheia primară

formată dintr-un singur atribut este automat în a doua formă normală.

După ce descoperiţi o încălcare a celei de-a doua forme normale, soluţia este

să se mute atributele parţial dependente într-o nouă relaţie, în care să depindă de

întreaga cheie primară. Figura 1-6 prezintă această soluţie. Toate atributele care

depind numai de FILM_ID sunt acum într-o relaţie (numită FILM) în care FILM_ID

este identificator unic. Cele care depind de combinaţia FILM_ID şi NR_ COPIE sunt

într-o relaţie (numită FILM Copy) în care FILM_ID şi NR_ COPIE formează

Page 28: Curs Sinteza SQL

identificatorul unic. Relaţia FILM Language era deja în a doua formă normală,

deoarece nu are atribute non-cheie şi, ca urmare, a rămas nemodificată.

FILM:

FILM_ID

GEN_ COD

GEN_DESCRIERE MPAA_ COD_RATING

MPAA_DESCRIERE_RATING

FILM_NUME AN_PRODUS

1 Drama Drama R

Sub 17 ani

necesita prezenta

parintilor sau a

unui adult

Mystic River

2003

2 ActAv Actiune si aventura R

Sub 17 ani

necesita

prezenta

parintilor sau a

unui adult

The Last

Samurai

2003

3 Comed

ie Comedie PG-13

Parintii sunt

avertizati

Something's

Gotta Give 2003

4 ActAv Actiune si aventura PG-13 Parintii sunt

avertizati

The Italian

Job 2003

FILM LANGUAGE:

FILM_ID LANGUAGE_CODE

1 En

1 Fr

2 En

2 Fr

2 Es

3 En

4 En

4 Fr

FILM COPY:

FILM ID NR_ COPIE DATA_CUMPARARE DATA_VAN

ZARE MEDIA FORMAT PRET_INCHIR

1 1 01/01/2005 DVD 19.96

2 1 01/10/2005 DVD 19.96

2 2 01/10/2005 VHS 15.95

3 1 01/10/2005 1/30/2005 DVD 29.99

3 2 2/15/2005 DVD 29.99

4 1 2/15/2005 DVD 19.99

Figura 1-6. Soluţia pentru a doua formă normală

A treia formă normală: eliminarea dependenţelor tranzitive

Pentru a înţelege a treia formă normală, trebuie să se definescă conceptul de

dependenţă tranzitivă. Despre un atribut care depinde de un atribut care nu este

identificator unic (cheie primară) a relaţiei se spune că este dependent tranzitiv.

Page 29: Curs Sinteza SQL

În relaţia FILM din figura 1 -6, observăm că atributul GEN_DESCRIERE

depinde de atributul GEN_COD, iar MPAA Ratig Description depinde de

MPAA_COD_RATING. Pericolul păstrării acestor descrieri în relaţia FILM este

faptul că, în final, cele două atribute ajung să depindă de înregistrarea unui film, ceea

ce duce la toate cele trei anomalii de date prezentate mai devreme în acest capitol.

Se spune că o relaţie este în a treia formă normală dacă îndeplineşte

următoarele două criterii:

Relaţia este în a doua formă normală.

Nu există dependenţe tranzitive (cu alte cuvinte, toate atributele non-cheie

depind numai de identificatorul unic).

Pentru a aduce la a treia formă normală o relaţie aflată în a doua formă

normală, se mută atributele dependente tranzitiv în relaţii în care depind numai de

cheia primară. Se lasă atributul de care depind acestea în relaţia originală, cu rolul de

cheie externă.Va trebui apoi să reconstruim vizualizarea originală printr-o uniune.

Ca efect secundar, toate atributele uşor de calculat sunt eliminate ca încălcări

ale criteriilor celei de-a treia forme normale. De exemplu, într-o bază de date pentru

vânzări, Suma Totală este obţinută înmulţind Cantitatea Cumpărată cu Preţul Unitar;

aşa cum se observă cu uşurinţă, Suma Totală este dependentă de Cantitatea

Cumpărată şi de Preţul Unitar. Presupunând ci toate cele trei atribute sunt dependente

de identificatorul unic al relaţiei care le conţine, este uşor de văzut că Suma Totală

(rezultatul calculat) este, de fapt, dependentă tranzitiv te celelalte două atribute.

Figura 1-7 conţine soluţia în a treia formă normală. S-au creat noi relaţii

pentru MPAA Rating şi FILM Gen, s-a mutat descrierile în noile relaţii şi am lăsat

atributele pentru coduri (MPAA_COD_RATING şi FILM GEN_COD) în relaţia

FILM, definite ca fiind chei externe. Mulţi proiectanţi de baze de date numesc relaţiile

MPAA Rating şi FILM Genre „tabele de căutare" sau „tabele de coduri‖ deoarece

sunt utilizate, în principal, pentru căutarea codurilor stocate în coloana cheie primară a

relaţiei. Totuşi aceste relaţii au şi alte roluri, cum ar fi controlul codurilor şi furnizarea

unei surse convenabile pentru lista de coduri valide, care poate fi folosită într-o listă

derulantă de pe o pagină web.

FILM:

FILM_

ID

GEN_

COD

MPAA_

COD_RA

TING

FILM_NUME

PRET_

INCHIR VHS

PRET_

INCHI

R DVD

AN_PRODUS

1 Drama R Mystic River 58.97 19.96

2003

2 ActAv R The Last

Samurai

15.95 19.96 2003

3 Comedie PG-13 Something's

Gotta Give

14.95 29.99 2003

4 ActAv PG-13 The Italian Job 11.95 19.99

2003

Page 30: Curs Sinteza SQL

FILM_ COPII:

FILM_ID NR_ COPIE DATA_CUMPAR

ARE

DATE _

VINZARE

MEDIA_FORMA

T

1 1 01/01/2005 DVD

2 1 01/10/2005 DVD

2 2 01/10/2005 VHS

3 1 01/10/2005 1/30/2005 DVD

3 2 2/15/2005 DVD

4 1 2/15/2005 DVD

MPAA Rating :

MPAA_COD_RATING MPAA_DESCRIERE_RATING

PG-13 Parintii sunt avertizati

R Sub 17 ani necesita prezenta parintilor sau a unui adult

FILM GEN :

FILM

GEN_COD

FILM_GEN_DES

CRIERE

ActAv Actiune si aventura

Comedie Comedie

Drama Drama

Figura 1-7. Soluţia pentru a treia formă normală

O altă modificare făcută pentru a ajunge la a treia formă normală este legată de

atributul PRET_INCHIR (preţ cu amănuntul) din relaţia Movie Copy, aşa cum se

poate vedea în figura 1-6. După o discuţie cu proprietarul magazinului, am stabilit că

preţul depinde de combinaţia dintre Movie ID şi Media Format, toate copiile cu

aceleaşi valori pentru FILM_ID şi Media Format având acelaşi preţ. In mod clar,

aceasta este o dependenţă tranzitivă şi, ca urmare, o încălcare a celei de-a treia forme

normale.

Soluţia normală pentru o asemenea problemă ar fi crearea unei relaţii numite

FILM Price, având ca identificator unic combinaţia dintre FILM_ID şi Media Format,

şi mutarea atributului PRET_INCHIR din FILM Copy în noua relaţie. Totuşi, în

timpul discuţiei s-a aflat că urmează să se renunţe la furnizarea filmelor în format

VHS, deoarece sunt cerute de un număr foarte mic de clienţi şi că peste câteva luni

magazinul va avea numai filme pe DVD.

Ţinând seama de această informaţie, am decis să mut preţul în două coloane

din tabelul FILM, una cu preţul pentru DVD şi una cu preţul pentru VHS. Deşi se

poate spune că aceasta este o încălcare a primei forme normale (şi, din punct de

vedere tehnic chiar este), mi s-a părut a fi cel mai bun compromis.

Proiectarea bazelor de date nu este întotdeauna o ştiinţă exactă, aşa că de

multe ori există posibilitatea unor mici ajustări, cu condiţia ca proiectantul să ia în

calcul consecinţele potenţiale (măsurate în termenii anomaliilor de date) ale fiecărui

compromis.

Page 31: Curs Sinteza SQL

Forma normală Boyce-Codd (BCNF)

Deşi nu ne propunem să discutăm şi alte forme normale avansate, consider

necesar să le amintim.

Dr. E. F. Codd a participat la definirea unei versiuni mai puternice a celei de-a

treia forme normale, numită forma normală Boyce-Codd.

Determinantul este un atribut sau o mulţime de atribute neredundante, care

constituie un identificator unic pentru alt atribut sau altă mulţime de atribute ale unei

relaţii date.

Intuitiv, o relaţie R este în forma normală Boyce-Codd dacă şi numai dacă

fiecare determinant este o cheie candidat.

Formal, o relaţie R este în forma normală Boyce-Codd dacă şi numai dacă

pentru orice dependenţă funcţională totală X A, X este o cheie (candidat) a lui R.

Exemplu: ADRESA(cod_parsoana#, telefon#, adresa)

cod_persoana

adresa

telefon

În dependenţa adresa telefon se observă că determinantul nu este o cheie

candidat. Relaţia ADRESA se desface în:

ADRESA_1(cod_persoana#, adresa);

ADRESA_2(adresa#, telefon).

Relaţiile sunt în BCNF, se conservă datele, dar nu se conservă dependenţele

(s-a pierdut cod_persoana, telefon adresa).

Diferiţi alţi autori şi cercetători au oferit propriile extensii, numite a patra

formă normală, a cincea formă normală, forma normală cu cheie de domeniu şi altele.

A patra formă normală(FN4) elimină redudanţele datorită relaţiilor de tip m:m.

Este nevoie de ceva exerciţiu în procesul de normalizare înainte ca aceste extensii să

devină logice.

In plus, a treia formă normală acoperă toate anomaliile pe care este posibil să

le întâlniţi în lucrul cu baze de date obişnuite.

Prezentarea generală a bazei de date pentru un magazin video

Majoritatea exemplelor din acest curs folosesc ca model o bază de date pentru

un magayin virtual de produse video.

Instrucţiunile SQL pentru creare obiectelor bazei de date şi pentru popularea

acestora cu date vor fi prezentate în lecţiile următoare.

În figura 1-8 se prezintă disgrama entitate relaţie, ERD (Entity Relationship

Diagram) pentru această bază de date.

Page 32: Curs Sinteza SQL

FILM_ID PK

FILM_COD_GEN FK1

MPAA_COD_RATING PK MPAA_COD_RATING FK2 FILM_COD_GEN PK

MPAA_DESCRIERE_VARSTE FILM_NUME FILM_DESCRIERE_GEN

RETAIL_PRET_VHS

RETAIL_PRET_DVD

AN_PRODUS

FILM_ID PK,FK1 FILM_ID PK,FK1

FILM_ID PK,FK1 NUMAR_COPIE PK NUMAR_COPIE PK,FK1

COD_LIMBA PK,FK2 DATA_CUMPARARE TRANZACTIE_ID PK,FK2

DATA_VANZARE DATA_INTOARCERE

FORMAT_MEDIA COST_INCHIRIERE

COST_INTARZIERE_SAU_PIERDERE

DATA_RETURNARE

COD_LIMBA PK

NUME_LIMBA CLIENT_CONT_ID PK TRANZACTIE_ID PK

CLIENT_HOLD_IND CLIENT_CONT_ID FK1

DATA_INSCRIS ANGAJAT_PERSOANA_ID

DATA_TERMINAT TRANZACTIE_DATA

CLIENT_DEPOZIT_SUMA VANZARI_TAXA

CLIENT_CONT_ID PK,FK1 CARD_CREDIT_LA_DOSAR_INDIC

PERSOANA_ID PK,FK2 COPIL_INCHIRIERE_PERMIS_INDIC

PERSOANA_ID PK PERSOANA_ID PK,FK1

PERSOANA_PRENUME SUPERVISOR_PERSOANA_ID

PERSOANA_NUME_MIJLOCIU ANGAJAT_TAXA_ID

PERSOANA_NUME ANGAJAT_JOB_CATEGORIE

PERSOANA_ADRESA_1 ANGAJAT_RATA_PE_ORA

PERSOANA_ADRESA_2 ANGAJARE_DATA

PERSOANA_ADRESA_ORAS INCHIDERE_DATA

PERSOANA_ADRESA_JUDET_PROV

PERSOANA_ADRESA_COD_POSTAL

PERSOANA_ADRESA_TARA

PERSOANA_TELEFON

NASTERE_DATA

MOARTE_DATA

CLIENT_COD_PERSOANA

PERSOANA

CLIENT_TRANZACTIE

FILM_GEN

FILM_COPII

ANGAJAT

FILM_INCHIRIERE

CLIENT_CONT

FILM_LIMBA

LIMBA

FILM

MPAA_RATING

Figura 1_8. Diagrama entitate relaţie

Page 33: Curs Sinteza SQL

Probleme:

1. Să se normalizeze tabelul CURS_SUDENT şi PROFESOR

Amintim că o tabelă este în prima formă normală(FN1) dacă valorile tuturor

atributelor care o compun sunt atomice (indivizibile). În plus, nu trebuie să existe

atribute sau grupuri de atribute repetitive.

Această primă formă normală este considerată ca fiind o cerinţa minimală

pentru majoritatea sistemelor relaţionale, utilitatea ei fiind evidentă. Astfel , dacă o

coloană ar conţine o listă de valori , regăsirea şi manipularea informaţiilor stocate ar fi

foarte anevoioase.

Presupunem că tabela Curs_Student conţine următoarele date:

CURS_SUDENT

NrMatricol NumeSt PrenumeSt Grupa Cursuri-Nota

458 Predescu Alexandru 114 engleza-7,germana-8

521 Radu George 122 desen-tehnic-10,franceza-7

627 Cristescu Lucian 243 programare-8,engleza-10

746 Irimia Diana 361 analiza numerica-9

782 Tanase Daciela 341 gernana-6,programare-10

982 Bunea Mihaela 114 rezistenta materialelor-8

1204 Dragnea Liviu 412 educatie fizica-10

S1520 Popa Marius 452 analiza numerica-7,engleza-9

Coloana Cursuri conţine mult prea multa informaţie.

Să presupunem că am înlocui coloana Cursuri cu două noi coloane:

CURS_SUDENT

NrMatricol NumeSt PrenumeSt Grupa Curs1 Nota1 Curs2 Nota2

458 Predescu Alexandru 114 engleza 7 germana 8

521 Radu George 122 desen tehnic 10 franceza 7

627 Cristescu Lucian 243 programare 8 engleza 10

746 Irimia Diana 361 analiza numerica 9

782 Tanase Daciela 341 germana 6 programare 10

982 Bunea Mihaela 114

rezistenta

materialelor 8

1204 Dragnea Liviu 412 educatie fizica 10

1520 Popa Marius 452 analiza numerica 7 engleza 9

Nici acum nu am rezolvat toate problemele. De exemplu, pentru a afla câţi

studenti s-au înscris în total la un anumit curs , va trebui să parcurgem toate cele trei

coloane cu cursuri. În plus, ce se întâmplă în cazul în care un student s-a înscris la mai

mult de două cursuri? Să zicem că un student nu se poate inscrie la mai mult de cinci

cursuri şi deci putem introduce zece coloane pentru a stoca informaţiile curs-nota.

.Evident , aceasta ar presupune o mare risipă de spaţiu , de vreme ce ar exista şi unii

studenti care au ales doar două cursuri.

Pentru a aduce tabela Curs_Student la FN1 vom introduce o nouă coloană în

cheia primară a tabelei, astfel încât aceasta va fi formată acum din două coloane:

NrMatricol şi IdCurs. Acum putem afla numărul total de studenţi înscrişi la un

anumit curs.

Page 34: Curs Sinteza SQL

CURS_SUDENT

NrMatricol NumeSt PrenumeSt Grupa IdCurs Denumire

458 Predescu Alexandru 114 4 germana

521 Radu George 122 3 franceza

521 Radu George 122 5 desen tehnic

627 Cristescu Lucian 243 1 programare

627 Cristescu Lucian 243 2 engleza

746 Irimia Diana 361 8 analiza numerica

A doua formă normală (FN2)

Amintim că o tabelă este în a doua formă normală dacă este în FN1 şi fiecare

atribut care nu face parte din cheia primară este dependent de întreaga cheie primară.

Tabela Curs_Student este în FN1, dar nu îndeplineşte cea de-a doua cerinţă

pentru a fi în FN2. Coloana Denumire care depinde numai de IdCurs, nu şi de

NrMatricol , care , împreună cu IdCurs, formează cheia primară. Deci avem o

coloană care nu face parte din cheia primară şi nu depinde de toată cheia, în sensul că

, pentru o valoare dată a lui IdCurs, cunoaştem denumirea cursului fără a mai trebui să

ştim şi NrMatricol. Putem aduce tabelaCurs_Student în FN2 descompunând-o în

două tabele, după următoarea regulă: pentru fiecare dependenţă parţială se formează o

nouă tabelă (pe care o vom numi Curs) conţinând coloanele determinate de această

dependenţa (în acest caz, Denumirea) şi determinantul lor (IdCurs). Coloanele

determinate se elimină din tabela iniţială.

Cheia primară a noii tabele va fi formată din coloanele ce compun

determinantul dependenţei (IdCurs), între cele două tabele rezultate există o relaţie de

tip 1:m asigurată de existenţa lui IdCurs drept cheie străină în tabela Curs_Student.

Analog, deoarece coloanele NumeSt, PrenumeSt şi grupa depind numai de

NrMatricol, le eliminăm din tabela Curs_Student şi formăm o nouă tabelă, Student,

ce le va conţine şi va avea drept cheie primară coloana NrMatricol.

De asemenea , între tabelele Student şi Curs_Student există o relaţie de tip

1:m.

STUDENT

NrMatricol NumeSt PrenumeSt Grupa

458 Predescu Alexandru 114

521 Radu George 122

627 Cristescu Lucian 243

746 Irimia Diana 361

782 Tanase Daciela 341

982 Bunea Mihaela 114

1204 Dragnea Liviu 412

1520 Popa Marius 452

Page 35: Curs Sinteza SQL

CURS_SUDENT

A treia formă normală (FN3)

O tabelă este în a treia formă normală dacă este în FN2 şi toate coloanele care

nu fac parte din cheia primară sunt mutual independente (depind direct de cheia

primară şi numai de ea)

Un exemplu calasic de dependenţă tranzitivă este cel al coloanelor calculate.

Astfel , dacă o tabelă de produse ar conţine Coloanele PretUnitar şi Cantitate şi , în

plus, coloana PretTotal această tabelă nu ar fi în FN3.

Coloanele calculate nu sunt singurul caz de dependenţa tranzitivă într-o

tabelă. De exemplu în tabela Profesor se poate observă faptul că salariul depinde de

titlul profesorului, coloanele Salariu, Titlu şi IdTitlu nefăcând parte din cheia

primară.

Dependenţele tranzitivă creează probleme la adăugarea, actualizarea şi

ştergerea înregistrărilor. De exemplu, dacă la tabela Profesor se mai adaugă 20 de

înregistrări , fiecare cu titlul de preparator (prep), va trebui să introducem de 20 de ori

valoarea 5 pentru IdTitlu, descrierea „preparaotr‖ pentru Titlu şi valoarea 800 pentru

Salariu , ceea ce este evident, redundant. De asemenea, dacă salariul unui preparator

se modifică, va trebui să asctualizăm toate înregistrările corespunzătoare.

Pentru a înlătura toate aceste inconvenienţe, vom aduce tabela Profesor la

FN3 prin crearea unei noi tabele, pe care o vom numi Titlu.Tabela Titlu va avea drept

cheie primară coloana IdTitlu şi va mai conţine coloanele Titlu şi Salariu, pe care le-

am eliminat din tabela Profesor.

Profesor

IdCurs NrMatricol Nota

1 782 5

1 982 10

2 458 7

3 521 7

4 627 8

4 1520 8

5 521 10

5 1740 6

IdProf Nume Catedra IdTitlu

1 Popescu Marin Matematici 1

2 Dragnea Ion Limbi straine 4

3 Iosif Irina Educatie fizica 3

4 Ilie Daniel Informatica 2

5 Savu Cristina Limbi straine 5

6 Cristea George Fizica 3

7 Ene Dan Matematici 7

Page 36: Curs Sinteza SQL

Titlu

:

2. Amintim ca regulile de integritate sunt;

- unicitatea cheii primare

- integritatea entităţii – valorile cheii primare sa fie diferite de valoarea

null(o valoare necunoscuta sau lipseşte)

- integritatea referenţială - o cheie secundară trebuie să fie null în întregime

sau să corespundă unei valori a cheii primare asociate.(in tabela

asociată nu trebuie să existe valori fără corespondent).

Tabelele Titlu şi Profesor sunt în relaţia 1:m (un Titlu corespunde la mai

multe cadre didactice).

Tabele de mai sus păstrează regulile de integritate?

Raspuns Nu, deoarece există cadrul didactic cu IDProf= 7 cu IdTitlu =7 , care

nu există in tabelul Titlu, ca funcţie didactică.

3. Să se determine anomaliile pentru tabelul

Avion

A# nume capacitate localitate

1 AIRBUS 250 PARIS

2 AIRBUS 250 PARIS

3 AIRBUS 250 LONDRA

4 CAR 100 PARIS

5 B707 150 LONDRA

6 B707 150 LONDRA

Constrângere:

toate avioanele cu acelaşi nume au aceeaşi capacitate.

IdCurs Denumire

1 programare

2 engleza

3 franceza

4 germana

5 desen tehnic

6 Rezistenta materialelor

7 Educatie Fizica

8 analiza numerica

IdTitlu Titlu Salariu

1 lector dr. 1300

2 asistent 950

3 lector 1100

4 conferentiar dr. 1700

5 prepartor 680

6 profesor dr. 2150

Page 37: Curs Sinteza SQL

Datorită dependenţei introduse pot exista: anomalii la inserare, modificare sau

ştergere, redundanţă în date, probleme de reconexiune.

1. Redundanţă logică. Cuplul (AIRBUS, 250) apare de trei ori.

2. Anomalie la inserţie. S-a cumpărat un B727 cu 150 locuri. El poate fi

inserat în relaţia AVION doar dacă se defineşte o nouă valoare pentru

cheia primară.

3. Anomalie la ştergere. Dacă este ştearsă înregistrarea pentru care A# este

4, atunci se pierde informaţia că un avion CAR are capacitatea 100.

4. Anomalie la modificare. Dacă se modifică capacitatea lui B707 de la 150

la 170, atunci costul modificării este mare pentru a modifica toate

înregistrările, iar dacă se modifică doar o înregistrare atunci constrângerea

nu va mai fi verificată.

4. Exemplu: variante pentru a implementa FN1 pentru tabelul

MASINA:

Persoana Vehicul

Eu R25 - W14 - R21

Tu 205

El R5 - 305

noi BX - 305 - R12 - R25

Varianta 1

Persoana Vehicul

Eu R25

Eu W14

Eu R21

Tu 205

El R5

El 305

Noi BX

Noi 305

Noi R12

Noi R25

Varianta 2

Persoana Prima Doi Trei Patru

Eu R25 W14 R21

Tu 205

El R5 305

Page 38: Curs Sinteza SQL

Noi BX 305 R12 R25

Varianta 3 (4 tabele)

Masina 31 (similar se definesc Masina_32, Masina_33, Masina_34)..

Persoana Vehicul

Eu R25

Tu 205

El R5

Noi BX

Masina_34

Persoana Vehicul

Noi R25

5. Să se aduca la FN2

O relaţie R este în a doua formă normală dacă şi numai dacă:

relaţia R este în FN1;

fiecare atribut care nu este cheie (nu participă la cheia primară) este

dependent de întreaga cheie primară.

ATASAT_LA

COD_SALARIAT# JOB_COD NR_PROIECT# FUNCTIA SUMA

S1 PROGRAMATOR P1 SUPERVIZOR 60

S1 PROGRAMATOR P2 CERCETATOR 25

S1 PROGRAMATOR P3 AUXILIAR 10

S3 VANZATOR P3 SUPERVIZOR 60

S5 INGINER P3 SUPERVIZOR 60

ATASAT_2A

COD_SALARIAT# NR_PROIECT# FUNCTIA SUMA

S1 P1 SUPERVIZOR 60

S1 P2 CERCETATOR 25

S1 P3 AUXILIAR 10

S3 P3 SUPERVIZOR 60

S5 P3 SUPERVIZOR 60

ATASAT_2B

Page 39: Curs Sinteza SQL

COD_SALARIAT# JOB_COD

S1 PROGRAMATOR

S3 VANZATOR

S5 INGINER

A doua condiţie exprimă necesitatea total dependenţei de cheia

primară. Această formă normală interzice manifestarea unor dependenţe funcţionale

parţiale în cadrul relaţiei R!

Pentru a obţine o relaţie FN2 se poate aplica regula Casey-Delobel.

α β mulţimea atributelor care intervin în dependenţele funcţionale;

α γ reprezintă reuniunea determinantului cu restul atributelor lui A.

7. Tabelul atasat_2a nu este in FN3. De ce?

Forma normală 3 (FN3)

Intuitiv, o relaţie R este în a treia formă normală dacă şi numai dacă:

relaţia R este în FN2;

fiecare atribut care nu este cheie (nu participă la o cheie) depinde direct de

cheia primară.

atasat_3a

Cod_salariat# Nr_proiect# Functia

S1 P1 Supervizor

S1 P2 Cercetator

S1 P3 Auxiliar

S3 P3 Supervizor

S5 P3 Supervizor

atasat_3b

Functia Suma

Supervizor 60

Cercetator 25

Auxiliar 10

8. Presupunem că un şantier poate executa mai multe lucrări de bază şi că

o lucrare poate fi executată de mai multe şantiere.

LUCRARE(cod_obiectiv#, cod_lucrare#, nume);

SANTIER(nr_santier#, specialitate, sef);

EXECUTA(cod_obiectiv#, cod_lucrare#, nr_santier#, descriere, functie,

conducator, data_inceput, data_sfarsit).

Pentru relaţia EXECUTA sunt evidente dependenţele:

{cod_obiectiv#, cod_lucrare#} {data_inceput, data_sfarsit},

{cod_obiectiv#, cod_lucrare#, nr_santier#} {descriere, functie,

conducator}.

9. Să se aduca la FN3 tabelel EXECUTA_1 rezultat de la 8

Page 40: Curs Sinteza SQL

În tabelul EXECUTA_1(cod_obiectiv#, cod_lucrare#, nr_santier#, descriere,

functie, conducator) continuă să existe redundanţă în date.

Atributul conducator depinde indirect de cheia primară prin intermediul

atributului functie.

Între atributele relaţiei există dependenţele:

{cod_obiectiv#, cod_lucrare#, nr_santier#} {descriere},

{cod_obiectiv#, cod_lucrare#, nr_santier#} {functie} {conducator}.

Pentru a aduce relaţia EXECUTA_1 în FN3 se aplică regula Casey- Delobel.

Relaţia se desface, prin eliminarea dependenţelor funcţionale tranzitive, în

proiecţiile:

EXECUTA11(cod_obiectiv#, cod_lucrare#, nr_santier#, descriere, functie)

EXECUTA12(functie, conducator).

10 Să se aducă la forma BCNF (Forma normală Boyce-Codd )

(Formal, o relaţie R este în forma normală Boyce-Codd dacă şi numai dacă

pentru orice dependenţă funcţională totală X A, X este o cheie (candidat) a

lui R.)

Relaţia INVESTESTE_IN leagă entităţile INVESTITOR şi

OBIECTIV_INVESTITIE.

Ea are schema relaţională:

INVESTESTE_IN(cod_contractant#, cod_obiectiv#, nr_contract, cota_parte).

Între atributele relaţiei există dependenţele:

{cod_contractant#, cod_obiectiv#} {nr_contract, cota_parte},

{nr_contract} {cod_obiectiv}.

Se aplică regula Casey-Delobel şi se aduce relaţia în BCNF.

INVESTESTE_IN_1(cod_obiectiv, nr_contract#);

INVESTESTE_IN_2(cod_contractant#, nr_contract, cota_parte).

Page 41: Curs Sinteza SQL

Partea a II-a. LIMBAJUL SQL

În această tema se prezintă conceptele limbajului SQL în 6 lecţii, după cum

urmează:

LECŢIA 1. Concepte SQL

LECŢIA 2. Limbajul de definire a datelor - DDL

LECŢIA 3. Limbajul de interogare a datelor - DQL

LECŢIA 4. Combinarea datelor din mai multe tabele - Uniuni (Join)

LECŢIA 5. Limbajul de manipulare a datelor - DML

LECŢIA 1. Concepte SQL

În acestă lecţie se vor prezenta conceptele de bază ale limbajul SQL.

SQL a devenit limbajul universal pentru bazele de date relaţionale şi este

acceptat de aproape toate sistemele SGBD moderne. Fără îndoială, acceptarea pe

scară largă este rezultatul timpului şi eforturilor depuse pentru dezvoltarea

caracteristicilor limbajului şi a standardelor, crescând nivelul de portabilitate a

codului SQL între diferitele produse RDBMS.

Veţi avea mai multe succes în învăţarea limbajului SQL dacă folosiţi în mod

activ SQL şi o bază de date relaţională pentru a încerca exemplele prezentate sau dacă

veti încerca variante proprii ale exemplelor.

Ce este SQL?

SQL (Structured Query Language -limbaj structurat de interogare) este un

limbaj standard folosit pentru crearea, actualizarea şi regăsirea informaţiilor stocate în

baze de date prin intermediul sistemelor de gestionare a bazelor de date ( SGBD-uri).

Numele limbajului poate fi pronunţat pe litere (es-q-el) sau la fel ca şi

cuvântul englezesc „sequel". O interogare (query) este o simplă cerere transmisă către

baza de date, la care aceasta răspunde într-o anumită formă. SQL este limbajul folosit

cel mai frecvent pentru interogarea bazelor de date. SQL este considerat un limbaj

neprocedural sau declarativ, ceea ce înseamnă că-i spuneţi calculatorului ce rezultate

vreţi, fară să-i spuneţi cum să le obţină. De exemplu, dacă vreţi să obţineţi media

numerelor de pe o coloană, folosiţi funcţia AVG. Nu este nevoie să număraţi valorile

din coloană şi să împărţiţi suma acestora la numărul obţinut - procesorul limbajului

SQL din SGBDse ocupă de toate aceste lucruri în locul dumneavoastră.

Este important să înţelegi că SQL nu este un limbaj procedural, ca C, Pascal,

Basic, FORTRAN, COBOL sau Ada. Un limbaj procedural foloseşte o serie de

instrucţiuni executate secvenţial. De asemenea, limbajele procedurale includ

instrucţiuni care pot modifica secvenţa de execuţie, prin ramificarea la alte porţiuni

ale procedurii sau prin parcurgerea ciclică a unui set de instrucţiuni din procedură.

Mulţi producători de sisteme SGBDoferă extensii procedurale ale limbajului SQL de

bază, cum ar fi Oracle PL/SQL (Procedural Language/SQL) sau Microsoft Transact-

SQL, dar reţineţi că acestea sunt extensii SQL care formează noi limbaje - codul SQL

pe care-1 conţin rămâne neprocedural. De asemenea, SQL nu trebuie confundat cu

limbajele orientate spre obiecte, precum Java şi C++.

Simplu spus, SQL este un limbaj neprocedural pentru gestionarea şi

întreţinerea bazelor de date relaţionale, nu un limbaj potrivit pentru programarea

generală a aplicaţiilor, cum ar fi sistemele de prelucrare a comenzilor sau a plăţilor.

SQL este deseori folosit în combinaţie cu limbajele procedurale sau orientate

spre obiecte menţionate anterior pentru a manipula stocarea şi extragerea datelor,

folosind instrucţiuni din limbajul de programare cu destinaţie generală pentru alte

Page 42: Curs Sinteza SQL

sarcini de programare, precum prezentarea datelor pe o pagină web sau furnizarea

răspunsurilor la informaţiile introduse de utilizatori de la tastatură sau mouse. Atunci

când este necesară interacţionarea cu baza de date, instrucţiunile din limbajul

procedural formează instrucţiunea SQL, o transmit către SGBDîn vederea prelucrării,

primesc rezultatele returnate de SGBDşi le prelucrează într-un mod corespunzător.

Folosind SQL puteţi transforma întrebări obişnuite :‖Din ce oras sunt studentii

notri?‖ în instrucţiuni pe care le înţelege soft-ul pentru baze de date: ―SELECT oras

FROM studenti‖ . Aceste informaţii se pot extrage din bazele de date prin utilizarea

unui instrument grafic de interogare, dar pe măsură ce ce intrebrile devin mai

complexe, aceste instrumente devin limitate şi greoaie şi acesta este momentul când

intră în acţiune limbajul SQL.

SQL se poate folosi nu numai pentru interogare, dar şi pentru a adăuga, a

modifica sau a şterge înregistrări din bazele de date.

Majoritatea SGBD-urilor populare, ca de exemplu Microsoft Accsess, Oracle

şi MySQL , asigură suport pentru SQL, chiar dacă acest nivel de suport diferă de la

produs la produs.

Conectarea la baza de date

Atunci când folosiţi limbajul SQL pe un calculator personal, cu o copie

personală a unui sistem SGBD, precum Microsoft Access sau Oracle Personal

Edition, toate componentele bazei de date rulează pe acelaşi sistem de calcul. Totuşi,

acest aranjament nu este potrivit pentru bazele de date care trebuie să fie folosite în

comun de mai mulţi utilizatori. Ca urmare, sunt mult mai frecvent întâlnite situaţiile

în care baza de date este instalată într-un aranjament client/server.

Într-un aranjament client/server:

• Sistemul rulează pe un server, care este un sistem de calcul partajat. Pentru

scopurile acestei definiţii, un sistem mainframe poate fi considerat un server de

dimensiuni mari.

• Fişierele care compun baza de date din punct de vedere fizic sunt stocate pe

discuri conectate la serverul de baze de date.

• Utilizatorii care au acces la baza de date folosesc staţii de lucru, numite

clienţi. Clientul trebuie să aibă o conexiune de reţea la baza de date, care poate fi o

reţea privată, instalată acasă sau la birou, ori o reţea publică, precum Internet.

• Componentele software furnizate de producătorul SGBD rulează pe staţiile

de lucru alte clienţilor pentru a oferi utilizatorilor posibihtatea să introducă

instrucţiuni SQL, să le transmită sistemului SGBD în vederea prelucrării şi sa vadă

rezultatele returnate de DBMS. în general, acest software se numeşte cbent SQL.

Reţineţi că nimic nu vă opreşte să instalaţi clientul SQL pe acelaşi calculator

cu sistemul DBMS. De fapt, mulţi dezvoltatori care utilizează sisteme SGBD precum

MySQL, Microsoft SQL Server şi Oracle fac în mod obişnuit acest lucru, deoarece

este foarte convenabil să aibă întregul mediu de dezvoltare pe un singur calculator,

cum ar fi un laptop. Totuşi, în momentul în care este necesar accesul partajat al mai

multor utilizatori, este mult mai convenabil şi mai eficient să aveţi o singură copie a

sistemului SGBD pe un server partajat şi să aveţi numai clientul SQL instalat pe staţia

de lucru a fiecărui client.

În funcţie de interfaţa cu utilizatorul de pe staţia de lucru client, clienţii SQL

sunt clasificaţi în trei categorii: în linia de comandă, grafici şi bazaţi pe web. O

interfaţă în linia de comandă se bazează exclusiv pe intrări şi ieşiri de tip text, cu

comenzile introduse de la tastatură şi răspunsurile afişate ca mesaje de tip text.

Page 43: Curs Sinteza SQL

Principalul avantaj al interfeţelor în linia de comandă este că pot fi rulate pe aproape

orice sistem de operare. O interfaţă grafică cu utilizatorul (GUI - graphical user

interface) rulează sub un tip oarecare de sistem bazat pe ferestre, cum ar fi X Window

System, Mac OS sau Microsoft Windows, şi afişează datele sau opţiunile comenzilor

folosind elemente grafice, precum pictograme, butoane şi casete de dialog. O interfaţă

bazată pe web rulează pe serverul de baze de date, folosind un browser web de pe

staţia de lucru client pentru a interacţiona cu utilizatorul bazei de date. Din punct de

vedere tehnic, un client SQL bazat pe web nici nu este o aplicaţie client, deoarece nu

există nici o componentă software specifică producătorului SGBD rulată pe staţia de

lucru a clientului. Totuşi, aproape întotdeauna există componente furnizate de

producătorul SGBDcare sunt descărcate în fundal de browser-ul web pentru a asista în

procesul de reprezentare grafică a formularelor web folosite pentru introducerea

instrucţiunilor SQL şi afişarea rezultatelor.

Tabelul următor prezintă clienţi SQL oferiţi de diferiţi producători SGBD . Nu

avem suficient spaţiu în această carte pentru a prezenta toate detaliile referitoare la

fiecare client SQL pe care aţi putea să-1 folosiţi, aşa că vă rog să consultaţi

documentaţia producătorului SGBD pentru informaţii despre instalarea şi utilizarea

clienţilor SQL disponibile pentru sistemul SGBD pe care-1 folosiţi.

Producător DBMS Client SQL Descriere

Microsoft Access Nu există

Microsoft Access este o bază de date de

uz personal, cu clientul SQL integrat în

DBMS, toate fiind rulate local pe staţia

de lucru a utilizatorului.

Microsoft SQL Server iSQL

Client SQL care rulează ca aplicaţie în

linia de comandă într-un nucleu de

comenzi Microsoft Windows.

Microsoft SQL Server Query

Analyzer

Client SQL care rulează ca

aplicaţie Microsoft Windows.

MySQL MySQL MySQL

Client SQL care rulează ca

aplicaţie în linia de comandă

sub diferite sisteme de operare,

inclusiv Microsoft Windows,

Linux, Mac OS X şi diferite

implementări Unix.

Oracle Oracle iSQL*Plus

Client SQL bazat pe web -

acceptat în versiunile Oracle 9i

si mai noi.

Oracle Oracle SQL*Plus

Client SQL care rulează ca

aplicaţie Microsoft Windows sau

ca aplicaţie în linia de comandă

Page 44: Curs Sinteza SQL

sub diferite sisteme de operare,

inclusiv Microsoft Windows,

Linux, Mac OS X, diferite

implementări Unix şi altele.

Oracle Oracle SQL

Worksheet

Client SQL scris în Java -

disponibil în Oracle 8i şi 9i, dar

înlocuit de iSQL*Plus în Oracle

10g.

Sybase Sybase iSQL

Clientul SQL care rulează ca

aplicaţie în linia de comandă

într-un nucleu de comenzi

Microsoft Windows. Asemănările

cu Microsoft SQL Server nu

sunt întâmplătoare - primele

versiuni Microsoft SQL Server

erau bazate pe sistemul

SGBDSybase.

Un scurt istoric al limbajului SQL

Către sfârşitul anilor '70, un grup de cercetători de la IBM au dezvoltat o bază

de date relaţională, numită System/R, bazată pe lucrările Dr. E. F. Codd. în System/R a

fost inclus un limbaj, numit SEQUEL (Structured English Query Language), pentru

manipularea şi extragerea datelor. Acronimul „SEQUEL" a fost ulterior condensat în

abrevierea „SQL", atunci când s-a descoperit că „SEQUEL" era marcă înregistrată a

companiei Hawker-Siddeley Aircraft din Marea Britanie.

Deşi IBM a creat prima implementare SQL, două alte produse, cu nume

diferite pentru limbajele de interogare, au fost lansate pe piaţă ca primele produse

pentru baze de date relaţionale, Oracle, furnizat de Relational Software, şi INGRES,

furnizat de Relational Technology. IBM a lansat în 1982 produsul SQL/DS, cu

limbajul de interogare numit acum SQL (Structured Query Language). Dacă

programarea structurată era expresia la modă în anii '80, cuvântul „structured" din

SQL nu avea nici o legătură cu programarea structurată, deoarece SQL nu este un

limbaj de programare procedural.

Comitetele de standardizare a limbajului SQL au fost formate de ANSI

(American National Standards Institute) în 1986 şi ISO (International Organization

for Standardization) în 1987. Din fericire, comitetele create de cele două organizaţii

au colaborat pentru dezvoltarea unui standard SQL comun, la nivel mondial. Doi ani

mai târziu, au fost publicate primele specificaţii ale standardului, numite SQL-89.

După trei ani, specificaţiile originale au fost extinse, sub forma standardului SQL-92,

care avea aproximativ 600 de pagini. A treia generaţie a fost numită SQL-99 sau

SQL3. Cele mai multe produse SGBDsunt construite pe baza standardului SQL-92

Page 45: Curs Sinteza SQL

(numit acum SQL2). SQL3 include multe caracteristici obiectuale, necesare pentru

folosirea limbajului SQL cu o bază de date relaţională orientată spre obiecte, precum

şi extensii de limbaj care fac din SQL un limbaj de programare complet (adăugând

cicluri, ramificări şi construcţii de comutare, de tip case). Cea mai recentă generaţie,

numită SQL:2003, introduce caracteristici legate de XML şi alte îmbunătăţiri. Aceste

standarde nu sunt gratuite. Standardul SQL:2003 poate fi cumpărat de la ISO

(www.iso.org) sau ANSI (webstore.ansi.org). Pentru cei care au un buget mai

restrâns, este disponibilă o versiune apropiată de cea finală la Whitemarsh

Information Systems Corporation (www.wiscorp.com/SQLStandards.html). Aproape

toţi furnizorii au adăugat extensii la „dialectul" SQL propriu, în parte deoarece doreau

să diferenţieze produsele proprii şi în parte deoarece cerinţele pieţei îi forţau să

implementeze caracteristici înainte a apărea standarde pentru acestea.

Un astfel de exemplu este acceptarea tipurilor de date TIMESTAMP şi DATE.

Datele calendaristici sunt foarte importante pentru prelucrarea datelor comerciale, dar

dezvoltatorii produselor SGBD originale erau academicieni şi oameni de ştiinţă, nu

specialişti în prelucrări comerciale, aşa că această cerinţă nu a fost anticipată. Ca

rezultat, primele dialecte SQL nu asigurau un suport special pentru datele

calendaristice. Pe măsură ce au apărut produsele comerciale, furnizorii au răspuns

cererilor lansate de clienţii importanţi şi au adăugat în grabă suportul pentru date

calendaristice. Din nefericire, din cauza grabei fiecare a făcut-o în felul propriu. Ori

de câte ori migraţi instrucţiuni SQL de la produsul unui furnizor la altul, ţineţi seama

de diferenţele dintre dialecte. Codul SQL este foarte compatibil şi portabil între

produsele diferiţilor furnizori, dar sistemele complete de baze de date pot fi rareori

transferate fară anumite ajustări.

Convenţii de sintaxă SQL

Această secţiune prezintă convenţiile generale de sintaxă folosite pentru

construia instrucţiunilor SQL. Totuşi, reţineţi că există o mulţime de extensii şi

variaţii între diferiţii producători. Pentru simplitate, termenul implementare este

folosit pentru referirea fiecărei versiuni SQL a fiecărui producător (cu alte cuvinte,

Oracle 9i, Oracle 10g, Microsoft SQL Server 7, Microsoft SQL Server 2000 şi

Microsoft SQL Server 2005 conţin implementări diferite ale limbajului SQL).

Convenţiile de sintaxă SQL sunt mai uşor de înţeles folosind un exemplu

simplu Instrucţiunea de mai jos returnează valorile Movie ID şi Movie Title pentru

toate filmele din magazinul de produse video pentru care categoria MPAA este „PG":

SELECT FILM_ID, TITLU_FILM

FROM FILM

WHERE MPAA_RATING_COD = 'PG';

Convenţiile de bază sunt următoarele:

• Fiecare instrucţiune începe cu o comandă, de obicei sub forma unui singur

cuvânt, care aproape întotdeauna este un verb (în limba engleză) care descrie o

acţiune. în acest exemplu, instrucţiunea începe cu comanda SELECT, care este

descrisă în detaliu în lecţia 3.

• Fiecare instrucţiune se termină cu un delimitator, care este, de obicei, un

caracter punct şi virgulă (;). Unele implementări permit schimbarea delimitatorului cu

un alt caracter. Mai mult, unele implementări, cum ar fi cea din Oracle, nu execută o

instrucţiune SQL căreia-i lipseşte delimitatorul de sfârşit, în timp ce alte implementări

consideră acest delimitator opţional.

Page 46: Curs Sinteza SQL

• Instrucţiunile sunt construite într-o manieră similară cu propoziţiile din limba

engleză, cu unul sau mai multe spaţii pentru separarea elementelor de limbaj. Un

element de limbaj, asemănător cu un cuvânt dintr-o propoziţie, poate fi un cuvânt

cheie (SELECT, FROM, WHERE), numele unui obiect al bazei de date (FILM,

FILM_ID, TITLU_FILM), un operator (=) sau o constantă ('PG') care apare într-o

instrucţiune.

• Instrucţiunile sunt scrise într-o formă liberă, ceea ce înseamnă că nu există

reguli stricte privind poziţia elementelor de limbaj pe o linie sau locul în care se poate

face trecerea la o linie nouă. Totuşi, în general nu este o idee bună să împărţiţi un

element de limbaj pe mai multe linii. Din punct de vedere logic, instrucţiunea de mai

jos este identică cu cea prezentată la începutul acestei secţiuni, dar nu este la fel de

uşor de citit şi de înţeles:

SELECT FILM_ID, TITLU_FILM FROM FILM WHERE

MPAA_RATING_COD ='PG';

• Instrucţiunile sunt organizate într-o serie de clauze şi, de obicei, clauzele

trebuie să apară într-o anumită ordine atunci când sunt folosite (multe clauze sunt

opţionale). în exemplul nostru, există trei clauze, fiecare începând cu un cuvânt cheie

(SELECT, FROM, WHERE).

• Elementele de limbaj SQL pot fi scrise cu litere mari, cu litere mici sau în

combinaţii. Totuşi, în majoritatea implementărilor şi în conformitate cu standardele

ANSI/ISO, toate minusculele sunt transformate în majuscule în vederea prelucrării.

Aceasta nu înseamnă că datele nu pot conţine litere mici, ci că numele obiectelor din

baza de date (tabele, coloane etc.) şi comenzile trebuie să fie scrise cu litere mari.

Excepţii notabile sunt Microsoft SQL Server şi Sybase, care permit modul de lucru cu

diferenţierea literelor mari de cele mici, caz în care numele de obiecte scrise diferit

sunt tratate ca nume diferite. în MySQL, diferenţierea literelor mari de cele mici în

numele obiectelor este legată de capacitatea sistemului de operare de a face această

diferenţiere.

• Virgulele sunt folosite pentru separarea articolelor dintr-o listă. în exemplul

nostru, numele a două coloane sunt specificate într-o listă separată prin virgule

(FILM_ID, TITLU_FILM). Spaţiile care urmează după virgule sunt opţionale - puteţi

adăuga orice număr de spaţii, inclusiv zero.

• Şirurile de caractere care apar în instrucţiunile SQL trebuie să fie încadrate

cu apostrofuri (unele implementări SQL permit şi folosirea ghilimelelor). Constantele

numerice nu sunt niciodată încadrate cu apostrofuri. Dacă în şirul de caractere trebuie

să apară un caracter apostrof, sunt inserate două apostrofuri unul lângă celălalt. De

exemplu, dacă vreţi să găsiţi în baza de date un film numit Sophie's Choice, veţi scrie

clauza WHERE astfel:

WHERE TITLU_FILM = 'Sophie''s Choice'

• Numele obiectelor bazei de date sunt formate folosind numai litere, cifre şi

liniuţe de subliniere. Caracterul underscore (liniuţa de subliniere) este folosit, de

obicei, ca separator între cuvinte, pentru îmbunătăţirea lizibilităţii. Aşa cum am

menţionat anterior, unele implementări permit folosirea numelor care fac diferenţa

între literele mari şi cele mici, cum ar fi PersonMiddleName, un stil numit deseori

„scriere de tip cămilă", dar acest stil nu este recomandabil dacă doriţi ca instrucţiunile

SQL să fie portabile pe alte implementări. în definitiv, un nume precum

„PERSONMIDDLENAME" nu este foarte uşor de citit.

• In fiecare implementare SQL este definit un set de cuvinte rezervate, care

sunt cuvinte cu o semnificaţie specifică pentru procesorul SQL al sistemului SGBD şi,

Page 47: Curs Sinteza SQL

care urmare, nu trebuie folosite într-un alt context - de exemplu ca nume pentru

obiectele bazei de date. Scopul acestei restricţii este de a evita interpretarea greşită a

instrucţiunilor SQL de către SGBD. Aşa cum probabil bănuiţi, lista cuvintelor

rezervate diferă semnificativ de la o implementare SQL la alta, aşa că este bine să

consultaţi documentaţia implementării pe care o folosiţi pentru a vă familiariza cu

aceste cuvinte.

• Un comentariu pe o singură linie începe cu două liniuţe de despărţire (--).

Cele două liniuţe se pot afla la începutul unei linii, ceea ce înseamnă că întreaga linie

este considerată comentariu, sau oriunde în cadrul liniei, caz în care restul liniei, până

la sfârşit, este considerat comentariu. De exemplu:

-- Acesta este un comentariu pe o singură linie în SQL.

• Un comentariu pe mai multe linii începe cu combinaţia dintre o diagonală la

dreapta (slash) şi un asterisc (/*) şi continuă până la întâlnirea combinaţiei invers (*/).

Aveţi grijă să terminaţi corect comentariile, altfel multe linii SQL pe care le-aţi scris

vor fi tratate de către SGBDca şi cum ar fi comentarii. Iată un exemplu de comentariu

pe mai multe linii:

/* Acesta este un comentariu pe mai multe linii.

Continuă până la întâlnirea combinaţiei de caractere care marchează sfârşitul

comentariului. */

Categorii de instrucţiuni SQL

Instrucţiunile SQL sunt împărţite în categorii, după funcţiile pe care le

îndeplinesc. Unii experţi consideră aceste categorii ca fiind limbaje separate sau

sublimbaje. Totuşi, în SQL acestea au aceeaşi sintaxă de bază şi respectă aceleaşi

reguli, aşa că eu le consider categorii de instrucţiuni din acelaşi limbaj.

Categoriile de instrucţiuni, descrise în secţiunile următoare, sunt:

• Limbajul de definire a datelor (DDL - Data Definition Language)

• Limbajul de interogare a datelor (DQL - Data Query Language)

• Limbajul de manipulare a datelor (DML - Data Manipulation Language)

• Limbajul pentru controlul datelor (DCL - Data Control Language)

Limbajul de definire a datelor (DDL)

Limbajul de definire a datelor (DDL - Data Definition Language) include

instrucţiuni SQL care permit utilizatorului bazei de date să creeze şi să modifice

structura obiectelor bazei de date, cum ar fi tabele, vizualizări şi indexuri.

Instrucţiunile SQL care folosesc comenzile CREATE, ALTER şi DROP sunt

considerate parte a DDL. Este important să înţelegeţi că instrucţiunile DDL afectează

containerele care stochează datele în baza de date, nu datele propriu-zise. Ca urmare,

există instrucţiuni DDL pentru crearea, ştergerea şi modificarea tabelelor, dar nici una

dintre aceste instrucţiuni nu oferă posibilitatea de a crea sau modifica rânduri de date

din tabelele respective. Instrucţiunile DDL sunt prezentate în capitolul 3.

Limbajul de interogare a datelor (DQL)

Limbajul de interogare a datelor (DQL - Data Query Language) include

instrucţiuni SQL care permit obţinerea datelor din baza de date. Deşi reprezintă o

parte foarte importantă a limbajului SQL, DQL este format din instrucţiuni care

Page 48: Curs Sinteza SQL

folosesc o singură comandă: SELECT. Unii furnizori şi autori clasifică instrucţiunile

DQL şi DML în aceeaşi categorie.

Limbajul de manipulare a datelor (DML)

Limbajul de manipulare a datelor (DML - Data Manipulation Language)

include instrucţiuni SQL care permit utilizatorului bazei de date să adauge date în

baza de date (sub forma rândurilor din tabele), să şteargă date şi să modifice datele

existente în baza de date. Instrucţiunile SQL care folosesc comenzile INSERT,

UPDATE şi DELETE sunt considerate parte a DML.

Limbajul pentru controlul datelor (DCL)

Limbajul pentru controlul datelor (DCL – Data Control Language) include

instrucţiuni SQL care permit administratorilor să controleze accesul la datele din baza

de date şi folosirea diferitelor privilegii ale sistemului DBMS, cum ar fi privilegiul de

oprire şi pornire a bazei de date. Instrucţiunile SQL care folosesc comenzile GRANT

si ALTER sunt considerate parte a DCL.

Comenzile pentru controlul tranzacţiilor O tranzacţie în baza de date este un set de comenzi pe care utilizatorul bazei

de date vrea sa le trateze ca pe o unitate funcţionala de tip „totul sau nimic‖,

întelegând prin aceasta că intreaga tranzactie trebuie sa reuseasca sau sa esueze.

Comenzile pentru cotrolul tranzacţiilor (Transaction Control Commands ) nu respectă

cu exactitate sintaxa instrucţiunilor SQL , dar afecteaza puternic comportamentul

instructiuunilor SQL incluse în tranzacţii.

Întrebări

Alegeţi răspunsurile corecte pentru fiecare din următoarele întrebări cu

răspunsuri multiple. Întrebările pot avea mai multe răspunsuri corecte.

1. SQL este

a. Un limbaj orientat spre obiecte

b. Un limbaj procedural

c. Un limbaj nonprocedural

d. Un limbaj declarativ

e. Un limbaj standard

2. Într-un aranjament client/server

a. Componentele software DBMS ruleaza pe server

b. Componentele software DBMS ruleaza pe client

c. Componentele software ale clientului SQL ruleaza pe client

d. Componentele software ale clientului SQL ruleaza pe server

3. Un client SQL in linia de comanda

a. Necesita un sistem bazat pe ferestre

b. Ruleaza pe o mare varietate de platforme client.

Page 49: Curs Sinteza SQL

c. Necesita un browser web pe client.

d. Afişează datele şi opţiunile de comandă folosind caracteristici grafice

e. Afişează răspunsurile la comenzi sub formă de mesaje de tip text

4. Un client SQL cu interfata grafica (GUI)

a. Necesita un sistem bazat pe ferestre

b. Ruleaza pe o mare varietate de platforme client.

c. Necesita un browser web pe client.

d. Afişează datele şi opţiunile de comandă folosind caracteristici grafice

e. Afişează răspunsurile la comenzi sub formă de mesaje de tip text

5. Un client SQL bazat pe web

a. Necesita un sistem bazat pe ferestre

b. Ruleaza pe o mare varietate de platforme client.

c. Necesita un browser web pe client.

d. Afişează datele şi opţiunile de comandă folosind caracteristici grafice

e. Afişează răspunsurile la comenzi sub formă de mesaje de tip text

6. Clienţii SQL oferiţi de Oracle sunt

a. iSQL

b. Query Analyzer

c. iSQL*Plus

d. SQL*Plus

e. SQLWorksheet

7. Clienţii SQL oferiţi de Microsoft sunt

a. iSQL

b. Query Analyzer

c. iSQL*Plus

d. SQL*Plus

e. SQLWorksheet

8. Extensiile SQL create de furnizori

a. Cresc portabilitatea codului SQL

b. Scad portabilitatea codului SQL

c. Contribuie la diferenţierea produselor oferire de diferiţi producători

d. Au fost bazate pe cererile pieţei

e. Sunt compatibile între implementările diferiţilor producători

9. Instrucţiunile SQL

a. încep cu un cuvânt cheie reprezentând o comandă

b. Se termină cu un cuvânt cheie reprezentând o comandă

c. încep cu un delimitator, cum ar fi caracterul punct şi virgulă

d. Se termină un delimitator, cum ar fi caracterul punct şi virgulă

e. încep cu o paranteză deschisă

10. Elementele limbajului SQL includ

a. Cuvinte cheie

b. Nume ale obiectelor din baza de date

c. Operatori

Page 50: Curs Sinteza SQL

d. Restricţii

e. Constante

11. Elementele limbajului SQL sunt separate prin

a. Virgule

b. Exact un spaţiu

c. Unul sau mai multe spaţii

d. Linie nouă

e. Liniuţe de subliniere

12. Numele obiectelor bazei de date pot include

a. Paranteze

b. Liniuţe de subliniere

c. Numere

d. Litere

e. Virgule

13. Instrucţiunile SQL pot li împărţite în următoarele categorii

a. Limbajul dc definire a datelor (DDI, - Data Definition Language)

b. Limbajul dc selectare a datelor (DSL - Dala Selection Language)

c. Limbajul dc replicare a datelor (DRL - Dala Replication Language)

d. Limbajul pentru controlul datelor (DCL - Data Control Language)

e. Limbajul dc manipulare a datelor (DML - Data Manipulation Language)

14. Limbajul de definire a datelor (DDL - Data Definition Language) include

următoarele instrucţiuni:

a. SELECT

b. INSERT

c. CREATE

d. ALTER

e. DELETE

15. Limbajul de interogare a datelor (DQL - Data Query Language) include

următoarele instrucţiuni:

a. SELECT

b. INSERT

c. CREATE

d. UPDATE

e. DELETE

16. Limbajul de manipulare a datelor (DML - Data Manipulation Language)

include următoarele instrucţiuni:

a. SELECT

b. INSERT

c. CREATE

d. UPDATE

e. DELETE

Page 51: Curs Sinteza SQL

LECŢIA 2. Limbajul de definire a datelor - DDL

Se vor prezenta în continuare instrucţiunile SQL folosite pentru definirea şi

gestionarea obiectelor dintr-o bază de date relaţională. Instrucţiunile CREATE,

ALTER şi DROP formează o categorie a limbajului SQL numită limbaj de definire a

datelor (DDL– Data Definition Language).

Se prezintă DDL înaintea DQL, DML deoarece trebuiesc create

obiectele bazei de date înainte de a insera date în baza de date.

Convenţii de sintaxă

Instrucţiunile SQL DDL au mai multe opţiuni decât alte instrucţiuni SQL.

Următoarele convenţii sunt pentru a prezenta sintaxa instrucţiunilor DDL:

Cuvintele cheie şi cuvintele rezervate din SQL sunt scrise cu majuscule, cum

ar fi CREATE TABLE.

Informaţiile pe care ar trebui să fie furnizate la scrierea instrucţiunilor sunt

scrise cu italic, cum ar fi nume_coloană.

Elementele opţionale sunt încadrate în paranteze pătrate, cum ar fi [WITH

TIME ZONE].

Opţiunile dintr-o listă de elemente posibile sunt separate de o bară verticală

(simbolul logic pentru „sau"), cum ar fi TABLE | VIEW | INDEX. Se pot întâlni

uneori ca listă de elemente opţionale, cum ar fi [NULL | NOT NULL].

Elementele de grup care sunt explicate sau analizate ulterior pe componente

(de obicei după descrierea unui tip principal de instrucţiune) sunt încadrate de

caracterele „mai mic decât" şi „mai mare decât", cum ar fi

<specificaţii_pentru_coloană>.

Un element care se poate repeta este urmat de trei puncte, cum ar fi.

[,<restricţie_pentru_tabel>...].

Toate celelalte simboluri, în special virgulele şi parantezele, fac parte din

sintaxa SQL obligatorie şi, ca urmare, trebuie să fie incluse aşa cum sunt scrise aici.

Tipuri de date

O coloană este cea mai mică unitate denumită care poate fi referită într-o bază

de date relaţională. Fiecare, coloană trebuie să aibă asociate un nume unic şi un tip de

date. Un tip de date este o categorie pentru formatul folosit de o anumită coloană.

Tipurile de date asigură câteva avantaje importante:

Restricţionarea, datelor din coloana respectivă la caracterele care au sens

pentru tipul de date specificat.

Asigurarea unor comportamente utile pentru utilizatorul datelor. De exemplu,

dacă se scade un număr dintr-un alt număr, se obţine ca rezultat un număr; dar dacă se

scade o dată dintr-o altă dată, se obţine ca rezultat diferenţa în zile dintre cele două

date calendaristice.

Creşterea eficienţei sistemului SGBD la stocarea datelor din coloane.

SQL acceptă trei categorii de tipuri de date: tipuri predefinite, tipuri construite

şi tipuri definite de utilizator.

Page 52: Curs Sinteza SQL

Tipurile de date predefinite sunt cele furnizate de către producător ca parte

nativă a sistemului SGBD(vor fi tratate în continuare).

Tipurile de date construite, cunoscute şi ca tipuri de colecţii, conţin matrice

sau seturi de tipuri de date predefinite, în scopul reprezentării în SGBD a

construcţiilor de date orientate spre obiect.

Tipurile de date definite de utilizator permit utilizatorului bazei de date să

definească propriile tipuri de date, adaptate unor scopuri specifice.

Ultimele două tipuri de date nu vor fi tratate , fiind prea complicate

pentru intenţiile cursului.

Tipuri de date predefinite din standardul SQL:2003

Se vor prezenta fiecare tip de date în secţiuni separate, pentru evitarea

confuziilor.

Tipuri de date pentru caractere

Tipurile de date pentru caractere conţin şiruri de caractere, adică litere,

cifre şi alte simboluri permise de sistemul de calcul pe care se află baza de date.

Tipurile de date stardard pentru caractere sunt:

Caracter cu lungime fixă - Un şir de caractere cu lungime finită. Sintaxa

SQL este:

CHARACTER(lungime) | CHAR(lungime)

Exemplu: NUMAR_SECURITATE CHAR(9)

Caracter naţional - Acest tip de date poate fi folosit pentru t raducerea

şirur ilor de caractere în difer ite limbi. Sintaxa SQL este :

NATIONAL CHARACTER(lungime) | NCHAR(lungime)

Exemplu: TITLU_FILM NCHAR(100)

Caracter variabil - Un şir de caractere cu lungime variabilă, specificând

lungimea maximă a şirurilor de caractere stocate. Sintaxa SQL este:

CHARACTER VARYING(lungime_maximă) |

VARCHAR(lungime_maximă)

Exemplu: NUME_CLIENT VARCHAR(125)

Caracter naţional variabil – O variantă a tipului de date pentru şiruri de

caractere cu lungime variabilă, stocata într-un set de caractere al unei anumite limbi.

Sintaxa SQL este:

NATIONAL CHARACTER VARYING( lu ng ime_ ma x imă ) |

NVARCHAR (lungime_maximă)

Exemplu: TITLU_FILM NVARCHAR(100)

Tipuri de date numerice

Acestea sunt utile mai ales pentru atributele folosite în calcule. Toate tipurile

numerice au o precizie (un număr de cifre). De asemenea unele tipuri numerice au şi o

scală (numărul de cifre aflate în dreapta punctului zecimal). Tipurile întregi şi tipurile

numerice care include o scală sunt numite numerice exacte, în timp ce numerele reale

care nu include o scală (numerele cu virgulă mobilă) sunt numite numerice

aproximative.

Tipurile numerice standard sunt:

Numeric - Un tip numeric exact care include o precizie şi o scalã.

Sintaxa SQL este:

NUMERIC (precizie, scală)

Exemplu: PLATA_PE_ORA_ANGAJAT NUMERIC(5,2)

Page 53: Curs Sinteza SQL

Zecima1 - Un tip numeric exact care include o precizie şi o scală.

Sintaxa SQL este:

DECIMAL(precizie, scală)

Exemplu: PLATA_PE_ORA_ANGAJAT DECIMAL(5,2)

Întreg - Un tip numeric exact care include numai precizia, scris INTEGER sau

INT. Numerele întregi nu au cifre zecimale, aşa că scala nu este necesară, deoarece

este întotdeauna zero. Sintaxa SQL este:

INTEGER (precizie) | INT (precizie)

Exemplu: ID_CONT_CLIENT INTEGER

Întreg mic - O variantă a tipului INTEGER, scrisă SMALLINT, care

stochează numere mai mici şi, ca urmare, ocupă mai puţin spaţiu.

Sintaxa SQL este:

SMALLINT (precizie)

Exemplu: ID_CONT_CLIENT SMALLINT

Întreg mare - O variantă a tipului INTEGER, scrisă BIGINT, care stocheză

numere mai mari şi ocupă mai mult spaţiu. Sintaxa SQL este:

BIGINT (precizie)

Exemplu: ID_CONT_CLIENT BIGINT

Număr în virgulă mobilă - Un tip numeric aproximativ, cu precizia mai mare

sau egală cu precizia specificată. Specificarea preciziei este opţională. Este scrisă

FLOAT. Sintaxa SQL este:

FLOAT (precizie)

Exemple: RATA_DOBANDA FLOAT(16)

RATA_DOBANDA FLOAT

Număr real - Un tip numeric aproximativ, cu precizie definită de

implementare. Sintaxa SQL este:

REAL

Exemplu: RATA_DOBANDA REAL

Număr real cu precizie dublă - Un tip numeric aproximativ, cu precizie

definită de implementare, dar mai mare sau egală cu precizia definită pentru

tipul REAL. Sintaxa SQL este:

DOUBLE PRECISION | DOUBLE

Exemplu: RATA_DOBANDA DOUBLE PRECISION

Tipuri de date temporale Aceste tipuri (numite şi tipuri pentru date şi ore) stochează date care

măsoară timpul, într-un mod oarecare.

Tipurile de date temporale conţin următoarele componente, numite de

standard, câmpuri (fields) :

Numele câmpului (cuvânt cheie

SQL) Definiţie

YEAR Anul calendaristic, pe două sau

patru cifre

MONTH Luna din an

DAY Ziua din lună

HOUR Ora din zi

MINUTE Minutul din oră

SECOND Secunda din minut

TIMEZONE_HOUR Valoarea orei cu diferenţa de

fus orar

Page 54: Curs Sinteza SQL

TIMEZONE_MINUTE Valoarea minutului cu diferenţa

de fus orar

Câmpurile TIMEZONE_HOUR şi TIMEZONE_MINUTE sunt incluse în

toate tipurile de date temporale pentru care este specificat cuvântul cheie WITH

TIMEZONE.

Tipurile de date temporale sunt:

Data - O dată calendaristică, incluzând câmpurile YEAR, MONTH şi DAY.

Sintaxa SQL este:

DATE [WITH TIMEZONE]

Exemplu: DATA_INSCRISA DATE

Ora - Un tip de date pentru oră, incluzând câmpurile HOUR, MINUTE şi

SECOND. Sintaxa SQL este:

TIME [WITH TIMEZONE]

Exemplu: TIMPUL_INSCRIS TIME

Marcă temporală - Un tip de date combinat pentru dată şi oră, incluzând

câmpurile YEAR, MONTH, DAY, HOUR, MINUTE şi SECOND. Sintaxa SQL este:

TIMESTAMP [WITH TIMEZONE]

Exemplu: DATA_TIMP_ INSCRIS TIMESTAMP

Interval - Un interval de timp, incluzând câmpurile specificate printr-un

calificator de interval (internal qualifier), care reprezintă precizia intervalului.

Sintaxa SQL este:

INTERVAL câmp_de_start TO câmp_de_sfârşit|INTERVAL câmp

Exemple: TIMP_LUCRU INTERVAL HOUR TO MINUTE

ZILE_INCHIRIERE INTERVAL DAY

Tipuri de date pentru obiecte mari Obiectele mari permit stocarea unor date care depăşesc cu mult posibilităţile

de stocare ale tipurilor de date prezentate până acum, ajungând deseori la

dimensiuni de câţiva megaocteţi. Deoarece manipularea obiectelor mari este

un subiect avansat, care nu vace obiectul cursului, se vor prezenta aceste tipuri

fără sintaxa lor.

Obiect mare pentru caractere - Un obiect mare pentru caractere, scris în SQL

sub foma CLOB.

Obiect mare pentru caractere, în format naţional - Un obiect mare pentru

caractere, stocat într-o anumită limbă, scris în SQL sub forma NLOB.

Obiect mare binar - Un obiect mare care conţine date binare, cum ar fi o

imagine sau o secvenţă sonoră, scris în SQL sub forma BLOB.

Un alt tip de date

Există un tip standard de date care nu este încadrat în nici una dintre

categoriile prezentate anterior:

Boolean - Stochează o valoare logică adevărat sau fals. Sintaxa SQL este:

BOOLEAN

Exemplu: CLIENT_PREFERAT BOOLEAN

Page 55: Curs Sinteza SQL

Oracle

Oracle SQL acceptă următoarele tipuri de date standard:

BLOB - Obiecte binare mari, cu dimensiunea maximă de (4GB-1) x

(dimensiunea unui bloc din baza de date).

CHAR - Şiruri de caractere cu lungime fixă, conţinând cel mult 2000 de

octeţi.

CLOB - Obiecte de tip caracter mari, cu dimensiunea maximă de (4GB- 1) x

(dimensiunea unui bloc din baza de date).

DATE - Funcţionează ca tipul standard de date DATE, dar din punct de vedere

tehnic seamănă mai mult cu tipul DATETIME, deoarece poate stoca atât data, cât şi

ora. Acceptă date de la 1 ianuarie 4712 î.e.n. la 31 decembrie 9999 e.n.

Opţional, poate fi inclusă şi ora, în ore, minute şi secunde. Dacă partea opţională este

omisă, este stocată cu valoarea zero, echivalentă cu miezul nopţii.

DECIMAL - Implementat ca NUMBER(precizie,scală).

DOUBLE PRECISION - Implementat ca NUMBER.

FLOAT - Implementat ca NUMBER.

INTEGER - Implementat ca NUMBER(38).

INTERVAL - Un interval de timp, dar sunt acceptate din standard numai

variantele INTERVAL YEAR TO MONTH şi INTERVAL DAY TO SECOND.

NCHAR - Şiruri de caractere cu lungime fixă într-o limbă naţională, cu

dimensiunea maximă de 2000 de octeţi.

NCLOB - Şiruri de caractere cu lungime fixă într-o limbă naţională, cu

dimensiunea maximă de (4GB-1) x (dimensiunea unui bloc din baza de date).

NUMERIC - Implementat NUMBER(precizie,scală).

NVARCHAR - Date de tip caracter cu lungime variabilă într-o limbă

naţională, cu dimensiunea maximă de 4000 de octeţi .

REAL - Implementat ca NUMBER.

SMALLINT - Implementat ca NUMBER(38).

TIMESTAMP - Data şi ora în ani, luni, zile, ore, minute şi secunde.

VARCHAR - Date de tip caracter cu lungime variabilă, conţinând cel mult

4000 de caractere.

Oracle oferă următoarele extensii la tipurile de date standard:

BFILE - O valoare de localizare a unui fişier binar de dimensiuni mari, stocat

în afara bazei de date.

LONG - Date de tip caracter cu lungime variabilă, cu dimensiunea maximă

de 2GB.

LONG RAW - Date binare, cu dimensiunea maximă de 2GB.

NUMBER - Date numerice, cu cel mult 38 de cifre. Poate stoca valori întregi

sau în virgulă mobilă.

NVARCHAR2 - Identic cu NVARCHAR.

RAW - Date binare, cu dimensiunea maximă de 2000 de octeli.

ROWID - Şir de caractere codat Base 64*, reprezentând adresa unică a unui

rând în tabelul din care face parte.

UROWID - Şir de caractere codat Base 64, reprezentând adresa logică a

unui rând într-un tabel indexat.

VARCHAR2 - Identic cu VARCHAR, dar Oracle recomandă folosirea

folosirea acestui tip în loc de VARCHAR, deoarece Oracle e posibil să schimbe la un

moment dat implementarea tipului VARCHAR.

Page 56: Curs Sinteza SQL

Valori NULL şi logica bazată pe trei valori

La definirea coloanelor din tabelele bazei de date, se află opţiunea de a

specifica dacă valorile nule (null) sunt permise în coloana respectivă. O valoare nulă

într-o bază de date relaţională este un cod special care poate fi plasat pe o

coloană pentru a indica faptul că valoarea pentru coloana respectivă nu este

cunoscută. O valoare nulă nu este ace1aşi lucru cu un spaţiu, un şir vid sau

valoarea zero – este un cod special care nu are nici o altă semnificaţie în baza de

date.

În Microsoft Access, restricţia NOT NULL este controlată de opţiunea

Required din panoul de proiectare a tabelului. În SQL DDL, se specifică cuvintele

cheie NULL sau NOT NULL, în definiţia coloanei (în dreapta tipului de date al

coloanei). În Oracle, DB2 şi majoritatea celorlalte baze de date relaţionale, dacă se

omite specificarea acestei restricţii, valoarea prestabilită este NULL, ceea ce înseamnă

că în coloana respectivă sunt valori nule. Pe de altă parte, în Microsoft SQL Server şi

Sybase Adaptive Server este exact invers: dacă se omite specificarea acestei

restricţii, valoarea prestabi1ită este NOT NULL, ceea ce înseamnă ca în coloana

respectivă nu pot fi valori nule.

Exemple

Pentru memorarea datelor numerice, tipurile cele mai frecvent folosite sunt:

NUMBER, INTEGER, FLOAT, DECIMAL.

Pentru memorarea şirurilor de caractere, cele mai frecvent tipuri de date

utilizate sunt: CHAR, NCHAR, VARCHAR2 , NVARCHAR2 şi LONG.

Informaţii relative la timp sau dată calendaristică se obţin utilizând tipul

DATE. Pentru fiecare dată de tip DATE sunt depuse: secolul, anul, luna, ziua, ora,

minutul, secunda. Pentru o coloană de tip DATE sistemul rezervă 7 bytes, indiferent

dacă se memorează doar timpul, sau doar data calendaristică.

FORMATUL IMPLICIT AL DATEI SE DEFINESTE CU AJUTORUL

PARAMETRULUI DE INITIALIZARE NLS_DATE_FORMAT. ÎN GENERAL,

ACEST PARAMETRU ESTE SETAT LA FORMA DD-MON-YY. DACA NU

ESTE SPECIFICAT TIMPUL, TIMPUL IMPLICIT ESTE 12:00:00.

Oracle9i introduce noi tipuri de date pentru timp:

TIMESTAMP(precizie_fracţiuni_secundă) cuprinde valori

pentru anul, luna şi ziua unei date calendaristice, dar şi valori pentru oră, minut,

secundă

INTERVAL YEAR (precizie_an) TO MONTH stochează o perioadă de

timp specificată în ani şi luni, unde precizie_an reprezintă numărul de cifre din

câmpul YEAR.

INTERVAL DAY (zi) TO SECOND (prec_frac_sec) stochează o

perioadă de timp reprezentată în zile, ore, minute şi secunde.

Probleme

Să se creeze un tabel cu trei coloane, inceput, durata_1, durata_2. Coloana

inceput va cuprinde valori ce reprezintă momente de timp, inclusiv fracţiunile de

Page 57: Curs Sinteza SQL

secundă corespunzătoare. Valorile coloanei durata_1 vor fi intervale de timp

specificate în număr de zile, ore, minute şi secunde. Coloana durata_3 va conţine

intervale de timp precizate în număr de ani şi luni. Să se insereze o înregistrare în

acest tabel.

CREATE TABLE TIMP (

inceput TIMESTAMP,

durata_1 INTERVAL DAY(2) TO SECOND(3),

durata_2 INTERVAL YEAR TO MONTH );

Exemple date inserate 1.

INSERT INTO timp

VALUES (TIMESTAMP '2009-10-31 09:26:50.30',

INTERVAL '23 7:44:22' DAY TO SECOND,

INTERVAL '19-02' YEAR TO MONTH);

Ex. 2

INSERT INTO timp

VALUES (TIMESTAMP '2010-02-20 09:20:40.20',

INTERVAL '23 7:44:22' DAY TO SECOND,

INTERVAL '200-02' YEAR TO MONTH);

INTERVAL '200-02' da eroare, deoarece implicit precizia pentru an este 2,

iar 200 are 3 digiti

Ex.3

Page 58: Curs Sinteza SQL

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '23 7:44:22' DAY TO SECOND,

INTERVAL '20-100' YEAR TO MONTH);

INTERVAL '20-100' eroare, deoarece 100 de luni adauga ani

Ex.4

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '23 2:2:2' DAY TO SECOND,

INTERVAL '20-10' YEAR TO MONTH);

Ex.5

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '23 2:2:2' DAY TO SECOND,

INTERVAL '20-12' YEAR TO MONTH);

Page 59: Curs Sinteza SQL

INTERVAL '20-12' eroare deoarece 12 luni fac un an si depasesc intervalul de

20 ani

Ex.6

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '23 2:2:2' DAY TO SECOND,

INTERVAL „120‟ MONTH);

Se observă ca executând instructiunea:

SELECT * from timp ;

Ca durata_2 are valoarea 10;

Ex.7

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:26:50.30',

INTERVAL '360' SECOND,

INTERVAL „144‟ YEAR);

Page 60: Curs Sinteza SQL

Se observa că inregistrarea introdusa are :

Durata_1 este de 6 min(360 sec) si

Durata_2 de 12 ani(144 de zile)

Ex.8

INSERT INTO timp

VALUES (TIMESTAMP '2010-01-25 09:00:00.30',

INTERVAL '20' DAY(2),

INTERVAL „10‟ YEAR);

Se observa că inregistrarea introdusa are :

Durata_1 de 20 zile si 0 secunde( fiind un INTERVAL DAY TO

SECOND) si

Durata_2 este 10 ani si 0 luni (fiind un INTERVAL YEAR TO MONTH)

Exemplu

CREATE TABLE exemplu

(durata INTERVAL YEAR(3) TO MONTH);

Page 61: Curs Sinteza SQL

INSERT INTO exemplu

VALUES (INTERVAL '120' MONTH);

SELECT TO_CHAR(SYSDATE+durata, 'DD-mon- YYYY')

FROM exemplu;

Exemplu

CREATE TABLE noi_carti

(codel NUMBER,

start_data TIMESTAMP);

INSERT INTO noi_carti

VALUES (1,TIMESTAMP '2009-10-31 09:26:50.30');

SELECT codel ,start_data

FROM noi_carti;

INSERT INTO noi_carti

VALUES (5, timestamp '12-02-08 0:0:0');

Pentru informatii de tip TIMESTAMP, numarul maxim de digiti pentru fractiuni

de secunda este 9, implicit este 6.

Rezultatele cererii:

1

31-OCT-09 09.26.50.300000 AM

5

08-FEB-12 12.00.00.000000 AM

Page 62: Curs Sinteza SQL

Pentru informatii de tip DATE, formatul implicit ar fi fost DD-MON-RR

Câmp Valori valide pentru date

calendaristice Valori valide pentru

intervale

YEAR De la -4712 la 9999 (cu excepţia

anului 0).

Orice valoare

întreagă.

MONTH De la 01 la 12. De la 0 la 11.

DAY

De la 01 la 31 (limitat de

valorile câmpurilor MONTH şi YEAR,

corespunzător regulilor calendarului

curent).

Orice valoare

întreagă.

HOUR De la 00 la 23. De la 0 la 23.

MINUTE De la 00 la 59. De la 0 la 59.

SECOND De la 00 la 59.9(n), unde „9(n)―

este precizia fracţiunilor de secundă.

De la 0 la 59.9(n),

unde „9(n)― este precizia

fracţiunilor de secundă.

TIMEZONE_HO

UR

De la –12 la 13 (prevede

schimbările datorate trecerilor la ora de

vară sau iarnă).

Nu se aplică.

TIMEZONE_MI

NUTE De la 00 la 59. Nu se aplică.

Sistemul Oracle permite construcţia de expresii folosind valori de tip dată

calendaristică şi interval. Operaţiile care pot fi utilizate în aceste expresii şi tipul

rezultatelor obţinute sunt următoarele:

Data + Interval, Data – Interval, Interval + Data, iar rezultatul este de tip

dată calendaristică;

Data – Data, Interval + Interval, Interval – Interval, Interval * Number,

Number * Interval, Interval / Number, iar rezultatul este de tip interval.

MODELE DE FORMAT

UN MODEL DE FORMAT ESTE UN LITERAL CARACTER CARE

DESCRIE FORMATUL VALORILOR DE TIP DATE SAU NUMBER

STOCATE INTR-UN SIR DE CARACTERE. ATUNCI CAND SE

CONVERTESTE UN SIR DE CARACTERE INTR-O DATA

CALENDARISTICA SAU INTR-UN NUMAR, MODELUL DE FORMAT

INDICA SISTEMULUI CUM SA INTERPRETEZE SIRUL RESPECTIV.

ÎN INSTRUCTIUNILE SQL SE POATE FOLOSI UN MODEL DE

FORMAT CA ARGUMENT AL FUNCTIILOR TO_CHAR SI TO_DATE. ÎN

FELUL ACESTA SE POATE SPECIFICA FORMATUL FOLOSIT DE

SISTEMUL ORACLE PENTRU A RETURNA SAU A STOCA O VALOARE

IN/DIN BAZA DE DATE. UN MODEL DE FORMAT NU SCHIMBA

REPREZENTAREA INTERNA A VALORII IN BAZA DE DATE.

O PARTE DINTRE ELEMENTELE CEL MAI FRECVENT

Page 63: Curs Sinteza SQL

INTALNITE ALE UNUI FORMAT DE TIP NUMERIC SUNT SINTETIZATE

IN TABELUL URMATOR.

El

ement Exemplu

Descriere

,

(virgulă)

9,9

99

Plasează o virgulă în poziţia specificată. Într-un model de

format numeric pot fi precizate mai multe virgule, dar o

virgulă nu poate apărea în partea dreaptă a punctului

zecimal.

.

(punct)

99.

99

Plasează un punct zecimal în poziţia specificată.

Într-un format numeric, se poate specifica cel mult un

punct zecimal.

$ $99

99 Include semnul „$― în faţa unei valori.

0 099

9; 9990 Plasează zerouri în faţa sau la sfârşitul valorii.

9 999

9

Întoarce valoarea cu numărul specificat de cifre.

Valoarea va avea un spaţiu, respectiv un minus în faţă dacă

este pozitivă, respectiv negativă.

C C99

9

Plasează în poziţia specificată simbolul ISO pentru

monede(valoarea curentă a parametrului

NLS_ISO_CURRENCY).

D 99D

99

Plasează în poziţia specificată caracterul zecimal,

care este valoarea curentă a parametrului

NLS_NUMERIC_CHARACTER. Valoarea implicită este

punctul. Se poate specifica cel mult un caracter zecimal

într-un model de format numeric.

E

EEE

9.9

EEEE Returnează o valoare folosind notaţia ştiinţifică.

L L99

9 Întoarce în poziţia specificată simbolul monedei

locale (valoarea curentă a parametrului NLS_CURRENCY).

MI 999

9MI

Plasează semnul minus la sfârşitul valorilor negative şi un

spaţiu la sfârşitul celor pozitive. Acest element poate fi

specificat numai pe ultima poziţie a modelului de format

numeric.

S

S99

99; 999

9S

Plasează semnele plus sau minus la începutul sau la

sfârşitul valorii. Acest element poate apărea doar pe prima

sau ultima poziţie a modelului de format numeric.

MODELELE DE FORMAT PENTRU DATE CALENDARISTICE POT FI UTILIZATE IN CADRUL URMATOARELOR FUNCTII DE CONVERSIE:

TO_DATE, pentru a converti o valoare de tip caracter, care este într-un alt format decât cel implicit, într-o valoare de tip DATE;

TO_CHAR, pentru a converti o valoare de tip DATE, care este într-un alt format decât cel implicit, într-un şir de caractere.

SYSDATE, pentru aflarea datei curente. De exemplu SELECT SYSDATE FROM dual;

Page 64: Curs Sinteza SQL

Un model de format pentru date calendaristice este alcătuit dintr-unul sau mai multe elemente specifice. Scrierea cu litere mari sau mici a cuvintelor, abrevierilor sau a numeralelor romane este respectată în elementul de format corespunzător.

De exemplu, modelul de format „DAY― produce cuvinte cu majuscule, cum ar fi „FRIDAY―, iar „Day― şi „day― au ca rezultat „Friday―, respectiv „friday―.

Într-un model de format pentru date calendaristice se pot preciza semne de punctuaţie şi literale caracter, incluse între ghilimele. Toate aceste caractere apar în valoarea returnată pe locul specificat în modelul de format.

Element Explicaţie

AD sau A.D. Indicatorul AD (Anno Domini) cu sau fără puncte.

BC sau B.C. Indicatorul BC (Before Christ) cu sau fără puncte.

D Numărul zilei din săptămână (1-7). Duminica este considerată prima

zi a săptămânii.

DAY Numele zilei completat cu spaţii, până la lungimea de 9

caractere.

DD Numărul zilei din lună (1-31).

DDD Numărul zilei din an (1-366).

DY Numele zilei din săptămână, printr-o abreviere de 3 litere.

FF Fracţiunile de secundă.

HH sau HH12 Ora din zi (1-12).

HH24 Ora din zi (0-23).

MI Minutele din oră (0-59).

MM Luna din an (01-12).

MON Numele lunii, printr-o abreviere de 3 litere.

MONTH Numele lunii completat cu spaţii, până la lungimea de 9 litere.

RM Luna în cifre romane (I-XII).

RR Anul cel mai apropiat de data curentă.

RRRR Acceptă intrarea atât cu 2, cât şi cu 4 cifre. Dacă anul de

intrare se dă cu 2 cifre, furnizează acelaşi lucru ca şi formatul RR.

SS Secundele din minut (0-59).

SSSSS Secundele trecute de la miezul noptii (0-86399).

TZH Ora regiunii.

TZM Minutul regiunii.

Y,YYY Anul scris cu virgulă după prima cifră.

YEAR sau SYEAR Anul în litere („S― prefixează anii i.Hr. cu semnul minus).

YYYY sau SYYYY Anul cu 4 cifre.

YYY, YY sau Y Ultimele cifre ale anului.

Page 65: Curs Sinteza SQL

Modificatorii FM şi FX pot fi utilizaţi în modelele de format din cadrul funcţiei TO_CHAR, controlând completarea cu spaţii şi verificarea exactă a formatelor. Un modificator poate să apară într-un model de format de mai multe ori. În acest caz, efectele sale sunt active pentru porţiunea din model care începe la prima apariţie şi apoi dezactivate pentru porţiunea din model care urmează celei de-a doua apariţii ş.a.m.d.

Modificatorul FM (Fill Mode) suprimă completarea cu spaţii în valoarea returnată de funcţia TO_CHAR, iar FX (Format eXact) impune corespondenţa exactă dintre argumentul de tip caracter şi modelul de format precizat pentru data calendaristică respectivă.

Exemplu:

SELECT nume, TO_CHAR(data_ang,‘Month FMDD,YYYY‘) angajare

FROM angajati

WHERE TO_CHAR(data_ang, ‘YYYY‘)=‘2009‘;

Nume Angajare

Pop January 21,2009

Ene October 10,2009

Exemplu

SELECT nume, TO_CHAR(data_ang,‘ DDTH ‖of‖ Month YYYY‘) angajare

FROM angajati

WHERE TO_CHAR(data_ang, ‘YYYY‘)=‘2009‘;

Nume Angajare

Pop 21st of January 2009

Ene 10TH of October 2009

Exemplu

SELECT TO_CHAR(data_ang,‘ fmDDspth Month.Year‘) angajare

FROM angajati

WHERE id_ang=100;

Angajare

Twenty_NineTH July, Two Thousand Nine

Exemplu

Page 66: Curs Sinteza SQL

SELECT ‘sesiune incepe pe ‘|| TO_DATE(‘20-09-2010‘,‘DD-MM-YYYY‘) from dual;

Sesiunea incepe pe 20-09-2010

(Afişează formatul standard pentru dată)

Valoarea null, reprezentând lipsa datelor, nu este egală sau diferită de nici o altă valoare, inclusiv null.

Totuşi, există două situaţii în care sistemul Oracle consideră două valori null

ca fiind egale: la evaluarea funcţiei DECODE şi dacă valorile null apar în chei

compuse. Două chei compuse care conţin valori null sunt considerate identice dacă

toate componentele diferite de null sunt egale.

Instrucţiuni DDL (Data Definition Language)

Instrucţiunile DDL (Data Definition Language) definesc obiectele bazei de

date, dar nu inserează şi nu actualizează date în obiectele respective. În SQL, există

trei comenzi de bază pentru instrucţiunile DDL:

CREATE - Creează în baza de date un nou obiect, de tipul specificat în

instrucţiune : CREATE DATABASE, CREATE TABLE, CREATE INDEX şi

CREATE VIEW.

ALTER - Modifică definiţia unui obiect existent în baza de date, de tipul

specificat în instrucţiune : ALTER TABLE, ALTER DATABASE, ALTER

SYSTEM, ALTER USER, ALTER SESSION.

D R O P - Şterge (distruge) un obiect existent în baza de date, de tipul

specificat în instrucţiune.

Instrucţiunea CREATE TABLE

CREATE TABLE este una din instrucţiunile fundamentale din SQL.

Modelul relaţional cere ca toate datele stocate să fie ancorate într-un tabel, aşa că

posibilitatea de a stoca orice într-o bază de date începe întotdeauna cu crearea

unui tabel. Sintaxa de bază pentru instrucţiunea CREATE TABLE este:

CREATE TABLE nume_tabel

(<definiţie_coloană>

[,<definiţie_coloană> ...])

[,<restricţie—tabel>... ];

Definirea coloanelor în SQL DDL

Sintaxa de bază folosită pentru definirea coloanelor unui tabel este:

<definiţie_coloană>

nume coloană tip_de_date

[DEFAULT expresie]

[NULL | NOT NULL]

[<restricţie_coloană>]

Page 67: Curs Sinteza SQL

Componentele din definiţia unei coloane sunt:

Numele coloanei - Numele coloanei trebuie să fie unic în cadrul tabelului.

Tipul de date - Tipul de date trebuie să fie un tip de date valid pentru

implementarea SGBD

Restrictiile coloanei care sunt prezentate în continuare

STRUCTURA UNUI TABEL POATE FI CREATĂ ÎN

URMĂTOARELE PATRU MODURI:

fără a indica cheile;

indicând cheile la nivel de coloană;

indicând cheile la nivel de tabel;

prin copiere din alt tabel.

Exemplu : Gestiunea activităţilor de împrumut dintr-o bibliotecă

1. Crearea structurii unui tabel fără a indica cheile:

CREATE TABLE carte

(codel CHAR(5),

titlu VARCHAR2(30),

autor VARCHAR2(30),

pret NUMBER(8,2),

nrex NUMBER(3),

coded CHAR(5));

2. Crearea structurii unui tabel indicând cheile la nivel coloană:

CREATE TABLE carte

(codel CHAR(5) PRIMARY KEY,

titlu VARCHAR2(30),

autor VARCHAR2(30),

pret NUMBER(8,2),

nrex NUMBER(3),

coded CHAR(5) NOT NULL

REFERENCES domeniu(coded));

CITI

TOR codec#

nume

dep

CAR

TE codel#

titlu

autor

pret

nrex

coded

DOME

NIU coded#

intdom

imprumut

a

apartine

M

(1)

M

(0)

M

(0)

1

Page 68: Curs Sinteza SQL

CONSTRANGEREA DE CHEIE PRIMARA SAU EXTERNA CE

PRESUPUNE?

CREATE TABLE carte

(codel CHAR(5) PRIMARY KEY,

titlu VARCHAR2(30),

autor VARCHAR2(30),

pret NUMBER(8,2),

nrex NUMBER(3),

coded CHAR(5) NOT NULL

REFERENCES domeniu(coded)

ON DELETE CASCADE);

CREATE TABLE domeniu

(coded CHAR(5) PRIMARY KEY,

den_dom VARCHAR2(30));

CREATE TABLE cititor

(codec CHAR(5) PRIMARY KEY,

den_cititor VARCHAR2(30));

Opţiunea ON DELETE CASCADE specifică că suprimarea oricărui domeniu

de carte din tabelul domeniu este autorizată şi implică suprimarea automată a tuturor

cărţilor din domeniul respectiv care se găsesc în tabelul carte.

3. Crearea structurii unui tabel indicând cheile la nivel de tabel:

CREATE TABLE carte (codel CHAR(5), titlu VARCHAR2(30), autor VARCHAR2(30), pret NUMBER(8,2), nrex NUMBER(3), coded CHAR(5) NOT NULL, PRIMARY KEY (codel),

FOREIGN KEY (coded)

REFERENCES domeniu (coded));

Dacă cheia primară are mai mult de o coloană atunci cheile trebuie indicate la

nivel de tabel.

CREATE TABLE imprumuta (codel CHAR(5), codec CHAR(5), dataim DATE DEFAULT SYSDATE, datares DATE, dataef DATE, PRIMARY KEY (codel, codec, dataim), FOREIGN KEY (codel)

REFERENCES carte(codel), FOREIGN KEY (codec) REFERENCES cititor(codec));

Page 69: Curs Sinteza SQL

INSERT INTO domeniu

VALUES(‘I‘, ‘Informatica‘);

INSERT INTO carte

VALUES(‘bnat1‘, ‘Baza_de_Date‘, ‘Popescu_Ioana‘, 300.50, 100,‘I‘);

4. Crearea structurii unui tabel prin copiere din alt tabel:

CREATE TABLE carte_info

AS SELECT codel, titlu, autor

FROM carte

WHERE coded = ‟I‟;

Un exemplu complet pentru crearea tabelului CONT_CLIENT, din baza de

date a magazinului de produse video, utilizând instrucţiune DDL şi incluzând

restricț ii

CREATE TABLE CONT_CLIENT

(

ID_CONT_CLIENT INTEGER NOT NULL,

CLIENT_CONT_STARE CHAR(1) DEFAULT ‗N‘ NOT NULL,

CHECK (CLIENT_CONT_STARE IN (‗Y‘, ‗N‘)),//restr. coloana

DATA_INSCRIERE DATE NOT NULL,

DATA_INCHEIERE DATE NULL, //NULL daca contul e activ

SUMA_DEPOZIT_CLIENT NUMERIC(5,2) NULL,

CREDIT_CARD_IND CHAR(1) NOT NULL,

CHECK (CREDIT_CARD_IND IN (‗Y‘, ‗N‘)), //restric coloana

IND_PERMIS_INCHIRIERE_COPIL CHAR(1) NOT NULL,

CHECK(IND_PERMIS_INCHIRIERE_COPIL IN(‗Y‘,‗N‘

PRIMARY KEY (ID_CONT_CLIENTINTEGER ) //restr. tabel

);

Page 70: Curs Sinteza SQL

Componentele din definiţia unei coloane sunt:

Numele coloanei - Numele coloanei trebuie să fie unic în cadrul tabelului.

Tipul de date - Tipul de date trebuie să fie un tip de date valid pentru

implementarea SGBD

Restrictiile coloanei care sunt prezentate în continuare

Restricţiile coloanelor

Restricţiile unei coloane limitează într-un mod oarecare valorile ce pot fi

stocate într-o coloană a unui tabel. Restricţiile coloanelor pot avea oricare dintre

următoarele forme:

Clauza DEFAULT - O expresie care este aplicată coloanei atunci când în

tabel este inserat un nou rând, care nu conţine o valoare explicită pentru coloana

respectivă. Expresia poate fi orice expresie validă. Sintaxa SQL cu o clauză

DEFAULT este:

[DEFAULT expresie]

Exemplu:

STARE_CONT_CLIENT CHAR(1) DEFAULT 'N' NOT NULL

Restricţia NULL | NOT NULL - Specificarea cuvântului cheie NULL

permite stocarca valorilor nule într-o coloană, în timp ce NOT NULL nu permite

stocarca valorilor nule în coloana respectivă. O restricţie NOT NULL poate fi

scrisă şi sub forma unei restricţii CHECK cu condiţia IS NOT NULL. Sintaxa SQL şi

câteva exemple:

NULL | NOT NULL

Exemple:

DATA_INSCRIERE DATE NOT NULL

DATA_INCHEIERE DATE NULL

Restricţia CHECK - O restricţie de verificare (check) poate fl folosită

pentru impunerea unei reguli care poate fi aplicată unei singure coloane a unui tabel.

Condiţia inclusă în restricţie trebuie să fie îndeplinită ori de câte ori datele din

coloana respectivă a tabelului sunt modificate – în caz contrar, sistemul SGBD va

respinge modificarea şi va afişa un mesaj de eroare. Sintaxa restricţiei CHECK şi un

exemplu:

[CONSTRAINT nume restricţie] CHECK (condiţie)

Exemplu:

CREDIT_CARD_IND CHAR(1) NOT NULL,

CHECK (CREDIT_CARD_IND IN (‗Y‘, ‗N‘))

Clauză NOT NULL poate fi rescrisă şi sub forma unei restricţii CHECK:

ID_CONT_CLIENT INTEGER

CONSTRAINT CK_CUST _ACCT _ID CHECK (ID_CONT IS NOT

NULL)

Restricţia UNIQUE - O restricţie UNIQUE impusă asupra unei coloane

garantează unicitatea valorilor din coloana respectivă a tabelului. Sintaxa:

[CONSTRAINT nume_restricţie] UNIQUE

Exemplu:

Page 71: Curs Sinteza SQL

ID_CONT_CLIENT INTEGER NOT NULL UNIQUE

Restricţia PRIMARY KEY - O restricţie de cheie primară (PRIMARY

KEY) impusă asupra unei coloane declară coloana respectivă ca fiind cheia primară a

tabelului, ceea ce înseamnă că în coloana respectivă nu pot exista valori nule, iar

valorile trebuie să fie unice în cadrul tabelului. Sintaxa :

(CONSTRAINT nume_restricţie] PRIMARY KEY

EXEMPLU: ID_CONT_CLIENT INTEGER NOT NULL PRIMARY KEY

Restricţia referentială (FOREIGN KEY) - O restricţie referenţială

impusă asupra unei coloane (numită şi restricţie de cheie externă) defineşte relaţia

dintre o cheie externă şi o cheie primară. Sintaxa:

[CONSTRAINT nume_restricţie]

REFERENCES nume_tabel(nume_coloană)

[ON DELETE CASCADE | ON DELETE SET NULL]

Exemplu:

MPAA_CODE_RATING din tabelul FILME este cheie externă pentru tabelul

MPPA_RATING, care are câmpurile: MPAA_CODE_RATING şi

MPAA__RATING _DESCRIERE

MPAA_COD_RATING CHAR (5) NOT NULL

REFERENCES MPPA_RATING(MPAA_CODE_RATING)

Clauza opţională ON DELETE spune sistemului SGBD ce să facă atunci când

este şters rândul referit din tabelul părinte cu opţiunea de a şterge toate rândurile care

conţin cheia externă (CASCADE) sau de a insera valori nule pentru toate cheile

externe (SET NULL).

Restricţiile tabelelor

Restricţia unei coloane poate fi rescrisă şi ca restricţie a întregului tabel, astfel

încât clauza care defineşte restricţia să apară în instrucţiunea CREATE TABLE după

definiţiile tuturor coloanelor, nu după definiţia unei coloane. Principalul avantaj al

restricţiilor la nivelul tabelului este că pot referi mai multe coloane.

Restricţia CHECK

[CONSTRAINT nume_restricţie] CHECK (condiţie)

Restricţia de mai jos împiedică stocarea unei valori negative în coloana

SUMA_DEPOZITE_CLIENT . Operatorul OR permite stocarea valorilor nule ,

deoarece o valoare nulA nu este mai mare sau egală cu zero.

Exemplu:

CONSTRAINT CK_SUMA_DEPOZITE_CLIENT

CHECK (SUMA_DEPOZITE_CLIENT >= 0 OR

SUMA_DEPOZITE_CLIENT IS NULL)

Restricţia UNIQUE

[CONSTRAINT nume_restricţie) UNIQUE (nume_coloană [,nume

coloană...])

Conform acestei restricţii , combinaţia de coloane ID_CONT_CLIENT şi

DATA_INSCRIERE trebuie să fie unică în rândurile din tabel.

Exemplu:

Page 72: Curs Sinteza SQL

CONSTRAINT UK_DATA_INSCR_CONT_CL

UNIQUE (ID_CONT_CLIENT, DATA_INSCRIERE )

Restricţia PRIMARY KEY

[CONSTRAINT nume_restricţie]

PRIMARY KEY (nume_coloană [,nume_coloană...])

Restricţia de mai jos este chiar definiţia cheii primare din tabelul

CONT_CLIENT [

Exemplu:

CONSTRAINT PK_CONT_CLIENT

PRIMARY KEY (ID_CONT_CLIENT)

Restricţia referenţială (FOREIGN KEY)

Spre deosebire de forma pentru restricţia referenţială a coloanei,

aceasta poate referi mai multe coloane.

[CONSTRAINT nume_restricţie]

FOREIGN KEY (nume_coloană [,nume coloană...])

REFERENCES nume_tabel (nume_coloană [,nume_coloană... [ON DELETE

CASCADE |ON DELETE SET NULL]

EXEMPLE: 1. SA SE DEFINEASCA O CONSTRANGERE LA NIVEL DE

COLOANA PRIN CARE SA SE SPECIFICE CHEIA PRIMARA SI CHEIA

EXTERNA.

CREATE TABLE carte

(codel CHAR(5)

CONSTRAINT cp_carte PRIMARY KEY, Titlu VARCHAR2(30),

autor VARCHAR2(30),

pret NUMBER(8,2),

nrex NUMBER(3), coded CHAR(5) CONSTRAINT nn_coded NOT NULL CONSTRAINT ce_coded REFERENCES domeniu(coded));

2. SA SE DEFINEASCA O CONSTRANGERE LA NIVEL DE TABEL

PRIN CARE SA SE SPECIFICE CHEIA PRIMARA SI CHEIA EXTERNA.

CREATE TABLE carte

(codel CHAR(5),

titlu VARCHAR2(30),

autor VARCHAR2(30),

pret NUMBER(8,2),

nrex NUMBER(3),

coded CHAR(5) NOT NULL,

Page 73: Curs Sinteza SQL

CONSTRAINT cp_carte PRIMARY KEY (codel), CONSTRAINT ce_coded FOREIGN KEY (coded)

REFERENCES domeniu(coded));

Observaţii:

Liniile ce nu respectă constângerea sunt depuse automat într-un tabel

special.

Constrângerile previn ştergerea unui tabel dacă există dependenţe.

Constrângerile pot fi create o dată cu tabelul sau după ce acesta a fost

creat.

Constrângerile pot fi activate sau dezactivate în funcţie de necesităţi.

CONSTRANGERI DECLARATIVE POT FI: CONSTRANGERI DE

DOMENIU, CONSTRANGEREA DE INTEGRITATE A ENTITATII,

CONSTRANGEREA DE INTEGRITATE REFERENTIALA.

Constrângerile de domeniu definesc valori luate de un atribut (DEFAULT,

CHECK, UNIQUE, NOT NULL).

constrângerea (coloană) DEFAULT ;

constrângerea (coloană sau tabel) CHECK ; constrângerea CHECK la nivel de

tabel poate compara coloane între ele, poate face referinţă la una sau mai multe

coloane, dar nu poate conţine subcereri. Constrângerea la nivel de coloană nu

poate referi alte coloane ale aceluiaşi tabel.

CREATE TABLE carte (codel CHAR(5),… nrex NUMBER(3),

pret NUMBER(8,2)

CONSTRAINT alfa CHECK (pret < nrex),…);

La execuţia acestei comenzi apare mesajul: ORA – 02438: Column check

constraint cannot reference other columns.

Dacă după NUMBER(8,2) se adaugă o virgulă, atunci constrângerea va fi la

nivel de tabel, iar în aceste caz este permisă referirea altei coloane.

Instrucţiunea CREATE INDEX

Indexurile sunt instrumente puternice, deoarece permit sistemului să

gasescă datele mult mai repede, tot aşa cum indexul unei cărţi ne permite să gasim

mai rapid ceea ce ne interesează. De asemenea, indxurile pe coloanele cheilor externe

cresc mult peformanţele la unirea tabelelor. Sistemul SGBD întreţin automat indexul,

dar activitatea de întreţinere consumă din resursele calculatorului.

Sintaxa de bază a instrucţiunii CREATE INDEX este:

CREATE [UNIQUE] INDEX nume_index ON nume_tabel

(nume_coloană [,nume coloană [ASC | DESC] …]);

Page 74: Curs Sinteza SQL

Cuvântul cheie opţional UNIQUE defineşte indexul ca unic, însemnând că nu

pot exista două rânduri din tabel cu exact acceaşi combinaţie de valori în

coloanele specificate.

Cuvântul cheie opţional ASC creează indexul în ordine crescătoare, în timp ce

DESC creează indexul în ordine descrescătoare. Dacă nu este specificată nici una

dintre cele două opţiuni, ordinea prestabilită este crescătoare.

Un index trebuie să aibă cel puţin o coloană, dar, nu există o limită superioară

a numărului de coloane.

Instrucţiunea CREATE VIEW

O vizualizare este o interogare SQL stocată, care poate fi referită de

instrucţiuni1e SQL DML şi DQL ca şi cum ar fi un tabel real. Unii consideră că

vizualizările sunt „tabele virtuale", deoarece se comportă la fel ca tabelele, dar

nu există ca tabele fizice. Sintaxa generală a instucţiunii CREATE VIEW este:

CREATE [OR REPLACE] VIEW nume_vizualizare AS interogare sql;

Cuvântul cheie opţional OR REPLACE elimină necesitatea de a sterge o

vizualizare existentă înainte de a o crea din nou.

Numele vizualizării trebuie să respecte aceleaşi reguli de denumire ca şi

tabelele şi alte obiecte ale bazei de date.

Interogarea SQL inclusă în definiţia vizualizării poate fi orice instrucţiunea

SQL SELECT validă.

Instrucţiunea ALTER TABLE

Instrucţiunea ALTER TABLE ajută să se facă asupra tabelelor create.

Utilizarea instrucţiunii ALTER TABLE este un alt domeniu în care au un

rol important stilul şi preferinţele personale. Mulţi administratori de baze de date

preferă să folosească inst rucţuni CREATE TABLE cât mai simple, evitând

să definească restricţii în instrucţiunile CREATE TABLE. Aceştia adaugă

după instrucţiunea CREATE TABLE instrucţiuni ALTER TABLE prin care

specifică toate restricţiile necesare (cheie primară, cheie externă, unicitate,

verificare). Dezavantajul acestei metode este acela că necesită scrierea unei

cantităţi mai mari de cod. Pe de altă parte, instrucţiunea CREATE TABLE este

mult mai uşor de înţeles fără restricţii, iar scrierea separată a restricţiilor

simplifică refolosirea instrucţiunilor.

Deşi există unele diferenţe între implementările SGBD, o listă cu tipurile de

modificări acceptate de instrucţiunea ALTER TABLE, împreună cu sintaxa

generală pentru fiecare tip este:

Adăugarea unei coloane la un tabel. Definirea coloanei se face cu aceeaşi

sintaxă ca şi în cazul instrucţiunii CREATE TABLE.

ALTER TABLE nume_tabel

ADD ( <definiţie_co1oană>

[,<definiţie_co1oană>

Page 75: Curs Sinteza SQL

Exemplu:

ALTER TABLE CONT_CLIENT

ADD (DATA _CLIENT DATE NULL,

INTRODUSE_DE VARCHAR(50));

Modificarca definiţiei unei coloane. Majoritatea SGBD-urilor nu permit să

scădeţi precizia unei coloanedacă tabelul conţine date şi foarte puţine permit să se

schimbe tipul de date al unei coloane existente. Sunt acceptate creşterea preciziei unei

coloane, adăugarea sau modificarea valorii prestabilite pentru o coloană, şi trcerea de

la NULL la NOT NULL sau invers.

.

ALTER TABLE nume_tabel

MODIFY [COLUMN] (<definiţie — coloană>

[,<definiţie_co1oană> ...]);

Exemplu:

ALTER TABLE CONT_CLIENT

MODIFY (SUMA_DEPOZIT_CLIENT NUMERIC(7,2)

DEFAULT 0 NOT NULL);

Adăugarea unei restricţii. Definiţia restricţiei este identică cu definiţia

unei restricţii care ar putea apărea într-o instrucţiune CREATE TABLE.

ALTER TABLE nume_tabel

ADD CONSTRAINT <definiţie_restricţie>;

Exemplu:

ALTER TABLE CONT_CLIENT

ADD CONSTRAINT CK_SUMA_DEPOZIT_CLIENT CHECK

(SUMA_DEPOZIT_CLIENT >= 0

OR SUMA_DEPOZIT_CLIENT IS NULL);

Ştergerea cheii primare a unui tabel.

Dacă cheia primară este referită de restricţii referenţiale, trebuie mai întâi

şterse restricţiile respective.

ALTER TABLE nume_tabel DROP PRIMARY KEY;

Redenumirea unei coloane.

Dintre bazele de date care acceptă această sintaxă este numai Oracle, începând

cu versiunea 8.0

Microsoft SQL Server are o procedură stocată, numită sp_rename, care vă

pune la dispoziţie o modalitate de a redenumi coloanele, tabelele şi alte obiecte ale

bazei de date.

ALTER TABLE nume_tabel

RENAME nume_vechi_coloană TO nume _nou_coloană;

Instrucţiunea DROP

Instrucţiunea DROP este cea mai simplă dintre instrucţiunile DDL.

Sintaxa de bază este:

DROP <tip_obiect> nume_obiect [<opţiuni_de_ştergere>]

Tipul de obiect specifică tipul obiectului care urmează să fie şters, cum ar fi

INDEX, TABLE sau VIEW.

Page 76: Curs Sinteza SQL

Opţiunile de ştergere sunt specifice fiecărui SGBD. Sintaxa este diferită de la

un producător la altul — PostgreSQL şi MySQL folosesc în acest scop cuvântul cheie

CASCADE, în timp ce în Oracle trebuie să se folosească CASCADE

CONSTRAINTS.

Exemplu:

DROP TABLE COD_CLIENT;

DROP TABLE COD_CLIENT CASCADE CONSTRAINTS; (Oracle)

DROP TABLE COD_CLIENT CASCADE; (MySQL / PostgreSQL)

DROP INDEX IX_TITLU_FILM;

Exemple :

Comanda ALTER TABLE permite:

adăugarea (ADD) de coloane, chei (primare sau externe), constrângeri într-

un tabel existent;

modificarea (MODIFY) coloanelor unui tabel;

specificarea unei valori implicite pentru o coloană existentă;

activarea şi dezactivarea (ENABLE, DISABLE) unor constrângeri;

suprimarea unei coloane;

suprimarea (DROP) cheii primare, a cheii externe sau a unor constrângeri.

Comanda ALTER TABLE are următoarea sintaxă simplificată:

Adăugarea unei coloane la un tabel. Definirea coloanei se face cu aceeaşi

sintaxă ca şi în cazul instrucţiunii CREATE TABLE. Nu se poate specifica unde

să apară coloana, ea devenind ultima coloană a tabelului.

ALTER TABLE nume_tabel

ADD ( <definiţie_co1oană>

[,<definiţie_co1oană>

Exemplu:

ALTER TABLE CONT_CLIENT

ADD (DATA_CLIENT DATE,

INTRODUSE_DE VARCHAR(50));

ALTER TABLE CITITOR

ADD (ADRESA VARCHAR(50));

ALTER TABLE carte

ADD(rezumat LONG);

Page 77: Curs Sinteza SQL

Modificarca definiţiei unei coloane. Majoritatea SGBD-urilor nu permit să

scădeţi precizia unei coloane dacă tabelul conţine date şi foarte puţine

permit să se schimbe tipul de date al unei coloane existente. Sunt acceptate

creşterea preciziei unei coloane, adăugarea sau modificarea valorii

prestabilite pentru o coloană, şi trcerea de la NULL la NOT NULL sau

invers.

ALTER TABLE nume_tabel

MODIFY [COLUMN] (<definiţie — coloană>

[,<definiţie_co1oană> ...]);

Exemplu:

ALTER TABLE CONT_CLIENT

MODIFY (SUMA_DEPOZIT_CLIENT NUMERIC(7,2)

DEFAULT 0 NOT NULL);

Adăugarea unei restricţii. Definiţia restricţiei este identică cu definiţia

unei restricţii care ar putea apărea într-o instrucţiune CREATE TABLE.

ALTER TABLE nume_tabel

ADD CONSTRAINT <definiţie_restricţie>;

Exemplu:

ALTER TABLE CONT_CLIENT

ADD CONSTRAINT CK_SUMA_DEPOZIT_CLIENT

CHECK (SUMA_DEPOZIT_CLIENT >= 0

OR SUMA_DEPOZIT_CLIENT IS NULL);

Dacă pun o valoare negativă la suma, atunci apare eroare .

Page 78: Curs Sinteza SQL

CREATE TABLE carte

(CODEL char(5),

…);

ALTER TABLE carte

ADD CONSTRAINT cheie_prim PRIMARY KEY (codel);

Ştergerea cheii primare a unui tabel.

Dacă cheia primară este referită de restricţii referenţiale, trebuie mai

întâi şterse restricţiile respective.

ALTER TABLE nume_tabel DROP PRIMARY KEY;

Dacă există o CE care referă o CP şi dacă se încearcă ştergerea cheii primare, această ştergere nu se poate realiza (tabelele sunt legate prin declaraţia de cheie externă). Ştergerea este totuşi permisă dacă în comanda ALTER apare opţiunea CASCADE, care determină şi ştergerea cheilor externe ce referă cheia primară.

ALTER TABLE domeniu DROP PRIMARY KEY CASCADE;

Ştergerea cheii externe se face ca si pentru ştergerea cheii primare

ALTER TABLE carte ADD CONSTRAINT beta

FOREIGN KEY (coded) REFERENCES domeniu;

Schimbarea cheii primare. Este destul de complicat procesul schimbării

cheii primare fără a afecta modul de proiectare a bazei de date. Schimbarea

se face în două etape: se şterge cheia primară şi apoi se recreează.

ALTER TABLE carte ADD (PRIMARY KEY(codel)); ALTER TABLE carte

DROP PRIMARY KEY;

ALTER TABLE carte

ADD PRIMARY KEY(titlu, autor));

Redenumirea unei coloane.

Dintre bazele de date care acceptă această sintaxă este numai Oracle,

începând cu versiunea 8.0

ALTER TABLE nume_tabel

RENAME COLUMN nume_vechi_coloană TO nume _nou_coloană;

ALTER TABLE timp

RENAME COLUMN durata_1 TO dur_1;

Page 79: Curs Sinteza SQL

ALTER TABLE timp

RENAME COLUMN durata_2 TO dur_2;

Pentru a activa (ENABLE) sau dezactiva (DISABLE) constrângeri:

ALTER TABLE nume_tabel

ENABLE nume_constrangere;

ALTER TABLE carte

DROP CONSTRAINT beta;

ALTER TABLE cititor

ADD CONSTRAINT cp_cititor

PRIMARY KEY (codec)

DISABLE;

ALTER TABLE cititor

ENABLE CONSTRAINT cp_cititor;

Stergerea unei coloane se face ca şi a unei constringeri;

ALTER TABLE nume_tabel

DROP nume_coloana;

ALTER TABLE CONT_CLIENT

DROP (DATA_CLIENT ,INTRODUSE_DE );

Observaţii

Nu se poate specifica poziţia unei coloane noi în structura tabelului. O

coloană nouă devine automat ultima în cadrul structurii tabelului.

Modificarea unei coloane presupune schimbarea tipului de date, a

dimensiunii sau a valorii implicite a acesteia. O schimbare a valorii implicite

Page 80: Curs Sinteza SQL

afectează numai inserările care succed modificării.

Dimensiunea unei coloane numerice sau de tip caracter poate fi mărită, dar

nu poate fi micşorată decât dacă acea coloană conţine numai valori null sau

dacă tabelul nu conţine nici o linie.

Tipul de date al unei coloane poate fi modificat doar dacă valorile coloanei

respective sunt null.

Alte opţiuni ale comenzii ALTER TABLE, care au apărut începând CU

VERSIUNEA ORACLE8I, SUNT SET UNUSED ŞI DROP UNUSED

COLUMNS:

ALTER TABLE NUME_TABEL

ET UNUSED [ ( ] NUME_COLOANĂ [ ) ];

ALTER TABLE NUME_TABEL

DROP UNUSED COLUMNS;

Opţiunea SET UNUSED permite marcarea uneia sau mai multor coloane

ca fiind nefolosite, cu scopul de a fi şterse atunci când necesităţile sistemului

impun acest lucru. Coloanele nefolosite sunt tratate ca şi cum ar fi fost

suprimate, deşi datele acestora rămân în liniile tabelului. După ce o coloană a

fost marcată UNUSED, utilizatorul nu mai are acces la aceasta prin intermediul

cererilor. În plus, numele şi tipurile de date ale coloanelor nefolosite nu vor fi

afişate cu comanda DESCRIBE din SQL*Plus. Utilizatorul poate să adauge

tabelului o nouă coloană având acelaşi nume cu cel al unei coloane nefolosite.

DROP UNUSED COLUMNS şterge din tabel toate coloanele marcate ca

fiind nefolosite. Acest lucru se poate utiliza pentru eliberarea spaţiului de pe disc

corespunzător coloanelor nefolosite din tabel. Dacă tabelul nu conţine nici o

coloană nefolosită, instrucţiunea nu întoarce o eroare şi nu are nici un efect.

Atunci când se elimină o coloană dintr-un tabel folosind opţiunea DROP a

comenzii ALTER TABLE, vor fi suprimate şi coloanele din tabel care sunt

marcate cu opţiunea SET UNUSED.

Suprimarea unui tabel

Pentru ştergerea unui tabel este utilizată comanda DROP TABLE:

DROP TABLE [nume_schema.]nume_tabel

[CASCADE CONSTRAINTS];

Clauza CASCADE CONSTRAINTS permite suprimarea tuturor

constrângerilor de integritate referenţială corespunzătoare cheilor primare şi

unice din tabelul supus ştergerii. Dacă se omite această clauză şi există

constrângeri de integritate referenţială, sistemul returnează o eroare şi nu

suprimă tabelul.

Suprimarea unui tabel presupune:

suprimarea definiţiei sale în dicţionarul datelor;

suprimarea indecşilor asociaţi;

suprimarea privilegiilor conferite în legătură cu tabelul;

recuperarea spaţiului ocupat de tabel;

permanentizarea tranzactiilor in asteptare;

Page 81: Curs Sinteza SQL

invalidarea (dar nu suprimarea) funcţiilor, procedurilor, vizualizărilor,

secventelor, sinonimelor referitoare la tabel.

Odată executată, instrucţiunea DROP TABLE este ireversibilă. Ca şi în

cazul celorlalte instrucţiuni ale limbajului de definire a datelor, această comandă

nu poate fi anulată (ROLLBACK).

Instrucţiunea DROP

Exemplu:

DROP TABLE DEPARTAMENT ;

DROP TABLE COD_CLIENT CASCADE CONSTRAINTS; (Oracle)

Pentru ştergerea întregului conţinut al unui tabel şi eliberarea spaţiului

de memorie ocupat de acesta, sistemul Oracle oferă instrucţiunea:

TRUNCATE TABLE NUME_TABEL;

Fiind o instrucţiune DDL, aceasta nu poate fi anulată ulterior (printr-o

operaţie ROLLBACK). Ea reprezintă o alternativă a comenzii DELETE din

limbajul de prelucrare a datelor(DML). De remarcat că instrucţiunea DELETE

nu eliberează spaţiul de memorie. Comanda TRUNCATE este mai rapidă

deoarece nu generează informaţie ROLLBACK şi nu activează declanşatorii

asociaţi operaţiei de ştergere. Dacă tabelul este „părintele“ unei constrângeri de

integritate referenţială, el nu poate fi trunchiat. Pentru a putea fi aplicată

instrucţiunea TRUNCATE, constrângerea trebuie să fie mai întâi dezactivată.

In DDL, informaţiile despre tabele se găsesc în vizualizarea USER_TABLES.

Dintre cele mai importante coloane ale acesteia, se remarca le obtinem cu

instructiunea:

DESCRIBE USER_TABLES;

TABLE_NAME Numele tabelului

TABLESPACE

_NAME

Spaţiul tabel în care se află tabelul

Page 82: Curs Sinteza SQL

CLUSTER_NAME Numele cluster-ului din care face parte tabelul

PCT_FREE Procentul de spaţiu păstrat liber în interiorul fiecărui bloc

PCT_USED Procentul de spaţiu ce poate fi utilizat în fiecare bloc

INI_TRANS Numărul iniţial de tranzacţii concurente în interiorul unui bloc

NITIAL_EXTENT Dimensiunea spaţiului alocat pentru prima extensie

NEXT_EXTENT Dimensiunea spaţiului alocat pentru următoarea extensie

MIN_EXTENTS Numărul minim de extensii ce se alocă la crearea unui tabel

MAX_EXTENTS Numărul maxim de extensii ce se alocă la crearea unui tabel

PCT_INCREASE Procentul cu care creşte dimensiunea unei extensii

BACKED_UP Y sau N, după cum tabelului i-a fost făcută o copie de

siguranţă de la ultima modificare

NUM_ROWS Numărul de înregistrări din tabel

BLOCKS Numărul de blocuri utilizate de tabel

EMPTY_BLOCKS Numărul de blocuri ce nu conţin date

AVG_SPACE Spaţiul mediu liber din tabel

AVG_ROW_LEN Lungimea medie, în octeţi, a unei linii

TABLE_LOCK ENABLED (activat) sau DISABLED (dezactivat): este activată

sau nu blocarea tabelului

PARTITIONED YES sau NO, indică dacă tabelul este partiţionat (sau nu)

TEMPORARY Y sau N, indică dacă tabelul este temporar (sau nu)

NESTED YES sau NO, indică dacă tabelul este imbricat (sau nu)

EXEMPLU:

SELECT TABLE_NAME, NUM_ROWS, NESTED

FROM USER_TABLES;

EXEMPLU:

SELECT 'DROP TABLE' || OBJECT_NAME || ';'

FROM USER_OBJECTS

WHERE OBJECT_TYPE = 'TABLE';

Page 83: Curs Sinteza SQL

Instrucţiunea CREATE INDEX

Indexurile sunt instrumente puternice, deoarece permit sistemului să găsescă

datele mult mai repede, tot aşa cum indexul unei cărţi ne permite să găsim mai rapid

ceea ce ne interesează. De asemenea, indexurile pe coloanele cheilor externe cresc

mult peformanţele la unirea tabelelor. Sistemul SGBD întreţine automat indexul, dar

activitatea de întreţinere consumă din resursele calculatorului.

Un index este un obiect al schemei unei baze de date care:

creşte viteza de execuţie a cererilor;

garantează că o coloană conţine valori unice.

Cuvântul cheie opţional UNIQUE defineşte indexul ca unic, însemnând că nu

pot exista două rânduri din tabel cu exact acceaşi combinaţie de valori în

coloanele specificate.

Cuvântul cheie opţional ASC creează indexul în ordine crescătoare, în timp ce

DESC creează indexul în ordine descrescătoare. Dacă nu este specificată nici una

dintre cele două opţiuni, ordinea prestabilită este crescătoare.

Un index trebuie să aibă cel puţin o coloană, dar, nu există o limită superioară

a numărului de coloane.

Server-ul Oracle utilizează identificatorul ROWID pentru regăsirea liniilor în structura fizică a bazei de date. Indexul, din punct de vedere logic, este compus dintr-o valoare cheie şi din identificatorul adresă ROWID.

Cheia indexului poate fi coloana unui tabel sau concatenarea mai multor coloane (numărul maxim de coloane care pot defini cheia indexului este 32). Coloanele care apar în cheia indexului trebuie declarate NOT NULL în tabel.

Indecşii sunt utilizaţi şi întreţinuţi automat de către server-ul Oracle. Odată creat indexul, el nu necesită o acţiune directă din partea utilizatorului.

Indecşii pot fi creaţi în două moduri:

automat, de server-ul Oracle (PRIMARY KEY, UNIQUE);

manual, de către utilizator (CREATE INDEX).

Server-ul Oracle creează automat un index unic atunci când se defineşte o

constrângere PRIMARY KEY sau UNIQUE asupra unei coloane sau unui grup de

coloane. Numele indexului va fi acelaşi cu numele constrângerii.

Indecşii, fiind obiecte ale schemei bazei, beneficiază de procesul de

definire a unui obiect.

Crearea unui index (care nu este obligatoriu unic) pe una sau mai multe

coloane ale unui tabel se face prin comanda:

CREATE [UNIQUE] INDEX <nume_index>

ON [<nume_schema>.] <nume_tabel>

(<nume_col> [ASC | DESC], <nume_col> [ASC | DESC], …);

Page 84: Curs Sinteza SQL

Când este creat un index, un segment de date este rezervat automat în spaţiul

tabel. Alocarea de memorie este controlată prin clauzele INITIAL, PCTINCREASE,

PCTFREE, NEXT, care pot să apară în comanda CREATE INDEX.

Exemplu:

1) Să se creeze un index descrescător relativ la coloana adresa din tabelul cititor.

CREATE INDEX cititor_id

ON cititor (adresa DESC);

2) Să se afişeze informaţiile referitoare la indexul cititor_idx.

SELECT TABLE_NAME

FROM USER_INDEXES

WHERE INDEX_NAME=‘CITITOR_IDX‘;

3) Să se afişeze toate indexurile(numele tabelelor, numele indexului si daca a fost

sau nu generat)

SELECT TABLE_NAME, INDEX_NAME, TABLE_TYPE

FROM USER_INDEXES;

4)Să se creeze un index explicit, referitor la cheia primara a unui tabel.

CREATE TABLE exem

( cod_id NUMBER(6)

PRIMARY KEY USING INDEX

(CREATE INDEX cod_id_idx ON exem (cod_id)),

nume VARCHAR2(20));

Mai mulţi indecşi asupra unui tabel nu implică întotdeuna interogări mai

rapide. Fiecare operaţie LMD care este permanentizată asupra unui tabel cu

indecşi asociaţi presupune actualizarea indecşilor respectivi.

Prin urmare, este recomandată crearea de indecşi numai în anumite

situaţii:

coloana conţine o varietate mare de valori;

coloana conţine un număr mare de valori null;

una sau mai multe coloane sunt utilizate frecvent împreună într-o

clauză WHERE sau într-o condiţie de join;

tabelul este mare şi este de aşteptat ca majoritatea interogărilor

asupra acestuia să regăsească mai puţin de 2-4% din linii.

Crearea unui index nu este recomandată în următoarele cazuri:

tabelul este mic;

coloanele nu sunt utilizate des în cadrul unei condiţii dintr-o cerere;

majoritatea interogărilor regăsesc mai mult de 2-4% din liniile

tabelului;

tabelul este actualizat frecvent;

coloanele indexate sunt referite în expresii.

In concluzie, ce tabele sau ce coloane trebuie (sau nu) indexate?

Page 85: Curs Sinteza SQL

indexaţi tabelele pentru care interogările selectează un număr redus de rânduri

(sub 5%);

indexaţi tabelele care sunt interogate folosind clauze SQL simple;

nu indexaţi tabelele ce conţin puţine înregistrări (accesul secvenţial este mai

simplu);

nu indexaţi tabelele care sunt frecvent actualizate, deoarece ştergerile, inserările şi modificările sunt îngreunate de indecşi;

indexaţi coloanele folosite frecvent în clauza WHERE sau în clauza ORDER BY;

nu indexaţi coloanele ce conţin date asemănătoare (puţine valori distincte);

Exemplu: Pentru a asigura că server-ul Oracle utilizează indexul şi nu efectuează o

căutare asupra întregului tabel, valoarea funcţiei corespunzătoare expresiei indexate trebuie să nu fie null în interogările ulterioare creării indexului. Următoarea instrucţiune garantează utilizarea indexului dar, în absenţa clauzei WHERE, server-ul Oracle ar putea cerceta întreg tabelul.

SELECT * FROM artist WHERE UPPER(nume) IS NOT NULL

ORDER BY UPPER(nume);

Exemplu: Să se creeze tabelul artist, specificându-se indexul asociat cheii primare.

CREATE TABLE artist( cod_artist NUMBER PRIMARY KEY USING INDEX (CREATE INDEX artist_cod_idx ON artist(cod_artist)), nume VARCHAR2(30) NOT NULL, prenume VARCHAR2(30));

INSERT INTO ARTIST VALUES(1,‟Grigorescu‟,‟Dan‟); INSERT INTO ARTIST VALUES(2,‟ene‟,‟ana‟);

CREATE INDEX upper_nume_idx ON artist (UPPER(nume));

Indexul creat prin instrucţiunea precedentă facilitează prelucrarea unor interogări precum:

SELECT * FROM artist

WHERE UPPER(nume) = 'GRIGORESCU';

Ştergerea unui index se face prin comanda:

DROP INDEX nume_index [ON [nume_schema.] nume_tabel]

Pentru a suprima indexul trebuie ca acesta să se găsească în schema personală sau să ai privilegiul de sistem DROP ANY INDEX.

Page 86: Curs Sinteza SQL

Pentru a reconstrui un index se pot folosi două metode:

se şterge indexul (DROP INDEX) şi se recreează (CREATE INDEX);

se utilizează comanda ALTER INDEX cu opţiunea REBUILD.

Modificarea parametrilor de stocare a indecşilor (STORAGE), alocarea

(ALLOCATE EXTENT) şi dealocarea (DEALLOCATE UNUSED) manuală a spaţiului utilizat de un index se pot realiza cu ajutorul comenzii ALTER INDEX. Începând cu Oracle9i, este posibilă modificarea structurii indecşilor prin comanda ALTER INDEX.

Validarea unui index, adică verificarea integrităţii indexului specificat

pentru un tabel, se face prin comanda:

VALIDATE INDEX nume_index [ON nume_tabel] [WITH LIST]

Oracle8 foloseşte următoarele tipuri de indecşi:

index de tip arbore B* – creat la executarea unei comenzi standard CREATE INDEX;

index partiţionat – folosit în cazul tabelelor mari pentru a stoca valorile coloanei indexate în mai multe segmente;

index de cluster – bazat pe coloanele comune ale unui cluster;

index cu cheie inversă – sunt B* arbori, dar care stochează datele în mod invers;

index de tip bitmap – nu se stochează valorile efective ale coloanei indexate, ci un bitmap format pe baza acestor valori.

Versiunea Oracle8 permite construirea de tabele organizate pe bază de index. În acest caz, datele sunt stocate în indexul asociat. Un astfel de tabel poate fi manipulat de către aplicaţii la fel ca un tabel obişnuit, folosind comenzi SQL. Diferenţa constă în faptul că în cazul tabelului organizat pe bază de index, toate operaţiile sunt efectuate numai asupra indexului. În loc ca fiecare intrare a indexului să conţină valoarea coloanei sau coloanelor indexate şi valoarea ROWID (care identifică unic un rând) pentru rândul corespunzător, ea conţine întreg rândul.

Coloana sau coloanele după care se face indexarea sunt cele care constituie cheia primară a tabelului.

Informaţii referitoare la indecşi şi la coloanele care îi definesc pot fi

regăsite în vizualizările USER_INDEXES, respectiv USER_IND_COLUMNS din dicţionarul datelor. Dintre coloanele tabelului USER_INDEXES se remarcă:

INDEX_NAME Numele indexului

INDEX_TYPE Tipul indexului (NORMAL, LOB, CLUSTER etc.)

TABLE_OWNER Proprietarul tabelului indexat

TABLE_NAME Numele tabelului indexat

TABEL_TYPE Tipul tabelului indexat (TABLE, CLUSTER etc.)

UNIQUENESS Starea de unicitate (UNIQUE, NONUNIQUE)

TABLESPACE_NAME Spaţiul tabel în care este stocat indexul

INITIAL_EXTENT Spaţiul alocat pentru prima extensie

NEXT_EXTENT Spaţiul alocat pentru următoarea extensie

MIN_EXTENTS Numărul minim de extensii alocate

MAX_EXTENTS Numărul maxim de extensii

PCT_INCREASE Procentul cu care cresc extensiile

BLEVEL Nivelul din B-arbore. Acesta arată adâncimea indexului de

Page 87: Curs Sinteza SQL

la ramuri la frunze

LEAF_BLOCKS Numărul de blocuri frunză din index

DISTINCT_KEYS Numărul de chei distincte în index

STATUS Starea indexului (VALID, INVALID, DIRECT_LOAD)

NUM_ROWS Numărul de linii utilizate. Acesta nu trebuie să includă valorile NULL din tabelul de bază

PARTITIONED Determină dacă indexul este partiţionat (YES sau NO)

GENERATED Determină dacă sistemul a generat numele indexului (Y) sau utilizatorul (N)

Exemplu: Să se obţină informaţii referitoare la indecşii tabelului carte. SELECT a.index_name, a.column_name,

a.column_position poz, b.uniqueness

FROM user_indexes b, user_ind_columns a

WHERE a.index_name = b.index_name

AND a.table_name = ’carte’;

Secvenţe

O secvenţă este un obiect în baza de date care serveşte pentru a genera întregi

unici în sistemele multi-utilizator, evitând apariţia conflictelor şi a blocării.

Secvenţele sunt memorate şi generate indiferent de tabele aceeaşi secvenţă

poate fi utilizată pentru mai multe tabele. O secvenţă poate fi creată de un utilizator şi

poate fi partajată de mai mulţi utilizatori.

Crearea unei secvenţe se face cu ajutorul comenzii:

CREATE SEQUENCE [<nume_schema>.]<nume_secventa>

[INCREMENT BY n] [START WITH m]

[{MAXVALUE n | NOMAXVALUE}] [{MINVALUE n | NOMINVALUE}]

[{CACHE k | NOCACHE}]

CACHE k | NOCACHE specifică numărul de valori alocate de server-ul Oracle pe

care le va păstra în memoria cache pentru a oferi utilizatorilor un acces rapid

(implicit sunt alocate 20 de valori);

O secvenţă este referită într-o comandă SQL cu ajutorul pseudo-coloanelor:

NEXTVAL – referă valoarea următoare a secvenţei;

CURRVAL – referă valoarea curentă a secvenţei.

NEXTVAL şi CURRVAL pot fi folosite în:

clauza VALUES a unei comenzi INSERT;

clauza SET a unei comenzi UPDATE;

lista SELECT a unei subcereri dintr-o comanda INSERT;

lista unei comenzi SELECT.

NEXTVAL şi CURRVAL nu pot fi folosite în:

subinterogare in SELECT, DELETE sau UPDATE;

interogarea unei vizualizări;

comandă SELECT cu operatorul DISTINCT;

Page 88: Curs Sinteza SQL

comandă SELECT cu clauza GROUP BY, HAVING sau ORDER BY;

clauza WHERE a unei comenzi SELECT;

condiţia unei constrângeri CHECK;

valoarea DEFAULT a unei coloane într-o comandă CREATE TABLE sau ALTER TABLE;

comandă SELECT care este combinată cu altă comandă SELECT printr-un operator mulţime (UNION, INTERSECT, MINUS).

Din dicţionarul datelor pot fi obţinute informaţii despre secvenţe folosind vizualizarea USER_SEQUENCES.

1) Să se creeze o secvenţă domeniuseq care să fie utilizată pentru a insera noi domenii în tabelul domeniu şi să se insereze un nou domeniu.

2) Să se afişeze informaţiile referitoare la secvenţa domeniuseq.

CREATE SEQUENCE domeniuseq

START WITH 1

INCREMENT BY 1;

INSERT INTO domeniu

VALUES (domeniuseq.NEXTVAL,’Informatica’);

SELECT INCREMENT_BY,MAX_VALUE, MIN_VALUE

FROM USER_SEQUENCES

WHERE SEQUENCE_NAME = 'domeniuseq';

Modificarea unei secvenţe se face prin comanda ALTER SEQUENCE.

Sintaxa comenzii este similară instrucţiunii CREATE SEQUENCE , dar:

noua valoare maximă pentru MAXVALUE nu poate fi mai mică decât valoarea

curentă;

opţiunea START WITH nu poate fi modificată de comandă.

Suprimarea unei secvenţe se face cu ajutorul comenzii:

DROP SEQUENCE [<nume_schema>.]<nume_secventa>;

După ce a fost ştearsă, secvenţa nu mai poate fi referită. Pentru a putea şterge

sau modifica secvenţa trebuie fie să fi proprietarul acesteia, fie să ai privilegiul de

sistem DROP ANY SEQUENCE, respectiv privilegiul ALTER SEQUENCE.

DROP SEQUENCE domeniuseq;

Comentarii

Sistemul Oracle oferă posibilitatea de a comenta obiectele create, printr-un

text care este inserat în dicţionarul datelor. Comentariul se poate referi la tabele,

vizualizări, clişee sau coloane.

COMMENT ON {TABLE nume_obiect | COLUMN

nume_obiect.nume_coloana}IS ‘text comentariu‘

Page 89: Curs Sinteza SQL

Sinonime

Oracle oferă posibilitatea de a atribui mai multe nume aceluiaşi obiect. Aceste

nume adiţionale sunt numite sinonime (synonymes). Ele sunt utile deoarece permit

simplificarea formulării cererii şi referirea la obiecte, fără a fi nevoie să se specifice

proprietarii obiectelor sau localizarea acestora.

Spre deosebire de alias a cărui durată de viaţă este limitată la cererea ce

conţine alias-ul, sinonimele sunt salvate în dicţionarul datelor şi pot fi reutilizate.

Sistemul Oracle permite crearea de sinonime pentru obiecte de tipul:

tabel, vizualizare, secvenţă, funcţie, procedură, pachet, clişeu, sinonim.

CREATE [PUBLIC] SYNONYM [schema.]nume_sinonim

FOR [schema.]obiect

Exemplu:

CREATE SYNONYM artist1 FOR artist;

SELECT * from user_objects;

SELECT * from artist1;

Administratorul bazei poate produce şi poate suprima sinonime publice

sau private, iar utilizatorii pot genera sau suprima doar sinonime private. Pentru

suprimarea unui sinonim din baza de date se utilizează comanda:

DROP [PUBLIC] SYNONYM [schema.]nume_sinonim

Instrucţiunea CREATE VIEW

O vizualizare este o interogare SQL stocată, care poate fi referită de

instrucţiuni1e SQL DML şi DQL ca şi cum ar fi un tabel real. Unii consideră că

vizualizările sunt „tabele virtuale", deoarece se comportă la fel ca tabelele, dar

nu există ca tabele fizice. Sintaxa generală a instucţiunii CREATE VIEW este:

CREATE [OR REPLACE] VIEW nume_vizualizare AS interogare sql;

Cuvântul cheie opţional OR REPLACE elimină necesitatea de a sterge o

vizualizare existentă înainte de a o crea din nou.

Numele vizualizării trebuie să respecte aceleaşi reguli de denumire ca şi

tabelele şi alte obiecte ale bazei de date.

Interogarea SQL inclusă în definiţia vizualizării poate fi orice instrucţiunea

SQL SELECT validă.

Page 90: Curs Sinteza SQL

Vizualizări

Vizualizarea (view) este un tabel logic (virtual) relativ la date din una sau mai

multe tabele sau vizualizări. Vizualizarea este definită plecând de la o cerere a

limbajului de interogare a datelor, moştenind caracteristicile obiectelor la care se

referă. Vizualizarea, fiind virtuală, nu solicită o alocare de memorie pentru date. Ea

este definită în DD cu aceleaşi caracteristici ca şi un tabel.

Textul cererii care defineşte vizualizarea este salvat în DD. Nucleul Oracle

determină fuzionarea cererii relative la vizualizare cu comanda de definire a

vizualizării, analizează rezultatul fuziunii în zona partajată şi execută cererea.

Oracle transformă cererea referitoare la o vizualizare într-o cerere relativă

la tabelele de bază. Vizualizarea este memorata in DD sub forma unui SELECT.

Dacă sunt utilizate clauzele UNION, GROUP BY şi CONNECT BY, atunci

Oracle nu determină fuzionarea, el va rezolva vizualizarea şi apoi va aplica

cererea rezultatului obţinut.

O vizualizare reflectă la orice moment conţinutul exact al tabelelor de bază.

Orice modificare efectuată asupra tabelelor se repercutează instantaneu asupra

vizualizării. Ştergerea unui tabel implică invalidarea vizualizărilor asociate tabelului

şi nu ştergerea acestora.

Vizualizările sunt definite pentru:

furnizarea unui nivel mai înalt de securizare a bazei;

simplificarea formulării unei cereri;

mascarea complexităţii datelor;

afişarea datelor într-o altă reprezentare decât cea a tabelelor de bază;

asigurarea independenţei datelor;

asigurarea confidenţialităţii anumitor informaţii;

definirea constrângerilor de integritate;

restricţionarea acesului la date.

Vizualizările pot fi simple şi complexe. O vizualizare simplă extrage date

dintr-un singur tabel, nu conţine funcţii sau grupări de date şi asupra ei pot fi

efectuate operaţii LMD.

O vizualizare este considerată complexă dacă extrage date din mai multe

tabele, conţine funcţii sau grupări de date şi nu permite întotdeauna (prin

intermediul său) operaţii LMD asupra tabelelor de bază.

Operaţiile LMD asupra vizualizărilor complexe sunt restricţionate de

următoarele reguli:

nu se poate insera, actualiza sau şterge o linie dintr-o vizualizare dacă

aceasta conţine funcţii grup, clauza GROUP BY, cuvântul cheie

DISTINCT sau pseudocoloana ROWNUM;

nu se poate adăuga sau modifica o linie dintr-o vizualizare, dacă

aceasta conţine coloane definite prin expresii;

nu pot fi adăugate linii printr-o vizualizare, dacă tabelul de bază

conţine coloane care au constrângerea NOT NULL şi nu apar în lista

SELECT a vizualizării.

Pentru a obţine informaţii referitoare la vizualizările definite, se pot

interoga vizualizările USER_VIEWS şi ALL_VIEWS din dicţionarul datelor.

Page 91: Curs Sinteza SQL

Textul instrucţiunii SELECT care defineşte o vizualizare este stocat într-o

coloană de tip LONG, numită TEXT.

Atunci când datele sunt accesate prin intermediul unei vizualizări, server-

ul Oracle efectuează următoarele operaţii:

recuperează definiţia acesteia din USER_VIEWS;

verifică privilegiile de acces la tabelele ei de bază;

converteşte cererea într-o operaţie echivalentă asupra tabelelor de

bază.

Crearea unei vizualizări se realizează cu ajutorul comenzii:

CREATE [OR REPLACE][FORCE | NOFORCE] VIEW

[<nume_schema>.]<nume_view> [(<alias>[,<alias>]…)]

AS <cerere_SELECT>

[WITH {CHECK OPTION [CONSTRAINT <nume_constrangere>] |

READ ONLY }];

– OR REPLACE recreează vizualizarea dacă aceasta deja există.

– FORCE creează vizualizarea chiar dacă tabelul de bază nu există sau chiar dacă

vizualizarea face referinţă la obiecte care încă nu sunt create. Deşi vizualizarea va

fi creată, utilizatorul nu poate să o folosească.

– NO FORCE este implicită şi se referă la faptul că vizualizarea este creată numai

dacă tabelele de bază există.

– Cererea este o comandă SELECT care poate să conţină alias pentru coloane.

– WITH CHECK OPTION specifică faptul că reactualizarea datelor din tabele

(inserare sau modificare) se poate face numai asupra datelor selectate de

vizualizare (care apar în clauza WHERE).

– WITH READ ONLY asigură că nici o operaţie LMD nu poate fi executată asupra

vizualizării.

Exemplu:

Să se genereze o vizualizare care conţine informaţii referitoare

la împrumutul cărţilor şi în care să fie implementată constrîngerea că orice carte, care

există într-un singur exemplar, poate fi împrumutată maximum 15 zile.

CREATE VIEW imprumutare

AS SELECT *

FROM imprumuta

WHERE codel NOT IN

(SELECT codel

FROM carte

WHERE nrex = 1)

OR datares - dataim < 15

WITH CHECK OPTION;

Cererea care defineşte vizualizarea poate fi complexă, incluzând join-uri,

grupări şi subcereri, însă nu poate conţine clauza ORDER BY. Dacă este necesar,

această clauză poate fi specificată la interogarea vizualizării. Interogarea unei

vizualizări este similară celei unui tabel. Numărul coloanelor specificate în

definiţia vizualizării trebuie să fie egal cu cel din lista asociată comenzii

Page 92: Curs Sinteza SQL

SELECT.

Asupra cererii care defineşte vizualizarea se impun următoarele restricţii:

nu pot fi selectate pseudocoloanele CURRVAL şi NEXTVAL ale unei

secvenţe;

dacă sunt selectate pseudocoloanele ROWID, ROWNUM sau LEVEL,

acestora trebuie să li se specifice alias-uri;

dacă cererea selectează toate coloanele unui tabel, utilizând simbolul

„*“, iar ulterior se adaugă coloane noi tabelului, vizualizarea nu va

conţine acele coloane până la recrearea sa printr-o instrucţiune

CREATE OR REPLACE VIEW;

pentru vizualizările obiect, numărul şi tipul elementelor selectate de

cerere trebuie să coincidă cu cel al atributelor de pe primul nivel al

tipului obiect.

Aportul versiunii Oracle9i în ceea ce priveşte instrucţiunea CREATE

VIEW constă în posibilitatea:

creării de subvizualizări ale vizualizărilor obiect;

definirii de constrângeri asupra vizualizărilor.

Exemplu:

a) Să se creeze o vizualizare care conţine numele şi prenumele artistului,

numărul operelor sale şi valoarea medie a acestora.

CREATE VIEW artist_nr_val(nume, numar_opere, val_medie)

AS SELECT a.nume || ' ' || a .prenume "Nume si prenume",

COUNT(o. cod_opera) numar, AVG(o.valoare) medie

FROM opera o, artist a

WHERE o.cod_artist = a.cod_artist

GROUP BY o.cod_artist, a.nume, a.prenume;

b) Să se creeze vizualizarea sculptura ce va conţine codul operei, data

achiziţiei, codul artistului şi stilul operelor al căror tip este

„sculptura“.

CREATE OR REPLACE VIEW sculptura

(cod_sculptura, informatii, cod_sculptor, stil)

AS SELECT cod_opera,

'Sculptura ' || titlu ||

' a fost achizitionata la data ' ||

data_achizitiei, cod_artist, stil

FROM opera

WHERE tip = 'sculptura';

Modificarea unei vizualizări presupune modificarea definiţiei acesteia.

Pentru a înlocui o vizualizare trebuie avut privilegiul de sistem necesar pentru

distrugerea şi crearea acesteia. Înlocuirea se poate face în două moduri.

Vizualizarea poate fi distrusă (DROP VIEW) şi apoi recreată (CREATE) cu

noua definiţie. Atunci când este distrusă, toate privilegiile sunt retrase.

Aceste privilegii trebuie să fie create pentru noua vizualizare.

Vizualizarea poate fi recreată prin redefinire cu instrucţiunea CREATE

VIEW, dar cu clauza OR REPLACE. Această metodă conservă toate

privilegiile curente.

Page 93: Curs Sinteza SQL

In Oracle9i este posibila adaugarea de constrangeri unei vizualizari prin

comanda ALTER VIEW.

Modificarea unui vizualizări are următoarele efecte:

definiţia vizualizării din DD este actualizată;

nici unul din obiectele de bază nu este afectat de înlocuire;

toate restricţiile care existau în vizualizarea originală sunt distruse;

toate vizualizările şi programele PL/SQL dependente de vizualizarea

înlocuită devin invalide.

Suprimarea unei vizualizări se realizează prin comanda DROP VIEW care

şterge definiţia vizualizării din baza de date.

DROP VIEW <nume_view> [CASCADE CONSTRAINT];

Ştergerea vizualizării nu va afecta tabelele relativ la care a fost definită

vizualizarea. Aplicaţiile şi vizualizările care se bazează pe vizualizarea suprimată

devin invalide. Pentru a suprima o vizualizare, utilizatorul trebuie să aibă privilegiul

DROP ANY VIEW sau să fie creatorul vizualizării respective.

Similar opţiunii corespunzătoare din comanda DROP TABLE, clauza

CASCADE CONSTRAINTS permite suprimarea tuturor constrângerilor de

integritate referenţială corespunzătoare cheilor primare şi unice din vizualizarea

supusă ştergerii. Dacă se omite această clauză şi există astfel de constrângeri,

instrucţiunea DROP VIEW va eşua.

Recompilarea unei vizualizări permite detectarea eventualelor erori

referitoare la vizualizare, înaintea executării vizualizării. După fiecare modificare a

tabelelor de bază este recomandabil ca vizualizarea să se recompileze:

ALTER VIEW <nume_view> COMPILE;

Reactualizarea tabelelor implică reactualizarea corespunzătoare a

vizualizărilor!!!

Reactualizarea vizualizărilor implică reactualizarea tabelelor de bază?

NU! Există restricţii care trebuie respectate!!!

Nu pot fi modificate date din vizualizare sau adaugate date prin vizualizare,

daca aceasta contine coloane definite prin expresii.

Nu pot fi înserate, şterse sau actualizate date din vizualizări ce conţin:

operatorul DISTINCT; clauzele GROUP BY, HAVING, START WITH,

CONNECT BY; pseudo-coloana ROWNUM; funcţii grup; operatori de

mulţimi.

Nu pot fi inserate sau actualizate date care ar încălca constrângerile din

tabelele de bază.

Nu pot fi inserate sau actualizate valorile coloanelor care rezultă prin calcul.

Nu se pot face operaţii LMD asupra coloanelor calculate cu DECODE.

Alături de restricţiile prezentate anterior, aplicabile tuturor

vizualizărilor, există restricţii specifice, aplicabile vizualizărilor bazate pe mai

multe tabele.

Regula fundamentală este că orice operaţie INSERT, UPDATE sau DELETE

pe o vizualizare bazată pe mai multe tabele poate modifica datele doar din unul din

tabelele de bază. In care???

Page 94: Curs Sinteza SQL

Un tabel de bază al unei vizualizări este protejat prin cheie (key preserved

table) dacă orice cheie selectată a tabelului este de asemenea şi cheie a vizualizării.

Deci, un tabel protejat prin cheie este un tabel ale cărui chei se păstrează şi la nivel de

vizualizare. Pentru ca un tabel să fie protejat prin cheie nu este necesar ca tabelul să

aibă toate cheile selectate în vizualizare. Este suficient ca, atunci când cheia tabelului

este selectată, aceasta să fie şi cheie a vizualizării.

Asupra unui join view pot fi aplicate instrucţiunile INSERT, UPDATE

sau DELETE, doar dacă sunt îndeplinite următoarele condiţii:

instrucţiunea LMD afectează numai unul dintre tabelele de bază;

în cazul instrucţiunii UPDATE, toate coloanele care pot fi reactualizate trebuie

să corespundă coloanelor dintr-un tabel protejat prin cheie (în caz contrar,

Oracle nu va putea identifica unic înregistrarea care trebuie reactualizată);

în cazul instrucţiunii DELETE, rândurile unei vizualizări pot fi şterse numai

dacă există un tabel în join protejat prin cheie şi numai unul (în caz contrar,

Oracle nu ar şti din care tabel să şteargă);

în cazul instrucţiunii INSERT, toate coloanele în care sunt inserate valori

trebuie să provină dintr-un tabel protejat prin cheie.

ALL_UPDATABLE_COLUMNS, DBA_UPDATABLE_COLUMNS şi USER_UPDATABLE_COLUMNS sunt vizualizări din DD ce conţin informaţii referitoare la coloanele vizualizărilor existente, care pot fi reactualizate.

Exmplu: 1. Să se creeze un view ce conţine câmpurile nume, prenume, job din tabelul

salariat. 2. Să se insereze, să se actualizeze şi să se şteargă o înregistrare în acest view. Ce

efect vor avea aceste acţiuni asupra tabelului de bază?

CREATE VIEW vederea2 AS SELECT nume, prenume, job

FROM salariat;

Nu se pot face inserari deoarece view-ul nu conţine cheia primară!

INSERT INTO vederea2

VALUES ('Popescu','Valentin','grafician');

va genera eroarea:

ORA-01400: cannot insert NULL into

("SCOTT"."SALARIAT"."COD_SALARIAT")

Actualizarea job-ului salariatului având numele "Popescu":

UPDATE vederea2 SET job = 'programator'

WHERE nume = 'Popescu';

SELECT nume, prenume, job FROM salariat;

Ştergerea înregistrării referitoare la salariatul având numele "Popescu":

DELETE vederea2

WHERE nume = 'Popescu';

Page 95: Curs Sinteza SQL

Operaţiile care se realizează asupra view-ului se realizează şi în tabelul

salariat. Pentru un caz mai general, când view-ul conţine cheia externă a tabelului de

bază, sunt permise modificări ale view-ului, dacă acestea nu afectează cheia externă.

Exemplu:

Să se creeze un view care conţine câmpurile nume, prenume, job din tabelul

salariat. Să se introducă în view doar persoanele care sunt graficieni.

CREATE VIEW vederea21

AS SELECT nume, prenume, job

FROM salariat

WHERE job = 'grafician'

WITH CHECK OPTION;

Să se creeze o vizualizare care să conţină cod_salariat, nume, prenume din tabelul salariat şi coloana tip din tabelul grafician. Apoi să se insereze, să se actualizeze şi să se şteargă o înregistrare din acest view (vizualizarea conţine cheia primară cod_salariat din tabelele salariat şi grafician).

CREATE VIEW vederea4

AS SELECT s.cod_salariat,nume,prenume,tip

FROM salariat s, grafician g

WHERE s.cod_salariat=g.cod_salariat;

În cazul inserării unei înregistrări pentru care se specifică toate câmpurile:

INSERT INTO vederea4

VALUES (30,'Popescu','Valentin','artist plastic');

va apare următoarea eroare:

ORA-01776: cannot modify more than one base TABLE through

a join view

Pot fi inserate date doar într-un tabel de bază (în oricare, dar în unul singur) prin intermediul view-ului, astfel:

INSERT INTO vederea4 (cod_salariat, nume)

VALUES (30, 'Popescu');

Comanda pentru ştergerea unei înregistrări:

DELETE vederea4

WHERE cod_salariat = 3;

va genera următoarea eroare:

ORA-01752: cannot delete from view without exactly one

key-preserved TABLE.

Modificarea unei înregistrări se face prin secvenţa care urmează. Toate

actualizările care se fac în view se fac şi în tabelele de bază.

UPDATE vederea4

SET tip = 'designer'

WHERE cod_salariat = 3;

Exemplu:

Care dintre coloanele unei vizualizări sunt actualizabile?

SELECT column_name, updatable FROM user_updatable_columns

Page 96: Curs Sinteza SQL

WHERE table_name = 'vederea4';

Exemplu:

1. Să se creeze un view (vederea3) care să conţină, pentru fiecare categorie de salariat, salariile medii şi numărul de angajaţi din tabelul salariat.

2. Să se insereze, să se actualizeze şi să se şteargă o înregistrare în view.

CREATE VIEW vederea3 (nr, job, salmed)

AS SELECT COUNT(*), job, AVG(salariu)

FROM salariat

GROUP BY job;

Nu se pot face inserări, actualizări sau ştergeri într-un view ce conţine funcţii grup. După oricare din aceste operaţii apare acelaşi mesaj:

ORA-01732: data manipulation operation not legal on

this view

Exemplu: Să se creeze o vizualizare care să conţină coloanele cod_contractant, adresa,

telefon din tabelul contractant şi coloanele nr_contract, tip_contract, data_incheiere din tabelul contract. Să se insereze o înregistrare în vizualizare.

CREATE VIEW vederea44

AS SELECT c.cod_contractant, adresa, telefon,

co.nr_contract, tip_contract,

data_incheiere

FROM contractant c, contract co

WHERE c.cod_contractant=co.cod_contractant;

La inserarea unei înregistrări căreia i se specifică valorile tuturor câmpurilor din ambele tabele:

INSERT INTO vederea44(cod_contractant, adresa,

nr_contract, data_incheiere)

VALUES (200, 'Str. Marmurei, 14', '6235',

TO_DATE('January 03,2002','Month

dd,yyyy'));

se obţine eroarea:

ORA-01779: cannot modify a column which maps to a non

key-preserved TABLE

Cele două tabele de bază, contractant şi contract, se află într-o relaţie ―one-to-many‖, iar view-ul creat conţine cheile primare din ambele tabele.

Doar tabelul contract este protejat prin cheie şi, prin urmare, doar el poate fi modificat prin intermediul view-ului. Aceasta, deoarece ar putea exista mai multe înregistrări în view, cu aceeaşi valoare corespunzătoare câmpului cod_contractant (CP în contractant).

Exact aceeaşi eroare se obţine dacă încercăm inserarea unei înregistrări în vederea44, specificând fie şi numai un câmp provenind din tabela contractant (indiferent dacă el conţine sau nu CP).

Singura operaţie de inserare permisă este aceea efectuată prin specificarea cheilor provenind doar din tabelul contract. Astfel, prin executarea comenzii:

INSERT INTO vederea44(nr_contract, tip_contract)

VALUES ('6234', 0);

Page 97: Curs Sinteza SQL

este creată o înregistrare, dar este modificat şi tabelul contract. Dacă la inserţie nu se specifică cheia primară din contract:

INSERT INTO vederea44(tip_contract)

VALUES (1);

ORA-01400: mandatory (NOT NULL) column is missing or NULL

during insert

Cererea din definiţia vizualizării poate fi restricţionată prin clauzele WITH READ ONLY şi WITH CHECK OPTION. Opţiunea WITH READ ONLY asigură că nu pot fi efectuate operaţii LMD asupra vizualizării. Constrângerea WITH CHECK OPTION garantează faptul că va fi permisă, prin intermediul vizualizării, numai inserarea sau actualizarea de linii accesibile acesteia (care sunt selectate de cerere). Prin urmare, această opţiune asigură constrângeri de integritate şi verificări asupra validităţii datelor inserate sau actualizate.

Opţiunea WITH CHECK OPTION nu poate funcţiona dacă:

există o cerere imbricată în cadrul subcererii vizualizării sau în vreuna dintre vizualizările de bază;

operaţiile de inserare, ştergere şi modificare se fac prin intermediul declanşatorilor INSTEAD OF.

Cuvântul cheie CONSTRAINT permite numirea constrângerii WITH CHECK OPTION. În absenţa acestei clauze, constrângerea va avea un nume implicit de forma SYS_Cn, unde n este un număr întreg unic.

Exemplu:

Să se creeze o vizualizare ce conţine artiştii de naţionalitate română, care

au opere expuse în muzeu. Definiţia vizualizării nu va permite modificarea

naţionalităţii unui artist sau inserarea unui artist având altă naţionalitate decât

cea română.

CREATE VIEW artist_roman

AS SELECT * FROM artist

WHERE nationalitate = 'romana'

WITH CHECK OPTION CONSTRAINT artist_roman_ck;

UPDATE artist_roman

SET nationalitate = 'engleza'

WHERE cod_artist = 25;

Încercarea de actualizare a unei linii prin instrucţiunea anterioară va genera eroarea „ORA-01402: view WITH CHECK OPTION where-clause violation“.

Exemplu: Să se creeze o vizualizare asupra tabelului galerie care să nu permită

efectuarea nici unei operaţii LMD.

CREATE VIEW viz_galerie

AS SELECT cod_galerie, nume_galerie

FROM galerie

WITH READ ONLY;

DELETE FROM viz_galerie

WHERE cod_galerie = 10;

Încercarea de ştergere a unei linii din vizualizarea viz_galerie determină

Page 98: Curs Sinteza SQL

apariţia erorii „ORA-01752: cannot delete from view without exactly one key-

preserved table“. Dacă se încearcă modificarea sau inserarea unei linii prin

intermediul unei vizualizări asupra căreia a fost definită o constrângere WITH

READ ONLY, server-ul Oracle generează eroarea „ORA-01733: virtual column

not allowed here“.

Exemplu:

Să se creeze o vizualizare care conţine codul şi titlul operelor de artă,

codul şi numele artiştilor care le-au creat, precum şi codul galeriilor unde sunt

expuse. Să se afle dacă este posibilă adăugarea unei noi înregistrări prin

intermediul acestei vizualizări.

CREATE VIEW opera_artist

AS SELECT o.cod_opera, o.titlu, o.cod_galerie,

a.cod_artist, a.nume

FROM opera o, artist a

WHERE o.cod_artist = a.cod_artist;

Instrucţiunea următoare afişează numele coloanelor şi valorile YES/NO,

după cum aceste coloane sunt, sau nu, modificabile.

SELECT COLUMN_NAME, UPDATABLE

FROM USER_UPDATABLE_COLUMNS

WHERE TABLE_NAME = 'OPERA_ARTIST';

Se va obţine că doar primele trei coloane ale vizualizării sunt

modificabile.

Indexul primar al coloanei cod_artist din tabelul artist nu este unic în

vizualizarea opera_artist. Prin urmare, tabelul artist nu este key-preserved, iar

coloanele sale nu sunt modificabile.

Instrucţiunea următoare va genera eroarea „ORA-01776: cannot modify more

than one base table through a join view―.

INSERT INTO opera_artist

VALUES (200, 'Poeme de l''ame', 20, 147, 'Janmot');

În schimb, instrucţiunea următoare va fi executată cu succes, întrucât adaugă o înregistrare în tabelul de bază opera, ale cărui coloane sunt modificabile.

INSERT INTO opera_artist (cod_opera, titlu,

cod_galerie)

VALUES (200, 'Poeme de l''ame', 20);

Constrângeri asupra vizualizărilor

Începând cu versiunea Oracle9i pot fi specificate constrângeri pentru

vizualizări. Se pot defini constrângeri la nivel de vizualizare, respectiv la nivel de coloană sau atribut. Constrângerile asupra vizualizărilor constituie o submulţime a constrângerilor specifice tabelelor.

Pot fi specificate explicit numai constrângerile UNIQUE, PRIMARY KEY

şi FOREIGN KEY. Constrângerea de tip CHECK poate fi realizată prin precizarea clauzei WITH CHECK OPTION în comanda care defineşte vizualizarea.

Constrângerile asupra vizualizărilor pot fi definite numai în modul

DISABLE NOVALIDATE. Aceste cuvinte cheie trebuie specificate la declararea constrângerii, nefiind permisă precizarea altor stări.

Page 99: Curs Sinteza SQL

Exemplu: Să se creeze o vizualizare care conţine codurile, numele şi adresele

galeriilor. Se va impune unicitatea valorilor coloanei adresa şi constrângerea de cheie primară pentru coloana corespunzătoare codului galeriei.

CREATE VIEW viz_galerie(

cod_gal, nume, adresa UNIQUE DISABLE NOVALIDATE,

CONSTRAINT cp_viz PRIMARY KEY (cod_gal) DISABLE

NOVALIDATE)

AS SELECT cod_galerie, nume_galerie, adresa

FROM galerie;

Definirea vizualizărilor materializate

O vizualizare materializată, cunoscută în versiunile anterioare sub numele de clişeu (snapshot), este un obiect al schemei ce stochează rezultatele unei cereri şi care este folosit pentru a rezuma, calcula, replica şi distribui date.

Clauza FROM a cererii poate referi tabele, vizualizări sau alte vizualizări materializate. Luate în ansamblu, aceste obiecte sunt referite prin tabele master (în temeni de replicare) sau prin tabele detaliu (în termeni de data warehouse).

Optimizorul pe bază de costuri poate utiliza vizualizările materializate pentru a îmbunătăţi execuţia cererilor. Acesta recunoaşte automat situaţiile în care o astfel de vizualizare poate şi trebuie să fie utilizată pentru rezolvarea unei cereri. În urma unui asemenea demers, optimizorul rescrie cererea utilizând vizualizarea materializată.

În data warehouse, vizualizările materializate sunt utile pentru a calcula şi stoca date agregat, precum totaluri sau medii aritmetice. De asemenea, acest tip de vizualizare este utilizat pentru a efectua cereri în care intervin operaţii de compunere şi în care pot apărea agregări.

În mediile distribuite, vizualizările materializate sunt utilizate pentru replicarea datelor la site-uri distribuite şi sincronizarea modificărilor efectuate pe diferite site-uri. Astfel, vizualizările materializate permit accesul local la date care, altfel, ar fi trebuit să fie accesate de la locaţii distante.

Din anumite puncte de vedere, vizualizările materializate sunt similare indecşilor:

consumă spaţiu de stocare;

trebuie reactualizate dacă datele din tabelele de bază sunt modificate;

îmbunătăţesc performanţa execuţiei instrucţiunilor SQL dacă sunt folosite pentru rescrierea cererilor;

sunt transparente aplicaţiilor SQL şi utilizatorilor.

Spre deosebire de indecşi, vizualizările materializate pot fi accesate utilizând instrucţiuni SELECT şi pot fi actualizate prin instrucţiunile INSERT, UPDATE, DELETE.

Asupra unei vizualizări materializate se pot defini unul sau mai mulţi indecşi. O vizualizare materializată poate fi partiţionată. De asemenea, se pot defini vizualizări materializate asupra unui tabel partiţionat.

Similar vizualizărilor obişnuite, asupra celor materializate se pot defini constrângerile PRIMARY KEY, UNIQUE şi FOREIGN KEY. Singura stare validă a unei constrângeri este DISABLE NOVALIDATE.

Pentru compatibilitate cu versiunile anterioare, cuvintele cheie SNAPSHOT şi MATERIALIZED VIEW sunt echivalente.

Page 100: Curs Sinteza SQL

CREATE MATERIALIZED VIEW [schema.]nume_viz_materializată [OF [schema.]tip_obiect] [ (constr_ref_domeniu) ] [ORGANIZATION INDEX clauza_tabel_org_index] [ {proprietăţi_vm | ON PREBUILT TABLE

[{WITH | WITHOUT} REDUCED PRECISION] } ]

[ {USING INDEX

[ {clauza_atribute_fizice | TABLESPACE nume_sp_tabel}

[ {clauza_atribute_fizice | TABLESPACE nume_sp_tabel} ] …] | USING NO INDEX} ] [refresh_vm] [FOR UPDATE] [ {DISABLE | ENABLE} QUERY REWRITE] AS subcerere;

Clauza OF permite crearea unei vizualizări materializate obiect.

Sintaxa clauzei constr_ref_domeniu este următoarea:

SCOPE FOR ( {ref_coloana | ref_atribut} )

IS [schema.]nume_tabel_scope

[, SCOPE FOR ( {ref_coloana | ref_atribut} )

IS [schema.]nume_tabel_scope] …

Clauza poate fi utilizată pentru restricţionarea domeniului referinţelor la

tabelul nume_tabel_scope. Valorile dintr-o coloană de tip REF vor adresa obiecte din

tabelul identificat prin nume_tabel_scope. În acest tabel sunt stocate instanţe de

obiecte care au acelaşi tip ca şi coloana REF.

Opţiunea ON PREBUILT TABLE permite considerarea unui tabel existent ca

fiind o vizualizare materializată predefinită. Tabelul trebuie să aibă acelaşi nume şi să

se afle în aceeaşi schemă ca vizualizarea materializată rezultată. La ştergerea acestei

vizualizări, tabelul revine la statutul său iniţial. Pentru o vizualizare materializată de

acest tip, alias-urile de coloană din clauza subcerere trebuie să corespundă, ca număr

şi tip de date, coloanelor din tabel.

Clauza WITH REDUCED PRECISION permite ca precizia coloanelor

tabelului sau vizualizării materializate să nu coincidă cu precizia coloanelor returnate

de subcerere. Pentru a impune respectarea întocmai a preciziei, sintaxa dispune de

opţiunea WITHOUT REDUCED PRECISION, care este implicită.

Atributele fizice au o semantică asemănătoare celei descrise de

clauza_proprietăţi_fizice din cadrul comenzii CREATE TABLE. Spre deosebire de

tabele, pentru o vizualizare materializată nu poate fi specificată opţiunea

ORGANIZATION EXTERNAL.

Clauza TABLESPACE specifică spaţiul tabel în care urmează să fie creată

vizualizarea materializată. În absenţa acesteia, vizualizarea va fi creată în spaţiul tabel

implicit al schemei care o conţine.

Clauza USING INDEX permite stabilirea de valori ale parametrilor INITRANS,

MAXTRANS şi STORAGE ai indexului implicit care este utilizat de sistemul Oracle

pentru a întreţine datele vizualizării materializate. Dacă este omisă clauza, sistemul va

utiliza indexul implicit pentru ameliorarea vitezei de reactualizare incrementală a

vizualizării materializate.

Clauza proprietăţi_vm este utilă pentru descrierea vizualizărilor materializate

care nu se bazează pe un tabel existent (nu sunt construite cu opţiunea ON PREBUILT

TABLE).

Page 101: Curs Sinteza SQL

Dintre proprietăţile care pot fi specificate în această clauză, se menţionează:

clauza_partiţionare_tabel, CACHE sau NOCACHE, clauza_paralelism. Pe lângă

acestea, poate fi menţionată opţiunea BUILD IMMEDIATE | DEFERRED care

determină introducerea de linii în vizualizarea materializată imediat, respectiv la

prima operaţie de reactualizare (refresh). În acest ultim caz, până la prima operaţie de

reactualizare, vizualizarea nu va putea fi utilizată în rescrierea cererilor. Opţiunea

IMMEDIATE este implicită.

Prin refresh_vm se specifică metodele, modurile şi momentele la care sistemul

va reactualiza vizualizarea materializată.

{REFRESH

[ {FAST | COMPLETE | FORCE} ] [ON {DEMAND | COMMIT} ]

[START WITH data] [NEXT data]

[ WITH {PRIMARY KEY | ROWID} ]

| USING

{DEFAULT [ {MASTER | LOCAL} ] ROLLBACK SEGMENT

| [ {MASTER | LOCAL} ] ROLLBACK SEGMENT nume_segm_anulare } [ {DEFAULT [ {MASTER | LOCAL} ] ROLLBACK SEGMENT

| [ {MASTER | LOCAL} ] ROLLBACK SEGMENT nume_segm_anulare}…] }

| NEVER REFRESH}

Opţiunea FAST indică metoda de reactualizare incrementală, care se efectuează corespunzător modificărilor survenite în tabelele master. Modificările sunt stocate într-un fişier log asociat tabelului master. Clauza COMPLETE implică reactualizarea completă, care se realizează prin reexecutarea completă a cererii din definiţia vizualizării materializate. Clauza FORCE este implicită şi presupune reactualizarea de tip FAST, dacă este posibil. În caz contrar, reactualizarea va fi de tip COMPLETE.

Clauza ON COMMIT indică declanşarea unei operaţii de reactualizare de tip

FAST ori de câte ori sistemul permanentizează o tranzacţie care operează asupra unui

tabel master al vizualizării materializate. Clauza nu este permisă pentru vizualizările

materializate ce conţin tipuri obiect.

Clauza ON DEMAND este implicită şi indică efectuarea reactualizării

vizualizării materializate la cererea utilizatorului, prin intermediul procedurilor

specifice din pachetul DBMS_MVIEW (REFRESH, REFRESH_ALL_MVIEWS,

REFRESH_DEPENDENT).

Opţiunile START WITH şi NEXT nu pot fi specificate dacă s-au precizat

clauzele ON COMMIT sau ON DEMAND. Expresiile de tip dată calendaristică

indicate în cadrul acestor opţiuni specifică momentul primei reactualizări automate şi

determină intervalul dintre două reactualizări automate consecutive.

Clauza WITH PRIMARY KEY este implicită şi permite ca tabelele master să fie

reorganizate fără a afecta eligibilitatea vizualizării materializate pentru reactualizarea

de tip FAST. Tabelul master trebuie să conţină o constrângere PRIMARY KEY.

Opţiunea nu poate fi specificată pentru vizualizări materializate obiect. Opţiunea

WITH ROWID asigură compatibilitatea cu tabelele master din versiunile precedente

lui Oracle8.

Clauza USING ROLLBACK SEGMENT specifică segmentul de anulare distant

Page 102: Curs Sinteza SQL

care urmează să fie utilizat pentru reactualizarea vizualizării materializate. Cuvântul

cheie DEFAULT determină ca sistemul să aleagă acest segment în mod automat.

Opţiunile MASTER şi LOCAL specifică segmentul de anulare distant care urmează să

fie utilizat pe site-ul distant pentru vizualizarea materializată individuală, respectiv

pentru grupul local de reactualizare care conţine vizualizarea materializată. Opţiunea

LOCAL este implicită.

Clauza NEVER REFRESH previne reactualizarea vizualizării materializate

prin mecanisme Oracle sau prin proceduri. Pentru a permite reactualizarea, trebuie

efectuată o operaţie ALTER MATERIALIZED VIEW…REFRESH.

Clauza FOR UPDATE permite actualizarea unei vizualizări materializate.

QUERY REWRITE permite specificarea faptului că vizualizarea materializată este

eligibilă pentru operaţia de rescriere a cererilor.

Opţiunea AS specifică cererea care defineşte vizualizarea materializată. Dacă

în clauza FROM a cererii din definiţia vizualizării materializate se face referinţă la o

altă vizualizare materializată, atunci aceasta va trebui reactualizată întotdeauna

înaintea celei create în instrucţiunea curentă.

Exemplu:

a) Să se creeze şi să se completeze cu înregistrări o vizualizare materializată

care va conţine titlul operelor de artă, numele artistului şi suma valorilor poliţelor de

asigurare încheiate.

Reactualizările ulterioare ale acestei vizualizări se vor realiza prin

reexecutarea cererii din definiţie. Vizualizarea creată va putea fi aleasă pentru

rescrierea cererilor.

CREATE MATERIALIZED VIEW opera_artist_polite

BUILD IMMEDIATE

REFRESH COMPLETE

ENABLE QUERY REWRITE

AS SELECT o.titlu, a.nume, SUM(p.valoare)

suma_polite

FROM opera o, artist a, polita_asig p

WHERE o.cod_artist = a.cod_artist

AND o.cod_opera = p.cod_opera

GROUP BY o.cod_opera, o.titlu, a.nume;

b) Să se creeze tabelul opera_artist_polite. Acesta va fi utilizat ca tabel

sumar preexistent în crearea unei vizualizări materializate ce va permite diferenţe de

precizie şi rescrierea cererilor.

CREATE TABLE opera_artist_polite(

titlu VARCHAR2(25),

nume VARCHAR2(15),

suma_polite NUMBER);

CREATE MATERIALIZED VIEW opera_artist_polite

ON PREBUILT TABLE WITH REDUCED PRECISION

ENABLE QUERY REWRITE

AS SELECT o.titlu, a.nume, SUM(p.valoare)

suma_polite

FROM opera o, artist a, polita_asig p

Page 103: Curs Sinteza SQL

WHERE o.cod_artist = a.cod_artist

AND o.cod_opera = p.cod_opera

GROUP BY o.cod_opera, o.titlu, a.nume;

c) Să se creeze o vizualizare materializată care conţine informaţiile din

tabelul artist, permite reorganizarea acestuia şi este reactualizată la momentul creării,

iar apoi la fiecare 5 minute.

CREATE MATERIALIZED VIEW artist_vm

REFRESH FAST START WITH SYSDATE NEXT SYSDATE +

1/288

WITH PRIMARY KEY

AS SELECT * FROM artist;

Pentru reactualizarea de tip FAST, este necesar un fişier log în care să fie

stocate modificările. Instrucţiunea precedentă generează eroarea „ORA-23413: table

―artist‖ does not have a materialized view log―. Pentru remedierea acestei situaţii,

înainte de crearea vizualizării se va lansa următoarea comandă:

CREATE MATERIALIZED VIEW LOG ON artist;

Comanda ALTER MATERIALIZED VIEW permite intervenţia asupra unei

vizualizări materializate, într-unul din următoarele sensuri:

modificarea caracteristicilor de stocare;

modificarea metodei, modului sau timpului de reactualizare (refresh);

modificarea structurii, astfel încât să devină un alt tip de vizualizare

materializată;

activarea sau dezactivarea funcţiei de rescriere a cererilor.

ALTER MATERIALIZED VIEW [ schema.]nume_viz_materializată

[atribute_fizice] [USING INDEX atribute_fizice]

[ {REBUILD | alter_vm_refresh} ]

[ { {ENABLE | DISABLE} QUERY REWRITE

| COMPILE | CONSIDER FRESH} ];

Opţiunea USING INDEX modifică parametrii de stocare asociaţi indexului

folosit de sistem pentru a întreţine datele vizualizării materializate.

Clauza REBUILD permite regenerarea operaţiilor de reactualizare atunci când

se modifică un tip care este referit în vizualizarea materializată. Specificarea acestei

opţiuni interzice utilizarea altor clauze în aceeaşi instrucţiune ALTER

MATERIALIZED VIEW.

Clauza alter_vm_refresh permite modificarea metodelor, modurilor şi timpului

implicit de reactualizare automată. În cazul modificării conţinutului tabelelor master

ale vizualizării materializate, datele din vizualizare trebuie reactualizate astfel încât să

reflecte datele existente.

Clauza QUERY REWRITE, prin opţiunile ENABLE şi DISABLE, determină ca

vizualizarea materializată să fie, sau nu, eligibilă pentru rescrierea cererilor.

Clauza COMPILE permite revalidarea explicită a vizualizării materializate.

Dacă un obiect de care depinde vizualizarea materializată este suprimat sau modificat,

vizualizarea rămâne accesibilă, dar nu este eligibilă pentru rescrierea cererilor. Clauza

este utilă pentru revalidarea explicită a vizualizării materializate, astfel încât aceasta

să devină eligibilă în operaţia de rescriere a cererilor.

Opţiunea CONSIDER FRESH indică sistemului să considere vizualizarea

Page 104: Curs Sinteza SQL

materializată ca fiind reactualizată şi deci eligibilă pentru rescrierea cererilor.

Exemplu:

Să se modifice vizualizarea materializată opera_artist_polite creată anterior,

astfel încât metoda de reactualizare implicită să fie de tip FAST, iar intervalul de timp

la care se realizează reactualizarea să fie de 7 zile. Nu va fi permisă utilizarea acestei

vizualizări pentru rescrierea cererilor.

ALTER MATERIALIZED VIEW opera_artist_polite

REFRESH FAST NEXT SYSDATE + 7 DISABLE QUERY

REWRITE;

Pentru că nu se specifică valoarea corespunzătoare opţiunii START WITH în

clauza REFRESH, următoarea reactualizare va avea loc la momentul stabilit prin

comanda de creare a vizualizării materializate sau prin ultima comandă de modificare

a acesteia. Sistemul va reactualiza vizualizarea evaluând expresia din clauza NEXT,

iar apoi va executa această operaţie o dată pe săptămână.

DROP MATERIALIZED VIEW [schema.]nume_viz_materializată;

Grupări

Cluster-ul este o regrupare fizică a două sau mai multe tabele, relativ la una

sau mai multe coloane, cu scopul măririi performanţelor. Coloanele comune definesc

cheia cluster-ului.

Un cluster este un obiect al bazei care necesită:

un nume unic la nivelul schemei,

specificare a coloanelor care compun cheia cluster-ului,

specificare a spaţiului de stocare (opţional),

un index (relativ la cheia cluster-ului).

Un cluster trebuie să aibă cel puţin un index. Acest index trebuie creat înaintea

oricărei comenzi LMD care va acţiona asupra tabelelor cluster-ului. Un index al

cluster-ului se deosebeşte de un index al tabelului (de exemplu, absenţa indexului

afectează utilizatorul – datele cluster-ului nu sunt accesibile).

Coloanele comune definite pentru cluster, reprezintă cheia cluster-ului şi

criteriul de regrupare.

Liniile diferitelor tabele sunt regrupate în interiorul aceluiaşi bloc

urmărind cheia cluster-ului. Dacă liniile asociate unei aceiaşi valori a cheii

cluster-ului necesită un spaţiu de mai multe blocuri, atunci blocurile sunt

înlănţuite.

Crearea unui cluster presupune:

crearea structurii cluster-ului;

crearea indexului cluster-ului;

crearea tabelelor care vor compune cluster-ul.

Crearea unui cluster se realizeaza prin comanda:

CREATE CLUSTER nume_cluster (nume_coloana tip_data [,nume_coloana tip_data] …) [SIZE n]

Page 105: Curs Sinteza SQL

Există două modalităţi pentru introducerea unui tabel într-un cluster.

O primă variantă presupune că cluster-ul este creat pentru un tabel care deja există. De fapt, nu se poate asocia un cluster unui tabel care există!

A doua variantă presupune că introducerea tabelului în cluster se face în momentul creării structurii tabelului (comanda CREATE TABLE).

Exerciţiu: Să se obţină un cluster referitor la lista cărţilor din fiecare domeniu.

Varianta 1

CREATE CLUSTER cdoml(cdom CHAR(1));

CREATE INDEX indcom ON CLUSTER cdoml; CREATE TABEL domino

CLUSTER cdoml(coded)

AS SELECT * FROM domeniu;

DROP TABEL domeniu;

RENAME domino TO domeniu;

ALTER TABLE carte

MODIFY coded NOT NULL;

CREATE TABEL carticica

CLUSTER cdoml(coded)

AS SELECT * FROM carte;

DROP TABLE carte;

RENAME carticica TO carte;

Varianta 2

CREATE CLUSTER cdoml(cdom CHAR(1));

CREATE INDEX indcom ON CLUSTER cdoml;

-- crearea spatiului

CREATE TABLE domeniu

(coded CHAR(1) NOT NULL, intdom CHAR() ... ) CLUSTER cdoml(coded);

CREATE TABLE carte

(codel CHAR(5) NOT NULL,

coded CHAR(1) NOT NULL)

CLUSTER cdoml(coded);

Pentru a scoate un tabel dintr-un cluster sunt parcurse următoarele etape: se

creează un nou tabel, în afara cluster-ului, prin duplicarea celui vechi; se distruge

tabelul din cluster; se suprimă cluster-ul.

CREATE TABLE alfa

AS SELECT * FROM domeniu;

DROP TABLE domeniu;

RENAME alfa TO domeniu;

CREATE TABLE beta

AS SELECT * FROM carte;

DROP TABLE carte;

RENAME beta TO carte;

DROP CLUSTER cdoml;

Un alt tip de cluster oferit de Oracle este cluster-ul hash. În acest caz, pentru a

accesa o înregistrare, cluster-ul hash nu foloseşte un index, ci o funcţie numerică,

Page 106: Curs Sinteza SQL

numită funcţia hash. Funcţia are ca parametru cheia cluster-ului şi returnează o

anumită valoare (valoare hash). Această valoare corespunde blocului de date din

cluster pe care Oracle îl va citi sau scrie pe baza comenzii executate.

De exemplu, apelurile telefonice efectuate de un client într-o lună vor fi

facturate împreună. Apelurile pot fi depozitate într-un cluster hash a cărui cheie este

formată din coloanele ce conţin numărul telefonului, anul şi luna în care a avut loc

convorbirea.

Suprimarea unui cluster din baza de date se face prin comanda:

DROP CLUSTER nume_cluster

În urma ştergerii unui cluster, tabelele pe care acesta le conţine nu mai sunt

grupate. Secvenţa următoare suprimă: cluster-ul, toate tabelele definite relativ la acest

cluster şi constrângerile lor de integritate.

DROP CLUSTER nume_cluster

INCLUDING TABLES

CASCADE CONSTRAINTS;

Modificarea unui cluster permite redefinirea condiţiilor, modificarea

parametriilor de stocare şi a caracteristicelor de stare (ALTER CLUSTER).

Informaţii despre obiectele bazei de date

Pot fi obţinute consultând DD(Dicț ionarul de Date). Dintre ele se remarcă:

definiţiile tuturor obiectelor din baza de date;

spaţiul alocat şi spaţiul utilizat în prezent de obiectele schemei;

constrângerile de integritate;

numele utilizatorilor bazei;

privilegiile şi rolurile acordate fiecărui rol;

alte informaţii generale despre baza de date.

Tabelul USER_CATALOG conţine informaţii despre tabelele şi vizualizările

definite de un utilizator particular. Acest tabel poate fi referit şi prin sinonimul său

public CAT.

Tabelul USER_OBJECTS conţine informaţii despre toate obiectele definite de

utilizatorul curent. Tabelul are următoarea schemă relaţională:

USER_OBJECTS (object_name, object_id, object_type, created, last_ddl_time,

timestamp, status)

Vizualizările cele mai importante ale dicţionarului datelor conţin:

descrierea tabelelor definite de utilizatori (USER_ALL_TABLES),

informaţii despre constrângerile definite de utilizator(USER_CONSTRAINTS),

informaţii despre legăturile bazei de date (USER_DB_LINKS),

erorile curente ale obiectelor depozitate (USER_ERRORS),

Page 107: Curs Sinteza SQL

informaţii despre indecşii creaţi de utilizator (USER_INDEXES),

informaţii despre tabelele utilizatorului (USER_TABLES) etc.

Vizualizările din dicţionarul datelor referitoare la tabele conţin:

USER_TAB_COLUMNS|COLS – informaţii despre coloanele tabelelor,

USER_CONS_COLUMNS – informaţii despre constrângeri la nivel coloană,

USER_TAB_COMMENTS – informaţii despre comentarii la nivel tabel,

USER_COL_COMMENTS – informaţii despre comentarii la nivel coloană,

USER_TAB_PARTITIONS – informaţii despre partiţiile tabelelor.

Întrebări

Alegeţi răspunsurile corecte pentru fiecare din următoarele întrebări cu

răspunsuri multiple. Reţineţi că întrebările pot avea mai multe răspunsuri corecte.

1. Tipurile de date oferă următoarele avantaje

a. Respectă standardele publicate

b. Oferă un set de comportamente utile pentru utilizatorii bazei

c. Asigură independenţa faţă de date

d. Restricţionează datele din coloane la caractere care au sens în context

e. Ajută sistemul DBMS să stocheze mai eficient datele din coloane

2. Tipurile de date pentru caractere

a. Sunt mai flexibile decât tipurile de date numerice

b. Acceptă atât date cu lungime fixă, cât şi date cu lungime variabilă.

c. Necesită întotdeauna specificarea preciziei şi a scalei

d. Determină completarea coloanelor până la lungimea maximă maximă

e. Pot stoca şiruri de caractere în format specific unei limbi naţionale

3. Tipurile de date numerice

a. Sunt mai flexibile decât tipurile de date pentru caractere

b. Restricţionează valorile din coloane la numere şi simboluri înrudite, cum

ar fi virgulele şi simbolul dolar

c. Necesită întotdeauna specificarea preciziei şi a scalei

d. Stochează valori exacte sau aproximative

e. Sunt potrivite pentru a fi folosite în calcule

4. Tipurile numerice standard includ

a. INTEGER

b. NUMBER

c. FLOAT

d. BOOLEAN

e. INTERVAL

5. Tipurile de date temporale standard includ

a. DATETIME

b. DATE

c. TIMESTAMP

Page 108: Curs Sinteza SQL

d. TIMEZONE

e. TIME

6. Valorile NULL

a. Pot fi folosite pentru reprezentarea datelor care lipsesc sau nu sunt

cunoscute

b. Înseamă acelaşi lucru ca şi spaţiile libere

c. Sunt egale cu alte valori NULL

d. Nu sunt egale cu alte valori NULL

e. Sunt întotdeauna permise în mod prestabilit

7. Instrucţiunile DDL includ

a. CREATE

b. ALTER

c. DELETE

d. INSERT

e. UPDATE

8. Instrucţiunea CREATE DATABASE

a. Funcţionează exact la fel în toate sistemele DBMS relaţionale

b. Specifieă întotdeauna numele bazei de date

c. Specifieă întotdeauna numele proprietarului bazei de date

d. Poate include parametri specifici producătorului

e. Funcţionează la fel cu instrucţiunea CREATE SCHEMA

9. Definiţia unei coloane din instrucţiunea CREATE TABLE poate include

a. Numele tabelului

b. Numele coloanei

c. restricţie la nivel de tabel

d. clauză DEFAULT

e. O clauză NULL sau NOT NULL

10. Numele unei coloane dintr-un tabel

a. Trebuie să fie specificat în instrucţiunea CREATE TABLE

b. Trebuie să fie unic în cadrul bazei de date

c. Trebuie să fie unic în cadrul tabelului

d. Poate fi folosit într-un singur index

e. Trebuie să fie specificat în instrucţiunea ALTER TABLE

11. O restricţie la nivel de coloană

a. Poate referi una sau mai multe coloane

b. Poate fi inclusă într-o instrucţiune CREATE TABLE sau ALTER TABLE

c. Foloseşte o sintaxă identică sau aproape identică cu cea a unei restricţii de

acelaşi tip la nivel de tabel

d. Poate fi folosită oriunde ar putea fi folosită o restricţie la nivel de tabel

e. Are o sintaxă care diferă de la un tip de restricţie la altul

12. Sintaxa corectă pentru clauza DEFAULT este

a. DEFAULT (precizie, scală)

b. DEFAULT [NULL | NOT NULL]

c. DEFAULT (expresie)

d. DEFAULT (nume–coloană) REFERENCES name–tabel (nume_coloană.)

e. DEFAULT [UNIQUE | PRIMARY KEY]

13. Sintaxa corectă pentru o restricţie NOT NULL este

a. nume_coloană tip--de–date IS NOT NULL

b. nume_coloană tip–de–date NOT NULL

Page 109: Curs Sinteza SQL

c. DEFAULT [NULL | NOT NULL]

d. CREATE NOT NULL INDEX ON nume_coloană

e. nume–coloană REFERENCES NOT NULL

14. Sintaxa corectă pentru o restricţie UNIQUE este

a. [CONSTRAINT nume—restricţie] UNIQUE (nume_coloană)

b. [CONSTRAINT nume—restricţie] UNIQUE (nume_tabel)

c. DEFAULT UNIQUE (nume_coloană)

d. nume_coloană REFERENCES UNIQUE nume_tabel

e. DEFAULT [UNIQUE | PRIMARY KEY]

15. Sintaxa corectă pentru o restricţie referenţială este

a. [CONSTRAINT nume—restricţie] REFERENCES nume_index

b. [CONSTRAINT nume—restricţie] REFERENCES nume_tabel

c. FOREIGN KEY nume_coloană REFERENCES nume_tabel

(nume_coloană)

d. REFERENCES nume—tabel (nume_coloană)

e. nume_coloană REFERENCES UNIQUE nume_tabel

16. Instrucţiunea CREATE INDEX

a. Poate fi folosită pentru crearea restricţiilor de unicitate şi cheie primară

b. Poate include cuvântul cheie UNIQUE

c. Trebuie să refere două sau mai multe nume de coloane

d. Poate include cuvintele cheie ASC sau DESC pentru orice coloană

e. Poate specifica ordinea ascendentă sau descendentă pentru una sau mai

multe coloane

17. Instructiunea CREATE VIEW

a. Stochează o interogare în baza de date

b. Poate include cuvântul cheie opţional CASCADE

c. Poate include cuvântul cheie opţional OR REPLACE

d. Trebuie să conţină o comandă DMI, validă

e. Trebuie să conţină o instrucţiune SELECT validă

18. Utilizările valide ale instrucţiunii ALTER TABLE includ

a. Adăugarea coloanelor

b. Modificarea lungimii sau a preciziei coloanelor

c. Redenumirea unui tabel

d. Eliminarea unei chei primare

e. Adăugarea unei chei primare

19. O instrucţiune ALTER TABLE nu poate fi folosită pentru

a. Schimbarea tipului de date al unei coloane la un tip numeric dacă în

coloana respectivă există date de alt tip

b. Redenumirea unei coloane

c. Schimbarea unei restricţii din NULL în NOT NULL pentru o coloană care

conţine valori nule

d. Eliminarea unei chei exteme care referă o cheie primară

e. Eliminarea unei chei primare dacă există chei exteme care referă cheia

primară

20. Instrucţiunea DROP poate fi folosită pentru a şterge

a. restricţie referenţială

b. Un index

c. Un tabel

d. coloană dintr-un tabel

e. vizualizare

Page 110: Curs Sinteza SQL

Lecţia 3. Limbajul de interogare a datelor(DQL)

Limbajul SQL de interogare a datelor (DQL – Data Query Language)

include o singură comandă SELECT, care este cea mai folosită pentru a obţine date

din baza de date, astfel încât acestea să fie prelucrate de o anumită aplicaţie sau să fie

afişate. Rezultatul unei instrucţiuni SELECT, numit şi set de rezultate, este

returnat sub forma unui tabel. Deoarece SQL este un limbaj neprocedural, se specifică

rezultatele pe care le doriţi să le obţineţi, nu şi modul lor de obţinere.

Instrucţiunea SELECT de bază

Forma elementară a instrucţiunii SELECT conţine două clauze:

SELECT [DISTINCT] - Specifică lista de coloane care urmează să

fie returnate în setul de rezultate, separate prin virgule. Se poate folosi simbolul

asterisc (*) în locul listei de coloane pentru a selecta toate coloanele dintr-un tabel sau

dintr-o vizualizare. Cuvântul cheie DISTINCT poate fi adăugat după cuvântul cheie

SELECT pentru a elimina rândurile duplicate din rezultatele interogării.

FROM - Specifică lista tabelelor sau vizualizărilor din care urmează să fie

selectate datele. În locul numelor reale ale tabelelor sau vizualizărilor se poate folosi

sinonime, adică pseudonime pentru tabele sau vizualizări definite în baza de date.

În exemplul următor se selectează coloanele: COD_GEN_FI LM,

MPAA_ RATING_COD şi TITLU_FILM din tabelul FILM.

SELECT COD_GEN_FILM, COD_ RATING, TITLU_FILM

FROM FILM;

Pseudonime pentru numele coloanelor

In setul de rezultate din interogări numele coloanelor din tabel apare

automat ca titlu de coloane în interogare. Dacă se doreşte un alt nume pentru

coloanele unei interogări se folosesc pseudonime.

Pseudonimele (aliases) specificate devin numele coloanelor din setul de

rezultate. Pseudonimele nu există decât după rularea instrucţiunii SQL, aşa că nu pot fi

folosite în alte părţi ale instrucţiunii SQL. Pseudonimul unei coloane este specificat prin

plasarea cuvântului cheie ”AS" după numele coloanei în lista SELECT (cu cel puţin un

spaţiu înainte şi după), urmat de numele dorit pentru a fi atribuit coloanei în setul de

rezultate.

SELECT COD_GEN_FILM AS GEN,

MPAA_ RATING_COD AS RATING, TITLU_FILM

FROM FILM;

Sortarea rezultatelor

Rezultatele interogărilor sunt deseori mult mai utile dacă se specifică pentru

rândurile returnate o ordine care să aibă o semnificaţie pentru persoana sau aplicaţia

care foloseşte informaţiile. În SQL, acest lucru este făcut prin adăugarea în instrucţiunea

SELECT a clauzei ORDER BY, cu o listă de una sau mai multe coloane care vor fi

folosite pentru sortarea rândurilor în ordine ascendentă sau descendentă, în conformitate

cu valorile datelor din coloane. De asemenea, se ţine seama de următoarele aspecte:

Page 111: Curs Sinteza SQL

Ordinea prestabilită pentru fiecare coloană este ascendentă, dar se poate

adăuga cuvântul cheie ASC după numele coloanei pentru obţinerea unei ordonări

ascendente sau cuvântul cheie DESC pentru obţinerea unei ordonări descendente.

Nu este obligatoriu ca numele coloanelor din lista ORDER BY să fie incluse şi

în lista de rezultate (adică în lista SELECT).

Motorul SQL din SGBD va găsi cea mai bună cale de ordonare a coloanelor.

În general, sortarea datelor este un proces costisitor din punct de vedere al resurselor

de calcul, aşa că majoritatea sistemelor SGBD folosesc un index pentru accesul la

rânduri în ordinea dorită, presupunând că există, şi fac o sortare propriu-zisă numai ca

ultimă soluţie.

Se poate folosi pseudonimele coloanelor în clauza ORDER BY, dar dacă se

face acest lucru se forţează motorul SQL să sorteze rezultatele abia după rularea

interogării.

În locul coloanelor, se poate specifica în lista de ordonare poziţia relativă a

coloanelor. De exemplu, clauza ORDER BY 1,2 va sorta rezultatele în ordine

ascendentă după primele două coloane din setul de rezultate. Numărul specificat nu

are nici o legătură cu poziţia coloanei în tabelul sau vizualizarea sursă. Această

opţiune nu este agreată în programarea SQL formală, deoarece dacă ulterior cineva

modifică interogarea, este posibil să amestece coloanele din lista SELECT, fără să-şi

dea seama că astfel schimbă şi coloanele folosite pentru sortarea rezultatelor.

SELECT MPAA_RATING_COD AS RATING,

COD_GEN_FILM AS GEN, TITLU_FILM

FROM FILM

ORDERBY MPAA_RATING_COD, COD_GEN_FILM

Dacă dorim să ordonăm acum crescător după rating şi descrescător după gen,

atunci instrucţiunea de mai sus odificată va fi

SELECT MPAA_ RATING_COD AS RATING,

COD_GEN_FILM AS GEN, TITLU_FILM

FROM FILM

ORDERBY MPAA_RATING_COD ASC, COD_GEN_FILM DESC;

Observaţie:

Oracle va afişa titlu de coloana la dimensiunea maximă a valorilor din

coloana(de ex. dacă în coloana RATING val cea mai mare este de 5 caractere,

interogarea va afişa RATIN). În noua versiune de SQL produs de Oracle, iSQL*Plus,

nu mai prescurtează.

Utilizarea clauzei WHERE pentru filtrarea rezultatelor

SQL foloseşte clauza WHERE pentru a filtra rândurile ce urmează să fie

afişate. O interogare fără o clauză WHERE returnează un set de rezultate care conţine

toate rândurile din tabelele sau vizualizările referite în clauza FROM. Dacă este

inclusă o clauză WHERE, sunt folosite regulile algebrei booleene, evaluând clauza

WHERE pentru fiecare rând de date. În rezultatele interogării sunt afişate numai

rândurile pentru care clauza WHERE este evaluată la valoarea logică „adevărat".

Operatori de comparare Operatorii de comparare sunt folosiţi în clauza WHERE pentru

compararea a două valori, având ca rezultat o valoare logică de „adevărat" sau „fals".

Page 112: Curs Sinteza SQL

Cele două valori comparare pot fi constante furnizate în clauza WHERE, valori ale

unor coloane din baza de date sau combinaţii ale celor două. Operatorii de comparare

care pot fi folosiţi în clauza WHERE sunt prezentaţi în tabelul următor:

Operator Descriere

= Egal cu

< Mai mic decât

<= Mai mic sau egal

> Mai mare decât

>= Mai mare sau egal

!= Diferit de

<> Diferit de (standard ANSI)

Exemple:

Să se afişeze toate filmele pentru care RATING are valoarea PG-13.

SELECT MPAA_RATING_COD AS RATING, TITLU_FILM

FROM FILM

WHERE MPAA_ RATING_COD = 'PG-13'

ORDER BY TITLU_FILM;

Să se afişeze pentru care RATING are altă valoare decât PG-13.

SELECT COD_RATING AS RATING, FILM

FROM FILM

WHERE COD_RATING <> 'PG-13'

ORDER BY TITLU_FILM;

Să se afişeze toate filmele cu preţul de vânzare cu amănuntul pentru

formatul DVD (DVD Retail Price) mai mic de 19.99, în ordinea

descrescătoare a preţurilor.

SELECT PRET_VANZARE_DVD, TITLU_FILM

FROM FILM

WHERE PRET_VANZARE_DVD < 19.99

ORDER BY PRET_VANZARE_DVD DESC;

Să se afişeze filmele cu preţul de vânzare cu amănuntul pentru formatul

DVD (DVD Retail Price) de 19.99 sau mai mic.

SELECT PRET_VANZARE_DVD, TITLU_FILM

FROM FILM

WHERE PRET_VANZARE_DVD <= 19.99

ORDER BY PRET_VANZARE_DVD DESC;

Să se afişeze toate filmele cu preţul de vânzare cu amănuntul pentru

formatul DVD (DVD Retail Price) mai mare de 25.00, în ordinea

crescătoare a preţurilor.

SELECT PRET_VANZARE_DVD, TITLU_FILM

FROM FILM

WHERE PRET_VANZARE_DVD >= 25.00

ORDER BY PRET_VANZARE_DVD DESC;

Page 113: Curs Sinteza SQL

Operatori conjunctivi

Uneori sunt necesare condiţii multiple pentru a îngusta setul de

rezultate al unei interogări. Atunci când sunt folosite mai multe condiţii, ele trebuie să

fie combinate din punct de vedere logic în clauza WHERE, iar aceasta este sarcina

operatorilor conjunctivi. Aceşti operatori sunt:

AND (ŞI) - Clauza WHERE este evaluată ca „adevărată" dacă toate condiţiile

conectate cu operatorul AND sunt adevărate.

OR (SAU) - Clauza WHERE este evaluată ca „adevărată" dacă oricare din

condiţiile conectate cu operatorul OR este adevărată.

Lucrurile devin complicate dacă operatorii AND şi OR sunt combinaţi în aceeaşi

clauză WHERE. Operatorul AND are prioritate mai mare şi, ca urmare, este evaluat

înaintea operatorilor OR.

Exemple de folosire a operatorilor conjunctivi:

Să se afişeze toate filmele pentru care categoria RATING este PG-13 şi

preţul de vânzare cu amănuntul pentru formatul DVD este 19.99 sau mai

mic, în ordinea crescătoare a preţurilor.

SELECT COD_RATING AS RATING,

PRET_VANZARE_DVD AS PRET, TITLU_FILM

FROM FILM

WHERE COD_RATING = 'PG-13'

AND PRET_VANZARE_DVD <= 19.99

ORDER BY PRET_VANZARE_DVD;

Să se afişeze toate filmele pentru care categoria RATING este PG-13 sau

preţul de vânzare cu amănuntul pentru formatul DVD este 19.99 sau mai

mic, în ordinea crescătoare a preţurilor.

SELECT COD_RATING AS RATING,

PRET_VANZARE_DVD AS PRET, TITLU_FILM

FROM FILM

WHERE COD_RATING = 'PG-13'

OR PRET_VANZARE_DVD <= 19.99

ORDER BY PRET_VANZARE_DVD;

Să se afişeze toate filmele pentru care categoria RATING este PG-13 şi

sunt din genul dramă sau acţiune/aventură.

SELECT COD_RATING AS RATING,

PRET_VANZARE_DVD AS PRET,

TITLU_FILM

FROM FILM

WHERE COD_GEN_FILM= 'ActAd'

OR COD_GEN_FILM = 'Drama'

AND COD_RATING = 'PG-13'

ORDER BY COD_GEN_FILM, COD_RATING;

Să se adauge parantezele necesare, astfel încât să obţinem filmele cu

categoria PG-13 şi genul acţiune/aventură sau dramă.

SELECT COD_GEN_FILM AS GEN,

Page 114: Curs Sinteza SQL

COD_RATING AS RATING, TITLU_FILM

FROM FILM

WHERE (COD_GEN_FILM = 'ActAd'

OR COD_GEM_FILM = 'Drama')

AND COD_RATING='PG-13'

ORDER BY COND_GEN_FILM, COD_RATING;

Operatori logici

Operatorii logici folosesc cuvinte cheie în locul simbolurilor la

formarea expresiilor de comparare. La oricare dintre aceşti operatori poate fi adăugat

cuvântul cheie NOT, pentru a inversa valoarea logică a comparaţiei.

IS NULL

Operatorul IS NULL este folosit pentru a determina dacă o valoare este nulă.

Exemple:

Să se găsească toate conturile de clienţi active, adică toate conturile pentru

care coloana DATA–TERMINATA conţine o valoare nulă:

SELECT ID_CONT_CLIENT

FROM CONT_CLIENT

WHERE DATA_INCHEIERE IS NULL;

Să se găsească toate conturile inactive, adică toate conturile pentru care

coloana DATA–TERMINATA conţine o altă valoare decât NULL:

SELECT ID_CONT_CLIENT

FROM CONT_CLIENT

WHERE DATA_INCHEIERE IS NOT NULL;

BETWEEN

Operatorul BETWEEN este folosit pentru a determina dacă o valoare

se încadrează într-un interval special. Intervalul este specificat folosind o valoare

minimă şi o valoare maximă, fiind un interval inclusiv, ceea ce înseamnă că include şi

valori specificate.

Exemple:

Să se afişeze toate filmele cu preţul de vânzare cu amănuntul pentru

formatul DVD între 14.99 şi 19.99, ordonate crescător după preţ.

SELECT TITLU_FILM, PRET_VANZARE_DVD

FORM FILM

WHERE PRER_VANZARE_DVD BETWEEN 14.99 AND 19.99

ORDER BY PRER_VANZARE_DVD;

Să se afişeze toate filmele pentru care preţul de vânzare cu amănuntul

pentru formatul DVD nu este în intervalul 14.99-19.99, ordonate crescător

după preţ.

SELECT TITLU_FILM, PRET_VANZARE_DVD

FROM FILM

WHERE PRET_VANZARE_DVD NOT BETWEEN 14.99 AND 19.99

ORDER BY PRET_VANZARE_DVD;

Să se afişeze toate conturile de clienţi în luna ianuarie 2005.

Page 115: Curs Sinteza SQL

SELECT ID_CONT_CLIENT, DATA_INSCRIERE

CONT_CLIENT

WHERE DATA_INSCRIERE BETWEEN ‖2005/01/01‖ AND „2005/01/31‖;

LIKE Operatorul LIKE este folosit pentru a compara o valoare de tip caracter cu un

tipar*, returnând valoarea logică ―adevărat‖ dacă valoarea de tip caracter se

încadrează în tipar şi ―fals" în caz contrar. Pentru definirea tiparului pot fi folosite

două caractere de înlocuire:

Liniuţa de subliniere (_) - Caracterul liniuţă de subliniere poate fi folosit

drept caracter de înlocuire poziţional, ceea ce înseamnă că se potriveşte cu orice

caracter aflat pe poziţia respectivă în şirul de caractere evaluat.

Procent (%) - Simbolul procent (%) poate fi folosit drept caracter de înlocuire

nepoziţional, ceea ce înseamnă că se potriveşte cu orice număr de caractere, indiferent

de lungime.

Microsoft Access oferă o caracteristică similară, dar pentru caracterul de

înlocuire poziţional este folosit semnul de întrebare (?), iar pentru caracterul de

înlocuire nepoziţional este folosit asteriscul (*) — aceste caractere corespund convenţiilor

folosite în DOS si Visual Basic.

Exemple de tipare:

Tipar Interpretare

%Now Se potriveşte cu orice şir de caractere care se termină

cu „Now".

Now% Se potriveşte cu orice şir de caractere care incepe cu

„Now".

%Now

%

Se potriveşte cu orice şir de caractere care confine

„Now" (1a inceput, la sfârşit sau în mijloc).

N_w Se potriveşte cu orice şir de caractere format din exact

trei caractere, care începe cu „N" şi se termină cu „w".

%N-w% Se potriveşte cu orice şir de caractere care conţine

litera „N", urmată de orice alt caracter, urmat de litera „w" (1a

începutul, la sfârşitul sau undeva în mijlocul şirului de

caractere)

Datele din bazele de date relaţionale fac întotdeauna diferenţierea literelor

mari de cele mici. O literă mica din date nit se potriveşte cu o literă mare din tiparul

unei clauze LIKE, şi invers.

Exemplu de utilizare a operatorului LIKE:

Să se afişeze toate titlurile de filme care conţin şirul de caractere „on":

SELECT TITLU_FILM

FROM FILM

WHERE TITLU_FILM LIKE '%on%';

Dacă se intenţionează să se găsească titlurile care conţin cuvântul „on", nu

literele „on" din alte cuvinte, ar fi trebuit să includă în tipar şi spatiile necesare, ca în

exemplul următor:

Page 116: Curs Sinteza SQL

IN

Operatorul IN este folosit pentru a determine dacă o valoare face parte dintr-o

listă de valori. Lista poate fi specificată ca valori literale, folosind o listă de valori

separate prin virgule şi încadrate între paranteze, sau poate fi selectată din baza de

date folosind o subselecţie (o subinterogare), care este o interogare în cadrul unei alte

interogări.

Exemple de utilizare a operatorului IN:

Să se afişeze toate filmele pentru care COD_GEN_FILM este Drama,

Forgn sau Rmce.

SELECT COD_GEN_FILM AS GEN, TITLU_FILM

FROM FILM

WHERE COD_GEN_FILM IN ('Drama','Forgn','Rmce')

ORDER BY COD_GEN_FILM, TITLU_FILM;

Să se afişeze toate filmele pentru care descrierea genului conţine cuvântul

„and". Aveţi nevoie de o subinterogare prin care să găsiţi toate valorile

COD_GEN_FILM care conţin cuvântul „and" în descriere. Operatorul IN

este apoi folosit pentru a găsi filmele care au unul dintre codurile selectate

de subinterogare.

SELECT COD_GEN_FILM AS GEN, TITLU_FILM

FROM FILM

WHERE COD_GEN_FILM IN

(SELECT COD_GEN_FILM

FROM GEN_FILM

WHERE GEN_FILM DESCRIPTION LIKE '% and %')

ORDER BY COD_GEN_FILM AS GEN, TITLU_FILM;

EXISTS

Operatorul EXISTS este folosit pentru a detemina dacă o subinterogare conţine

înregistrări. Dacă în setul de rezultate al subinterogării nu există nici un rând,

operatorul returnează valoarea „false‖; dacă setul de rezultate conţine cel puţin un

rând, valoarea devine „adevărat‖.

Exemple de utilizare a operatorului EXIST:

Filmul The Last Samurai se închiriază bine atât în format DVD, cât şi-n

format VHS şi se doreşte să se asigure că în inventarul magazinului există o copie

VHS. Tabelul FILM_COPIAT conţine un rând pentru fiecare copie a unui film din

inventarul magazinului, aşa că puteţi folosi o subinterogare pentru a afla dacă există

copii VHS ale filmului în inventar. De cele mai multe ori, operatorul EXISTS este

folosit in conjuncţie cu o formă mai complexă de subinterogare, numită subinterogare

corelat. (correlated subquery),în care valorile datelor din interogarea externă

(ID_FILM, în acest caz) sunt comparate cu rândurile din interogarea intenă.

SELECT ID_FILM, TITLU_FILM

FROM FILM m

WHERE TITLU_FILM = 'The Last Samurai'

AND EXISTS

(SELECT ID_FILM

FROM FILM_COPIAT c

WHERE m. ID_FILM = c. ID_FILM);

Dacă se inversează logica, folosind operatorul NOT EXISTS, puteţi afişa titlul

filmului numai dacă nu există o copie VHS în inventar.

SELECT ID_FILM, TITLU_FILM

Page 117: Curs Sinteza SQL

FROM FILM m

WHERE TITLU_FILM = 'The Last Samurai'

AND NOT EXISTS

(SELECT ID_FILM

FROM FILM_COPIAT c

WHERE m. ID_FILM = c. ID_FILM);

Operatori aritmetici

În SQL, operatorii aritmetici sunt folositi pentru efectuarea calculelor

matematice – la fel ca şi în formulele dintr-o foaie de calcul tabelar sau într-un limbaj

de programare, precum Java sau C. Cei patru operatori aritmetici din SQL sunt:

Op

erator

Descri

ere

+ Adun

are

- Scăde

re

* Înmul

ţire

/ Împăr

ţire

Ca şi în cazul operatorilor conjunctivi, dacă se amestecă operatorii aritmetici

în aceeaşi instrucţiune SQL fără a folosi paranteze, ordinea în care sunt evaluate

operaţiile este determinată de prioritatea predefinită. Din fericire, prioritatea

operatorilor din SQL este cea pe care o folosim în operaţiile matematice obişnuite.

Exemple de utilizare a operatorilor aritmetici:

Cât v-ar costa să cumpăraţi copiile VHS şi DVD ale filmului The Last

Samurai?

SELECT PRET_VANZARE_VHS + PRET_VANZARE _DVD AS COST

FROM FILM

WHERE TITLU_FILM = 'The Last Samurai';

Cât v-ar costa aceeaşi achiziţie dacă aţi avea un bon valoric de 5$?

SELECT (PRET_VANZARE _VHS + PRET_VANZARE _DVD) - 5 AS

COST

FROM FILM

WHERE TITLU_FILM = 'The Last Samurai';

Dacă taxele sunt de 8.25% (0.0825), cât reprezintă taxele de vânzare din

costul achiziţiei anterioare?

SELECT (PRET_VANZARE _VHS+ PRET_VANZARE _DVD) * 0.0825

AS TAX

FROM FILM

WHERE TITLU_FILM = 'The Last Samurai';

Care este costul mediu pentru o copie a filmului The Last Samurai?

SELECT (PRET_VANZARE_VHS+PRET_VANZARE _DVD) / 2

AS AVG_COST

FROM FILM

WHERE TITLU_FILM = 'The Last Samurai'

Page 118: Curs Sinteza SQL

Funcţii SQL elementare

O funcţie este un tip special de program, care returnează o singură valoare de

fiecare data când este apelată. Termenul provine de la conceptul matematic al unei

funcţii. În SQL, funcţiile necesită întotdeauna specificarea unei expresii, care deseori

include numele unei coloane. Cel mai des, funcţiile sunt folosite în lista de coloane a

unei instrucţiuni SELECT, sunt apelate pentru fiecare rând prelucrat de interogare şi,

ca urmare, returnează o singură valoare pentru fiecare rand din setul de rezultate.

Uneori este folosit termenul funcţie de coloană, pentru a indica faptul că funcţie este

aplicată unei coloane dintr-un tabel sau o vizualizare. Un număr de funcţii sunt

furnizate de producătorul DBMS şi se pot scrie propriile funcţii, folosind un limbaj

special livrat împreună cu sistemul DBMS, cum ar fi PL/SQL pentru Oracle sau

Transact SQL pentru Microsoft SQL Server şi Sybase Adaptive Server.

Funcţiile pot fi clasificate în multe moduri, dar majoritatea specialiştilor le

împart după ceea ce fac.

Funcţii pentru caractere Funcţiile pentru caractere sunt numite astfel deoarece manipulează date de tip

text.

Concatenarea şirurilor de caractere

Funcţia de concatenare a şirurilor de caractere reuneşte mai multe şiruri de

caractere pentru a forma o singură valoare în rezultatele interogării. Funcţia standard

de concatenare a şirurilor de caractere din SQL este apelată cu două bare verticale (||),

dar există şi excepţii, cum ar fi Microsoft SQL Server, care foloseşte semnul plus (+)

pentru concatenarea şirurilor de caractere.

Exemple de concatenare a şirurilor de caractere:

Magazinul de produse video vrea să trimită fiecărui client o scrisoare care

începe cu formula "Client", plus prenumele şi numele persoanei. Numele

sunt stocate în tabelul PERSON. Soluţia acestei cerintţe în Oracle:

SELECT 'Client' || NUME_PERSOANA||

' ' || NUME_FAMILIE_PERSOANA AS SALUT_CLIENT

FROM PERSOANA;

Aceeaşi soluţie, modificată pentru a funcţiona în Microsoft SQL Server

:

SELECT ‚Client' + NUME_PERSOANA +

' ' + NUME_FAMILIE_PERSOANA AS SALUT_CLIENT

FROM PERSOANA;

UPPER

Funcţia UPPER transformă literele dintr-un şir de caractere în litere mari.

Numerele şi caracterele speciale sunt lăsate ca stare.

Exemple:

Să se afişeze comediile (COD_GEN_FILM = 'Comdy') scriind titlurile cu

majuscule.

SELECT UPPER(TITLU_FILM) AS TITLU_FILM

FROM FILM

WHERE COD_GEN_FILM = 'Comdy';

Funcţia UPPER este deseori folosită în condiţiile WHERE. Să presupunem că

nu vă amintiţi dacă valorile COD_GEN_FILM au fost stocate cu litere mari, litere

Page 119: Curs Sinteza SQL

mici sau combinaţii ale acestora. Dacă în condiţia WHERE transformaţi valorile în

litere mari, puteţi obţine rezultatele corecte indiferent de modul de stocare.

SELECT UPPER(TITLU_FILM) AS TITLU_FILM

FROM FILM

WHERE UPPER(COD_GEN_FILM) = 'COMDY';

Atenţie la folosirea funcţiilor SQL în condiţiile WHERE. În cele mai multe

situaţii, pentru o coloană căreia îi este aplicată o funcţie nu poate fi folosită indexarea.

Ca urmare, în cazul tabelelor mari, utilizarea funcţiilor în condiţiile WHERE poate

duce la probleme de performanţă cu adevărat memorabile.

LOWER

Funcţia LOWER este inversa funcţiei UPPER — transformă literele dintr-un *

de caractere în litere mici.

Îată câteva exemple de utilizare a funcţiei LOWER:

Să se afişeze comediile (GEN_COD_FILM = 'Comedy') scriind titlurile cu

minuscule.

SELECT LOWER(TITLU_FILM) AS TITLU_FILM

FROM FILM

WHERE GEN_COD_FILM = 'Comedy';

Se poate folosi funcţia LOWER într-o clauză WHERE, atunci când nu ştiti

sigur ce tip de litere confine textul pe care vreţi să-1 comparaţi. Afişaţi toate filmele

care au în titlu cuvântul „of ", indiferent dacă este scris cu litere mari sau mici.

SELECT TITLU_FILM

FROM FILM

WHERE LOWER(TITLU_FILM) LIKE ' % of %'

OR LOWER(TITLU_FILM) LIKE 'of % '

OR LOWER(TITLU_FILM) LIKE ' % of ';

SUBSTR

Funcţia SUBSTR spare în majoritatea implementărilor SQL, dar uneori are un

nume puţin diferit. De exemplu, funcţia se numeşte SUBSTRING în Microsoft SQL

Server, Sybase Adaptive Server şi MySQL, dar SUBSTR în Oracle şi D132. Funcţia

returnează o porţiune a şirului de caractere, în funcţie de parametrii furniizaţi, care

specifică numele coloanei, poziţia de început a subşirului în datele coloanei şi

lungimea subşirului returnat (numărul de caractere). Deşi este o utilizare mai puţin

obişnuită, funcţia SUBSTR acceptă şi un şir de caractere literal în locul numelui unei

coloane. Iată forma generală a funcţiei, urmată de un exemplu:

SUBSTR (numele coloanei, poziţia de început, lungimea subşirului

În tabelul PERSON, unele persoane au al doilea nume în întregime, alţii au

numai initiale. Afişati numele complet al persoanelor al căror nume de familie începe

cu litera „B", sub forma unui singer şir de caractere care conţine prenumele, iniţiala şi

numele de familie.

Iată soluţia, pentru Oracle:

SELECT NUME_PERSOANA || ' ' ||

SUBSTR(PRENUME_PERSOANA, 1, 1) || ' . ' ||

NUME_FAMILIE_PERSOANA AS NUME_INTREG

FROM PERSOANA

WHERE SUBSTR(NUME_FAMILIE_PERSOANA, 1, 1)='B'

Page 120: Curs Sinteza SQL

Observaţi folosirea funcţiei SUBSTR în clauza WHERE pentru a elimina din

rezultate persoanele al căror nume de familie nu începe cu litera „B". Ar trebui să vă

puteţi deja gândi la alte moduri de a face acest lucru, prin folosirea operatorului LIKE.

Iată şi versiunea pentru Microsoft SQL Server a exemplului anterior:

SELECT NUME_PERSOANA + ' ' +

SUBSTRING(PRENUME_PERSOANA, 1, 1) +' . '+

NUME_FAMILIE_PERSOANA AS NUME_INTREG

FROM PERSOANA

WHERE SUBSTRING (NUME_FAMILIE_PERSOANA, 1, 1) = 'B'

LENGTH

Funcţia LENGTH returnează lungimea unui şir de caractere. Microsoft SQL

Server şi Sybase Adaptive Server folosesc numele LEN pentru versiunea proprie a

acestei funcţii.

Exemple:

Să se afişeze lungimea titlului pentru filmul a cărui valoare ID_FILM este 1.

Presupunem că folosiţi o bază de date oracle, DB2 sau MzSQL.

SELECT TITLU_FILM, LENGTH (TITLU_FILM) AS LENGTH

FROM FILM

WHERE ID_FILM = 1;

Să se afişeze lungimea titlului pentru filmul a cărui valoare ID_FILM este 1.

Presupunem că folosiţi o bază de date Microsoft SQL Server.

SELECT TITLU_FILM, LEN (TITLU_FILM) AS LENGTH

FROM FILM

WHERE LEN (TITLU_FILM) < 10;

Funţii matematice Funcţiile matematice manipulează valori numerice, în conformitate cu regulile

matematicii.

ROUND

Funcţia ROUND rotunjeşte o valoare la un număr specificat de zecimale.

Valoarea numerică este furnizată prin primul parametru, iar numărul de zecimale prin

cel de-al doilea. În continuare este prezentat formatul general al funcţiei ROUND.

ROUND (expresie numerică, număr de poziţii zecimale)

Care este costul mediu al unei copii a filmului The Last Samurai, rotunjit la

două zecimale?

SELECT ROUND((PRET_VANZARE_VHS + PRET_VANZARE

_DVD) / 2, 2) AS AVG_COST

FROM FILM

WHERE TITLU_FILM = 'The Last Samurai';

Alte funcţii matematice Tabelul care urmează prezintă funcţiile matematice cel mai des

întâlnite. Pentru toate, sintaxa generală este aceeaşi:

NUME_FUNCTIE (expresie)

F Descriere

Page 121: Curs Sinteza SQL

uncţie

A

BS

Valoarea absolută a unui număr dat

C

OS

Cosinusul trigonometric al unui unghi specificat în radiani

E

XP

Valoarea exponenţială a unui număr dat

P

OWER

Ridică un număr la o putere (numărul şi puterea sunt fumizate ca

parametri)

SI

N

Sinusul trigonometric al unui unghi specificat în radiani

T

AN

Tangenta trigonometrică a unui unghi specificat în radiani

Funcţii de conversie

Funcţiile de conversie transformă date dintr-un tip de date în altul.

CAST

Funcţia CAST transformă date dintr-un tip de date în altul. Iată sintaxa

generală a funcţiei CAST, urmată de un exemplu:

CAST (expresie AS tip de date)

Afişati preţul pentru formatul DVD al filmului The Last Samurai, cu un

simbol dolar în faţa sumei. Valoarea numerică trebuie să fie convertită într-un şir de

caractere pentru a putea fi concatenată cu o valoare literală conţinând simbolul dolar.

SELECT '$' || CAST(PRET_VANZARE _DVD AS VARCHAR(6)) AS PRET

FROM FILM

WHERE TITLU_FILM = 'The Last Samurai';

CONVERT TO

Multe implementări DBMS pun la dispoziţie o funcţie CONVERT sau

CONVERT TO. Totuşi este recomandată folosirea funcţiei CAST, deoarece este

implementată într-un mod mai unitar de către diferiţi producători.

Funcţii de agregare şi gruparea rândurilor

O funcţie de agregare (aggregate functions) este o funcţie care combină mai

multe rânduri de date într-un singur rând. Tabelul următor prezintă funcţiile de

agregare acceptate în majoritatea implementărilor SQL:

F

uncţie

Descriere

A

VG

Calculează valoarea medie pentru o coloană sau o

expresie.

C

OUNT

Numără valorile dintr-o coloană.

M

AX

Găseşte valoarea maxină dintr-o coloană.

M

IN

Găseşte valoarea minimă dintr-o coloană.

S

UM

Însumează valorile dintr-o coloană.

Page 122: Curs Sinteza SQL

Exemple:

Care este preţul mediu al unui DVD?

SELECT ROUND(AVG(PRET_VANZARE _DVD),2) AS AVG_PRET

FROM FILM;

Câte filme există în tabelul FILM?

SELECT COUNT(*) AS NUM_FILM

FROM FILM;

Câte genuri diferite de filme sunt reprezentate în tabelul FILM?

SELECT COUNT(DISTINCT(COD_GEN_FILM)) AS NUM_GEN

FROM FILM;

Care sunt lungimea minimă şi maximă a titlurilor filmelor?

SELECT MIN(LENGTH(TITLU_FILM)) AS MIN_LENGTH,

MAX(LENGTH(TITLU_FILM)) AS MAX_LENGTH

FROM FILM;

Clauza GROUP BY

GROUP BY cere sistemului DBMS să grupeze rândurile selectate de

interogare pe baza valorilor din una sau mai multe coloane şi să aplice funcţia (sau

funcţiile) de agregare fiecărui grup, returnând un rând pentru fiecare grup din setul de

rezultate.

Sistemul DBMS va ordona rândurile selectate de interogare după coloanele

din clauza GROUP BY, aşa că grupurile vor fi returnate în ordine ascendentă,

exceptând cazul în care se adăugă o clauză ORDER BY care specifică un alt mod de

ordonare.

Exemplu:

Afişati fiecare cod de gen, împreună cu numărul de filme asociate fiecărui cod.

SELECT COD_GEN_FILM AS GEN, COUNT(*) AS COUNT

FROM FILM

GROUP BY COD_GEN_FILM;

Ce se întâmplă dacă scoateţi clauza GROUP BY din această interogare?

Sistemul DBMS retumează un mesaj de eroare şi, din nefericire, mesajul de eroare

este deseori destul de criptic. Functia COUNT(*) este o functie de agregare şi, în

absenta clauzei GROUP BY, retumează un singur rând de date.

Operatori pentru interogări compuse

Uneori este util să se ruleze interogări multiple şi să se combine rezultatele

într-un singur set de rezultate.

UNION

Operatorul UNION adaugă rândurile din setul de înregistrări al unei interogări

la cel al unei alte inregistrări şi, în acelaşi timp, elimină rândurile duplicate, într-un

mod similar cu cel al cuvântului cheie DISTINCT. Operaţia este permisă numai dacă

interogările sunt compatibile din punctul de vedere al uniunii, ceea ce înseamnă că au

acelaşi număr de coloane şi că tipurile de date ale coloanelor corespondente sunt

compatibile.

Exemplu:

Afişaţi pe o singură coloană toate valorile nenule pentru taxa de inchiriere şi

taxa de întârziere din tabelul FILM_ÎNCHIRIAT.

SELECT INCHIRIAT_FEE AS FEE

FROM FILM_INCHIRIAT

WHERE INCHIRIAT _FEE IS NOT NULL UNION

Page 123: Curs Sinteza SQL

SELECT LATE_OR_LOSS_FEE AS FEE

FROM FILM_INCHIRIAT

WHERE LATE _OR_ LOSS FEE IS NOT NULL;

UNION ALL

UNION ALL funcţionează la fel ca şi operatorul UNION, exceptând faptul că

rândurile duplicate nu sunt eliminate.

INTERSECT Operatorul INTERSECT găseşte valorile selectate dintr-o interogare, care apar

şi într-o altă interogare. În esenţă, găseşte intersecţia valorilor din cele două

interogări. Totuşi, doar un număr mic de sisteme DBMS (cele mai importance fiind

Oracle şi DB2) implementează acest operator. Nu-1 veţi găsi în Microsoft SQL Server

sau MySQL.

Exemplu:

Există în tabelul FILM filme pentru care preţul pentru DVD este egal cu preţul

pentru VHS?

SELECT INCHIRIAT_FEE AS FEE

FROM FILM_ INCHIRIAT

WHERE INCHIRIAT _FEE IS NOT NULL

INTERSECT

SELECT LATE_OR_LOSS_FEE AS FEE

FROM FILM_ INCHIRIAT

WHERE LATE OR_ LOSS FEE IS NOT NULL

EXCEPT

EXCEPT este operatorul standard ANSI/ISO care găseşte diferenţele dintre

două seturi de rezultate, returnând, în esenţă, valorile din prima interogare care nu

apar în cea de-a doua interogare. Foarte puţine sisteme DBMS implementează acest

operator. În unele implementări, precum Oracle, operatorul se numeşte MINUS, nu

EXCEPT.

Întrebări şi Probleme

Alegeţi răspunsurile corecte pentru fiecare din următoarele întrebări cu

răspunsuri multiple. Reţineţi că întrebările pot avea mai multe răspunsuri corecte.

1. O instrucţiune SELECT fără o clauză WHERE

a. Selectează toate coloanele din tabel sau vizualizare

b. Returnează un mesaj de eroare

c. Selectează toate rândurile din tabel sau vizualizare

d. Afişează numai definiţia tabelului sau a vizualizării

e. Scrie întotdeauna rezultatele într-un fişier jurnal

2. În SQL, ordinea rândurilor din rezultatele interogării

a. Este specificată de clauza SORTED BY

b. Poate fi ascendentă sau descendentă pentru orice coloană

c. În mod prestabilit este descendentă, dacă nu se specifică o altă ordine

d. Este imprevizibilă dacă nu este specificată in interogare

Page 124: Curs Sinteza SQL

e. Poate fi specificată numai pentru coloanele din setul de rezultate al

interogării

3. Operatorul BETWEEN

a. Specifică un domeniu de valori care include şi capetele

b. Poate fi rescris folosind operatorii <= şi NOT <=

c. Poate fi rescris folosind operatorii <= şi >=

d. Selectează rândurile adăugate în tabel într-un anumit interval de timp

e. Nu este inclus în standardul ISO/ANSI

4. Operatorul LIKE standard

a. Foloseşte semne de întrebare drept caractere de înlocuire poziţionale

b. Foloseşte liniuţe de subliniere drept caractere de înlocuire poziţionale

c. Foloseşte liniuţe de subliniere drept caractere de înlocuire nepoziţionale

d. Foloseşte simboluri procent drept caractere de înlocuire poziţionale

e. Foloseşte simboluri procent drept caractere de înlocuire nepoziţionale

5. O instrucţiune SQL care confine o funcţie de agregare

a. Poate conţine şi coloane calculate

b. Poate conţine şi coloane obisnuite

c. Trebuie să includă o clauză ORDER BY

d. Trebuie să includă o clauză GROUP BY

e. Nu poate include, în acelaşi timp, o clauză GROUP BY şi o clauză

ORDERBY

6. Când operatorii AND şi OR sunt combinaţi în aceeaşi clauză WHERE

a. Sistemul SGBD returnează un mesaj de eroare

b. Operatorul AND are prioritate mai mare decât operatorul OR

c. Operatorul AND are prioritate mai mică decât operatorul OR

d. Parantezele, sunt obligatorii

e. Parantezele sunt opţionale

7. Sintaxa corectă pentru eliminarea valorilor nule din rezultatele interogării

este

a. = NULL

b. NOT = NULL

c. <>NULL

d. IS NULL

e. IS NOT NULL

8. Funcţiile SQL standard pentru şiruri de caractere includ

a. UPPER

b. MIDDLE

c. LOWER

d. SUBSTR

e. EXISTS

9. Funcţiile, SQL matematice standard includ

a. LENGTH

b. ROUND

c. CAST

d. MIN

e. ABS

10. Operatorul UNION

a. Elimină rândurile duplicate din setul de rezultate

b. Include rândurile duplicate în setul de rezultate

Page 125: Curs Sinteza SQL

c. Combină două interogări într-o singură interogare de tip join

d. Combină seturile de rezultate a două interogări într-un singur set de

rezultate

e. Este numit JOIN în unele implementări SQL

Scrieţi instrucţiunile SQL pentru următoarele probleme

1. Găsiţi toate filmele din tabelul FILM pentru care

MPAA_COD_INCHIRIERE are altă valoare decât „R".

2. Afişaţi titlurile şi preţurile tuturor filmelor pentru care

PRET_VANZARE_DVD este cel puţin 19.99, dar nu mai mare de 29.99,

ordonate crescător după preţ.

3. Afişaţi toate filmele pentru care genul (COD_GEN_FILM) este Comdy şi

categoria MPAA (MPAA _COD_INCHIRIERE) este PG-13, împreună cu

filmele pentru care genul este Drama şi categoria este R.

4. 14. Câte închirieri (tabelul FILM_INCHIRIAT) nu au nici o valoare în

coloana LATE_OR_LOSS_FEE?

5. Câte persoane au un nume de familie (NUME_FAMILIE_PERSOANA)

care conţine litera „a", majusculă sau minusculă?

6. Afişaţi toate titlurile de filme care conţin cuvântul „the", cu sau fără literă

mare.

7. Folosiţi funcţia SUM pentru a afla totalul valorilor din coloana

PLATA_INCHIRIAT din tabelul FILM_INCHIRIAT.

8. Afişaţi primele cinci caractere din numele de familie

(NUME_FAMILIE_PERSOANA) din tabelul PERSOANA, dar eliminaţi

toate valorile duplicate din setul de rezultate?

9. Din tabelul FILM, afişaţi toate genurile (COD_GEN_FILM), împreună cu

media preţurilor pentru DVD (PRET_VANZARE_DVD) pentru fiecare

gen, rotunjită la două poziţii zecimale.

10. Afişaţi toate filmele (ID_FILM) care au fost închiriate (tabelul

FILM_INCHIRIAT), cu suma totală strânsă din taxele de închiriere

(PLATA_INCHIRIAT) sau taxele de întârziere sau pierdere

(PLATA_PENALIZARE) pentru filmul respectiv. Sugestie: adunaţi

valorile PLATA_INCHIRIAT şi PLATA_PENALIZARE, apoi însumaţi

(SUM) rezultatul respectiv pentru fiecare valoare ID_FILM. Unele valori

din coloana PLATA_PENALIZARE sunt nule, aşa că, dacă nu aveţi o

funcţie care să înlocuiască valorile nule cu o altă valoare (zero, în acest

caz), veţi obţine valori nule în rezultate. În Oracle, funcţia se numeşte

NVL, în Microsoft SQL Server se numeşte ISNULL, iar în MySQL se

numeşte IFNULL. (Se pare că nu există o funcţie echivalentă în D132).

Lecţia 4. Combinarea datelor din mai multe tabele

S-au prezentat până acum instrucţiuni SQL care selectează date dintr-un singur

tabel. Deseori, este util să se combine date din tabele multiple într-o singură

interogare . De exemplu, în listingul celor trei coloane ale tabelului FILM din figura

următoare, observaţi valorile afişate pentru coloană FILM_GEN_COD. Atunci când

s-a proiectat baza de date pentru magazinul de produse video, s-au folosit coduri în

locul descrierilor complete pentru genurile filmelor în tabelul FILM. Din discuţia

Page 126: Curs Sinteza SQL

despre procesul de normalizare, s-a evitat anomalia de actualizare – dacă se schimbă

descrierea unui gen, nu este nevoie să actualizăm acea descriere pentru toate filmele

asociate genului respectiv în tabelul FILM. În timpul normalizării, descrierea

genurilor a fost mutată în tabelul, FILM_GEN, iar coloană FILM_GEN_COD a

devenit cheie externă în tabelul FILM, referind coloană cheie primară (cu acelaşi

nume) din tabelul FILM_GEN. S-a optat pentru folosirea unui cod mnemonic pentru

codurile genurilor, deoarece astfel permit celor familiarizaţi cu datele respective să

înţeleagă genul asociat filmelor fără să le caute în tabelul FILM_GEN.

FILM_COD FILM_GEN_COD FILM_TITLU

1 Drama Mystic River

2 ActAd The Last Samurai

3 Comedie Something's Gotta Grve

4 ActAd The Italian

5 ActAd Kill Bill: Voi. 1

6 ActAd Pirates of the Caribbean: Trie Curse of the Black

Pearl

7 Drama Big Fish

8 ActAd Man on Fire

9 ActAd Master and Commander The Far Side of the

World

10 Drama LosI în Translation

11 Rmce Two Weeks Notice

12 Comedie 50 First Dates

13 Comedie Matchstick Men

14 Drama Cold Mountain

15 Drama Road to Perdition

16 Comedie The School of Rock

17 Rmce 13 Going on30

18 Drama Monster

19 ActAd The Day After Tomorrow

20 Forgn Das Boot

Tabelul FILM (trei coloane)

Evident, nu puteţi afişa pe pagina web a magazinului de produse video,

tabelul FILM aşa cum este prezentat în figura de mai sus - trebuie să obţineţi

descrierea completă a genurilor din tabelul FILM_GEN. Aceasta este ideea

capitolului de faţă: combinarea datelor din mai multe tabele într-o singură interogare.

Figura următoare prezintă un listing al tabelului FILM_GEN.

FILM_GEN_COD FILM_GEN_DESCRIERE

ActAd Actiune

Anime Animatie

ChFam Copii şi Familie

Class Clasic

Comedie Comedie

Doc Documentar

Drama Drama

Forgn Strain

Page 127: Curs Sinteza SQL

Hor Horror

Indep Independent

Music Muzical

Rmce Romance(Romantic, Idila)

SciFi Stiintifico-Fantastic

Sport Sport

Thriller Groaza

Tabelul FILM_GEN

Page 128: Curs Sinteza SQL

Uniuni (join)

O uniune (join) este o operaţie într-o bază de date relaţionale care combină

coloane din două sau mai multe tabele în rezultatele unei singure interogări. O uniune

apare de fiecare dată când clauza FROM a unei instrucţiuni SELECT specifică

numele mai multor tabele.

De exemplu:

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM, FILM_GEN ORDER BY FILM_ID;

FIL

M_ID

GEN FILM_TITLU

1 Actiune şi Aventura Mystic River

1 Animatie Mystic River

1 Clasic Mystic River

1 Documentar Mystic River

1 Strain Mystic River

1 Independent Mystic River

1 Groaza Mystic River

1 Sport Mystic River

1 SF Mystic River

1 Musical Mystic River

1 Horror Mystic River

1 Drama Mystic River

1 Comedie Mystic River

1 Copii şi Familie Mystic River

1 Actiune şi Aventura The Last Samurai

2 Thriller The Last Samurai

2 Sport The Last Samurai

2 SF The Last Samurai

2 Romantic The Last Samurai

2 Musical The Last Samurai

2 Independent The Last Samurai

2 Horror The Last Samurai

2 Animatie The Last Samurai

2 Copii şi Familie The Last Samurai

2 Documentar The Last Samurai

2 Strain The Last Samurai

2 Drama The Last Samurai

2 Comedie The Last Samurai

2 Clasic The Last Samurai

.. ... ...............

Setul de rezultate al interogării a fost trunchiat după primele două titluri de

filme . Problema este că am cerut bazei de date să unească tabelele, dar nu i-am spus

care este corespondenţa dintre rândurile celor două tabele. Rezultatul este cunoscut

sub numele de produs cartezian (după numele filozofului şi matematicianului francez

Rene Descartes) şi, în bazele de date relaţionale, este un set de rezultate obţinut prin

uniunea dintre fiecare rând al unui tabel cu fiecare rând dintr-un alt tabel.

Page 129: Curs Sinteza SQL

Soluţia este să specificăm cum se va face unirea tabelelor. Trebuie indicat ce

coloane ar trebui să se potrivească pentru a uni două rânduri din cele două tabele, în

mod normal, cele două coloane vor fi cheia primară dintr-un tabel şi cheia externă din

celălalt tabel, dar pot există şi excepţii. Pentru a realiza acest lucru trebuie să se facă o

o uniune standard relaţională, cunoscut şi sub numele de uniune de egalitate

(equijoin).

Uniuni de egalitate (equijoin)

Avem o uniune de egalitale (equijoin), numită şi uniune internă (inner join),

atunci când legăm una sau mai multe coloane dintr-un tabel (de obicei, o cheie

externă) cu coloane similare dintr-un alt tabel (de obicei, cheia primară), folosind

condiţia de egalitale, aceasta fiind cea mai des folosită formă de uniune. Totusi,

termenul uniune de egalitate (equijoin) este rareori folosit în afara mediilor

academice, find preferate denurmirile uniune internă (inner join) sau uniune standard

(standard join ).

Există două modalităţi de specificare a coloanelor corespondente: folosind

clauza WHERE sau folosind clauza JOIN. Clauza JOIN a fost adaugată relativ recent

în standardul SQL, aşa că programatorii mai vechi sunt obisnuiţi cu metoda bazată pe

clauza WHERE.

Realizarea uniunilor folosind clauza WHERE

Folosirea clauzei WHERE pentru unirea tabelelor seamănă cu folosirea

acesteia pentru eliminărea rândurilor de care nu aveţi nevoie din setul de rezultate.

Totuşi, există unele diferenţe.

În clauza WHERE :

Se compară o coloană cu o altă co1oană, nu o coloană cu o constantă sau o

expresie.

Atunci când coloanele din cele două tabele au acelaşi nume (o soluţie

recomandată) trebuie să specificati numele complet al coloanelor (adică numele cu

calificator), astfel încât motorul SQL să ştie care dintre cele două coloane este

referită. Motorul SQL cere să se refere toate coloanele specificate într-o instrucţiune

SQL. Aceasta nu înseamnă numai coloanele din clauza WHERE, ci din orice alt loc al

instrucţunii, inclusiv în lista SELECT. Cea mai simplă formă de calificator este chiar

numele tabelului, separat cu caracterul punct de numele coloanei. În continuare este

prezentat un exemplu de uniune realizată prin clauza WHERE, cu numele coloanelor

specificate complet, folosind numele tabelelor. Observaţi că interogarea selectează

coloanele FILM_ID şi FILM_TITLU din tabelul FILM şi genul corespunzător

(FILM_GEN_DESCRIERE) din tabelul FILM_GEN.

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM, FILM_GEN

WHERE FILM.FILM_GEN_COD= FILM_GEN.FILM_GEN_COD

ORDER BY FILM_ID;

FILM_ID FILM_GEN FILM_TITLU

1 Drama Mystic River

Page 130: Curs Sinteza SQL

2 Actiune şi Aventura The Last Samurai

3 Comedie Something's Gotta Give

4 Actiune şi Aventura The Italian Job

5 Actiune şi Aventura Kill Bill Vol. 1

6 Actiune şi Aventura Pirates of the

Caribbean

7 Drama Big Fish

8 Actiune şi Aventura Man on Fire

9 Actiune şi

Aventura

Master and Commander

10 Drama Lost în Translation

11 Romantic Two Weeks Notice

12 Comedie 50 First Dates

13 Comedie Matchstick Men

14 Drama Cold Mountain

15 Drama Road to Perdition

16 Comedie The School of Rock

17 Romantic 13 Going on 30

18 Drama Monster

19 Actiune şi

Aventura

The Day After Tomorrow

20 Strain Das Boot

Folosirea numelor complete ale tabelelor pentru specificarea coloanelor poate

fi obositoare şi consumatoare de timp, mai ales deoarece numele tabelelor pot avea 30

sau mai multe caractere în sistemele DBMS moderne. Din această cauză, în SQL este

permisă şi folosirea pseudonimelor (aliases) pentru numele tabelelor. Acestea

funcţionează la fel ca şi pseudonimele coloanelor din clauza SELECT, exceptând

faptul că nu este folosit cuvântul cheie „AS" (în cele mai multe implementări SQL) -

doar lăsaţi un spaţiu între numele tabelului şi pseudonim în lista FROM. Deşi unii

folosesc mnemonice pentru pseudonimul tabelelor, este mult mai des întâlnită

folosirea secvenţelor de majuscule (adică „A", „B‖,‖C‖ şi aşa mai departe). După ce

asociaţi un pseudonim unui nume de tabel în clauza FROM, trebuie să folosiţi

pseudonimul în locul numelui de tabel în întreaga instrucţiune SQL. Folosirea

pseudonimelor în clauza SELECT poate părea puţin ciudată la început deoarece

folosiţi un pseudonim înainte de a-l defini (clauza SELECT precede clauza FROM şi

s-ar putea să vi se para mai simplu să completaţi clauza FROM înainte de a completa

lista de coloane din clauza SELECT atunci când scrieţi instrucţiunile SQL.

Exemplul următor prezintă instrucţiunea anterioară, după adăugarea

pseudonimelor pentru numele tabelelor. Deşi nu era necesar, pseudonimele au fost

adăugate şi în lista de coloane din clauzele SELECT şi ORDER BY, pentru a va arăta

cum sunt folosite.

SELECT A.FILM_ID, B.FILM_GEN_DESCRIERE AS GEN,

A.FILM_TITLU

FROM FILM A, FILM_GEN B

WHERE A.FILM_GEN_COD = B.FILM_GEN_COD

ORDER BY A.FILM_ID;

Page 131: Curs Sinteza SQL

Realizarea uniunilor folosind clauza JOIN

Clauza JOIN este scrisă ca o referinţă de tabel din clauza FROM şi combină

lista de tabele din clauza FROM şi condiţia de legătură scrisă anterior în clauza

WHERE într-o singură clauză. Sintaxa generală a clauzei JOIN pentru o uniune

internă, urmată de câteva exemple.

nume_tabel [INNER) JOIN nume_tabel

{ ON condiţie | USING (nume_coloană [ , nume_coloană...]) }

Clauza ON permite specificarea unei condiţii similare cu cea din clauza

WHERE .

Clauza USING specifică numele coloanelor folosite pentru legarea rândurilor.

Totuşi, clauza USING acţionează numai atunci când coloanele pe care se face

legătură au nume identice în ambele tabele.

Exemple:

• JOIN cu condiţie ON:

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM JOIN FILM_GEN ON

FILM..FILM_GEN_COD = FILM_GEN.FILM_GEN_COD

ORDER BY FILM_ID;

• JOIN cu pseudonime în loc de nume de tabele:

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM A JOIN FILM_GEN B ON

A.FILM_GEN_COD = B.FILM_GEN_COD

ORDER BY FILM_ID;

• JOIN folosind cuvântul cheie USING (în locul condiţiei ON) o scurtatură

elegantă atunci când coloanele din cele două tabele au acelaşi nume(nu e recunoscută

de toate SGBD-urile).

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM JOIN FILM_GEN USING (FILM_GEN_COD)

ORDER BY FILM_ID;

• JOIN cu cheie externă pe mai multe coloane.

Această interogare afişează lista cu copiile filmelor din tabelul

FILM_COPY care nu au fost vândute (coloană DATA_VANZARE conţine o valoare

nulă dacă nu a fost vândută) şi care au fost închiriate (uniune cu tabelul

FILM_INCHIRIAT) dar nu au fost încă returnate (coloană RETUR_DATA conţine o

valoare nulă până la returnarea filmului). A se revedea prezentarea generală a bazei de

date a magazinului de produse video, pentru a vedea unde se încadrează tabelul în

modelul general.

SELECT FILM_ID, COPY_NUMAR, DATA_RETURNARII

Page 132: Curs Sinteza SQL

FROM FILM_COPY JOIN FILM__INCHIRIAT

USING (FILM_ID, COPY_NUMAR)

WHERE DATA_VANZARE IS NULL

AND RETUR_DATA IS NULL;

FILM _ID COPY_NUMAR DATA_RETURNARII

2 2 02/27/2005

3 2 03/04/2005

5 1 02/27/2005

5 2 02/19/2005

10 1 03/04/2005

17 1 03/04/2005

Instrucţiunile care folosesc clauza JOIN sunt mai scurte , iată interogarea

precedentă scrisă folosind condiţii de legătură în clauza WHERE. Remarcaţi că în

acest caz trebuie să specificaţi numele complet al coloanelor FILM_ID şi

COPY_NUMAR, pentru a evita referirea ambiguă a lor. Instrucţiunea de mai jos

afişează aceleaşi rezultate ca şi instrucţiunea anterioară.

SELECT A.FILM_ID, A.COPY_NUMAR, DATA_RETURNARII

FROM FILM_COPY A, FILM_INCH B WHERE A.FILM_ID = B.FILM_ID

AND A.COPY_NUMAR = B.COPY_NUMAR

AND DATA_VANZARE IS NULL

AND RETURN_DATA IS NULL;

Uniuni naturale

O uniune naturală (natural join) se bazează pe toate coloanele cu acelaşi

nume din două tabele, în esenţă, toate uniunile de egalitate sunt uniuni naturale.

Totuşi, sintaxa unei uniuni naturale este mult mai simplă, deoarece nu este necesar să

specificaţi o condiţie sau o listă de coloane - se înţelege de la sine care sunt coloanele

folosite. Reţineţi,nu toate SGBD-urile acceptă această sintaxă pentru clauza

JOIN(accepta sigur Oracle şi MySQL )..

Exemplu: uniunea tabelelor FILM şi FILM_GEN, rescrisă sub forma unei

uniuni naturale:

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM NATURAL JOIN FILM_GEN ORDER BY FILM_ID;

Uniunile pot implica mai mult de două tabele. Exemplul următor

prezintă o uniune naturală care obţine coloana FILM_ID din tabelul FILM, coloana

FILM_GEN_DESCRIERE din tabelul FILM_GEN şi din tabelul MPAA_RATING,

coloana MPAA_RATING_DESCRIERE , pentru primele trei filme din tabelul FILM.

Folosirea clauzei WHERE permte să se elimine din setul de rezultate rândurile de care

nu avem nevoie. Am permis textului din coloana RATING_DESC să treacă automat

pe linia următoare în rezultatele interogării, din cauza lungimii. Exemplul foloseşte

două clauze JOIN. Prima clauză JOIN cere motorului SQL să lege tabelele FILM şi

FILM_GEN, iar a două clauză JOIN îi cere să lege rândurile deja unite (în esenţă, un

set de rezultate intermediar) cu tabelul MPAA_RATING.

Page 133: Curs Sinteza SQL

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN,

MPAA_RATING_COD AS RATING, MPAA_RATING_DESCRIERE AS

RATING_DESC

FROM FILM NATURAL JOIN FILM_GEN NATURAL JOIN

MPAA_RATING

WHERE FILM_ID < 4 ORDER BY FILM_ID;

FILM_ID GEN RATING RATING_DESC

1 Drama R Sub 17 ani acompaniati de

parinti

2 Acţiune si Aventura R Sub 17 ani acompaniati de

parinti

3 Comedie PG-13 Cu acordul strict a

parintilor

Dacă se foloseşte o implementare SQL care nu acceptă uniunile naturale,

aceeaşi interogare scrisă folosind cuvintele cheie JOIN şi ON este:

SELECT A.FILM_ID, B.FILM_GEN_DESCRIERE AS GEN,

C.MPAA_RATING__COD AS RATING,

C.MPAA_RATING__DESCRIERE AS

RATING_DESC

FROM FILM A JOIN FILM_GEN B ON

A.FILM_GEN_COD = B.FILM_GEN_COD

JOIN MPAA_RATING C ON

A.MPAA_RATING_COD = C.MPAA_RATING_COD

WHERE FILM_ID < 4 ORDER BY FILM_ID;

Uniuni externe (outer joins)

Toate uniunile pe care le-am descris până acum sunt uniuni exclusiv(uniuni

interne), ceea ce înseamnă că singurele rânduri care apar în setul de rezultate sunt cele

pentru care a fost găsită o legătură în toate tabelele unite. Există situaţii în care vreţi

să includeţi în rezultatele interogării şi rânduri pentru care nu există o legătură.

De exemplu, dacă se doreşte o listă cu toate genurile de filme, împreună cu

toate titlurile asociate cu fiecare gen?

O uniune externă (outer join) - pentru care un nume mai potrivit ar fi uniune

inclusivă - include în setul de rezultate şi rândurile pentru care nu există legături din

cel puţin unul dintre tabele. Atunci când există rânduri fără legături, datele selectate

din tabelul în care nu a fost găsită o legătură primesc valoarea nulă. Există trei tipuri

de bază:

Uniune externă către stânga (left outer join) . Returnează toate rândurile din

tabelul din stânga (cel specificat primul în clauza JOIN), împreună cu toate rândurile

din tabelul din dreapta pentru care poate fi găsită o legătură.

(asemănatoare interogărilor din tabele aflate in relaţia 1:m)

Page 134: Curs Sinteza SQL

Uniune externă către dreapta (right outer join). Returnează toate rândurile

din tabelul din dreapta (cel specificat al doilea în clauza JOIN), împreună cu toate

rândurile din tabelul din stânga pentru care poate fi găsită o legătură, în esenţă, o

uniune externă către stânga poale fi rescrisă ca o uniune externă către dreapta

inversând ordinea de specificare a tabelelor şi înlocuind cuvântul cheie LEFT cu

RIGHT.

Uniune externă completă (full outer join). Returnează toate rândurile din

ambele tabele. Acest tip de uniune este cel mai puţin probabil să fie acceptată de toate

implementari;e SQL. Această uniune nu este acelaşi lucru cu un produs cartezian,

care leagă fiecare rând dintr-un tabel cu fiecare rând din celălalt tabel. O uniune

externă completă leagă fiecare rând dintr-un tabel cu zero sau mai multe rânduri

corespondente din celălalt tabel.

Este folosită mai mult pentru tabelele aflate in relaţia m:m

Sintaxa generală pentru o uniune externă este:

nume_tabel {RIGHT | LEFT | FULL} [OUTER] JOIN nume_tabel {

ON condiţie | USING (nume_coloană [ ,nume_coIoană. ..]) }

Exemple de uniuni externe:

• Să se afişeze toate descrierile genurilor de filme, împreună cu filmele

asociate fiecărui gen. În setul de rezultate rândurile care nu au nici o valoare în

coloană FILM_TITLU - acestea sunt genurile de filme care nu au filme asociate. Dacă

implementarea DBMS nu acceptă uniuni realizate cu cuvântul cheie USING,

modificaţi instrucţiunea astfel încât să utilizeze cuvântul cheie ON, ca în exemplul

care urmează după acesta.

SELECT FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM_GEN LEFT OUTER JOIN FILM USING

(FILM_GEN_COD);

GEN FILM_TITLU

Actiune şi Aventura Kill Bill: Vol. 1

Actiune şi Aventura Man on Fire

Actiune şi Aventura Pirates of the Caribbean

Actiune şi Aventura Master and Commander

Actiune şi Aventura The Day After Tomorrow

Actiune şi Aventura The Last Samurai

Actiune şi Aventura The Italian Job

Anime and Animation

Copii şi Familie

Clasic

Comedie 50 First Dates

Comedie Matchstick Men

Comedie The School of Rock

Comedie Something's Gotta Give

Documentar

Page 135: Curs Sinteza SQL

Drama Big Fiah

Drama Road to Perdition

Drama Mystic River

Drama Monster

Drama Cold Mountain

Drama Lost în Translation

Strain Das Boot

Horror

Independent

Musical

Romantic 13 Going on 30

Romantic Two Weeks Notice

• Interogarea anterioară, rescrisă ca uniune externă către dreapta,

cu condiţie ON.

SELECT FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM RIGHT OUTER JOIN FILM_GEN

ON FILM.FILM_GEN_COD =FILM_GEN.FILM_GEN_COD;

• Interogarea anterioară, rescrisă ca uniune externă completă. Deoarece

fiecare film trebuie să aibă asociat un gen, această interogare va produce aceleaşi

rezultate ca şi uniunea externă către dreapta din interogarea anterioară. Totuşi, dacă

genurile filmelor ar fi opţionale, uniunea externă completă v-ar fi permis să afişaţi atât

genurile care nu au filme asociate, cât şi filmele care nu au genuri asociate.

SELECT FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM FULL OUTER JOIN FILM_GEN

ON FILM.FILM_GEN_COD = FILM_GEN.FILM_GEN_COD;

• Afişaţi descrierile genurilor care nu au nume asociate. Există şi alte moduri

de a face acest lucru, dar exemplul de faţă foloseşte faptul că rândurile pentru care nu

există legături returnează valori nule pentru a selecta numai genurile care nu au nume

asociate.

SELECT FILM_GEN_DESCRIERE AS GEN

FROM FILM RIGHT OUTER JOIN FILM_GEN

ON FILM.FILM_GEN_COD = FILM_GEN.FILM_GEN_COD

WHERE FILM_TITLU IS NULL;

GEN

Page 136: Curs Sinteza SQL

Animatie

Copii şi Familie

Clasic

Documentar

Horror

Independent

Musical

SF

Special Interes

Sport

Thriller

Ca răspuns la cererile clienţilor, mai mulţi producători de baze de date

relaţionale au introdus uniunile externe inainte de standardizarea clauzei JOIN.

Secţiunile următoare prezintă câteva implementări specifice ale sintaxei uniunii

externe. Aceste soluţii particulare sunt prezentate aici numai pentru că s-ar putea să le

intâlniţi în instrucţiuni SQL mai vechi

Sintaxa uniunii externe în Oracle

Oracle Corporation a decis să folosească un semn plus încadrat de paranteze

pentru definirea uniunilor externe. Simbolul ,,(+)― este plasat în clauza WHERE în

partea opusă tabelului din care vreţi să fie returnate toate rândurile (indiferent dacă

există legături pentru ele în celalalt tabel). Deoarece datele din celălalt tabel (cel din

care sunt returnate numai rândurile pentru care există legături) sunt completate cu

valori nule atunci când nu este găsit un rând corespondent, este mai uşor să reţineţi că

simbolul ,,(+)― este plasat în partea clauzei WHERE unde vreţi să adăugaţi valori

nule. Iată exemplul anterior rescris folosind sintaxa Oracle:

SELECT FILM_GEN_DESCRIERE AS GEN

FROM FILM A, FILM_GEN B

WHERE A.FILM_GEN_COD(+) = B.FILM_GEN_COD AND FILM_TITLU

IS NULL;

Sintaxa uniunii externe în Microsoft SQL Server

Microsoft SQL Server foloseşte operatorul „*=" în condiţia WHERE pentru o

uniune externă către stânga şi operatorul „=*" pentru o uniune externă către dreapta.

În ambele cazuri, este obligatoriu ca asteriscul şi semnul egal să nu fie separate de

spaţii. Iată exemplul anterior rescris folosind sintaxa Microsoft SQL Server (ca uniune

externă către dreapta):

SELECT FILM_GEN_DESCRIERE AS GEN

FROM FILM A, FILM_GEN B

WHERE A.FILM_GEN_COD =* B.FILM_GEN_COD

AND FILM TITLU IS NULL;

Page 137: Curs Sinteza SQL

Auto-uniuni (seif joins)

O auto-uniune (selfjoin) este o uniune a unui tabel cu el însuşi. Există relaţii

în care cheia primară şi cheia externă se află în acelaşi tabel. Acestea se numesc

relaţii recursive. În baza de date a magazinului de produse video există o relaţie

recursivă în tabelul angajaţi.

Tabelul ANGAJAT are o coloană numită SUPERVISOR_PERSOANA_ID,

care este o cheie externă către coloană PERSOANA_ID din acelaşi tabel. Este folosită

pentru a lega fiecare angajat de şeful direct, care, desigur, este un alt angajat, ceea ce

înseamnă că şi şeful respectiv are o coloană în tabelul ANGAJAT. Interogarea

următoare afişează trei coloane din tabelul ANGAJAT, inclusiv PERSOANA_ID şi

SUPERVISOR_PERSOANA_ID:

SELECT PERSOANA_ID, ANGAJAT_PLATA_ORE AS PLATA_ORE,

SUPERVISOR_PERSOANA_ID PROM ANGAJAT;

PERSOANA_ID PLATA_ORE SUPERVISOR_PERSOANA_ID

1 15

2 9.75 1

10 9.75 1

Aceste date arată că angajaţii 2 şi l0 sunt subordonaţi angajatului 1, iar

angajatul 1 nu e subordonat nimanui. .

Uniuni încrucişate (cross joins)

O uniune încrucişată (cross join) nu este altceva decât sintaxa standard

pentru un produs cartezian. Interogarea care care unea tabelele FILM şi FILM_GEN

şi obţinea un produs cartezian poate fi rescrisă ca mai jos, folosind o uniune

încrucişată:

SELECT FILM_ID, FILM_GEN_DESCRIERE AS GEN, FILM_TITLU

FROM FILM CROSS JOIN FILM_GEN ORDER BY FILM_ID;

Subinterogări

O caracteristică foarte puternică a limbajului SQL sunt subinterogările (numite

şi selecţii), care, aşa cum sugerează şi numele, se referă la o instrucţiune SELECT

care contine o instrucţiune SELECT subordonată. De obicei, subinterogările sunt

folosite în clauza WHERE, ca modalitate de limitare a rândurilor returnate în setul de

rezultate al interogării externe. Aceasta poate fi o modalitate foarte flexibilă de

selectare a datelor.

O regulă esenţială de sintaxă este ca subinterogarea să fie încadrată de

paranteze.

Orice operaţie efectuată cu o subinterogare poate fi facută şi printr-o uniune.

Page 138: Curs Sinteza SQL

Subinterogări necorelate

O subinterogare necorelată (noncorrelated subselect) este o subinterogare în

care interogarea internă nu face nici o referire la interogarea externă care o conţine.

Aceasta înseamnă că poate fi rulată mai intâi interogarea internă, apoi setul de

rezultate obţinut poate fi folosit în interogarea externă.

Exemple:

• Afişaţi toate limbile în care nu există nici un film în inventarul magazinului

de produse video.

SELECT LIMBA_COD, LIMBA_NUME

FROM LIMBA

WHERE LIMBA_COD NOT IN

(SELECT DISTINCT LIMBA_COD

FROM FILM_LIMBA)

ORDER BY LIMBA_COD

LIMBA_COD LIMBA_NUME

Ja Japoneza

Ko Coreana

ni Olandeza

ru Rusa

zh Chineza

Interogarea internă returnează o listă cu codurile de limbă asociate

filmelor în tabelul FILM_LIMBA. Cuvântul cheie DISTINCT elimină rândurile

duplicate din setul de rezultate .

Interogarea internă rulată independent, pentru a vă ajuta să înţelegeţi

cum funcţionează:

SELECT DISTINCT LIMBA_COD FROM FILM_LIMBA;

LIMBA_COD

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

de (Germana)

en (Engleza)

es (Spaniola)

f r (Franceza)

• Proprietarul magazinului vrea să vadă efectul recentei creşteri de preţuri şi

are nevoie de o listă a tranzacţiilor (TRANZACTIE_ID) în care clientul a plătit mai

mult decât taxa medie (INCHIRIAT_TAXA) pentru un film. Iată cum arată

interogarea:

SELECT DISTINCT TRANZACTIE_ID

FROM FILM_INCHIRIAT

WHERE INCHIRIAT_TAXA>

(SELECT AVG(INCHIRIAT_TAXA) FROM FILM_INCHIRIAT)

Page 139: Curs Sinteza SQL

Interogarea internă calculează media taxelor de închiriere, iar interogarea

externă găseşte apoi toate rândurile din tabelul FILM_INCHIRIAT pentru care

valoarea INCHIRIAT_TAXA depăşeşte media.

Cuvântul cheie DISTINCT elimină tranzacţiile duplicate.

• Rezultatele interogării anterioare ar fi mai utile pentru proprietarul magazinului

dacă ar include şi data tranzacţiei. O modalitate de a realiza acest lucru este şi

adăugăm o uniune cu tabelul CLIENT_TRANZACTIE în interogarea externă. Totuşi,

deoarece tocmai aţi învăţat despre subinterogari, să facem acelaşi lucru folosind încă

o subinterogare. Iată cum arată interogarea:

SELECT TRANZACTIE_ID, TRANZACTIE_DATA AS TRANZ_DATA

FROM CLIENT_TRANZACTIE

WHERE TRANZACTIE_ID IN

(SELECT DISTINCT TRANZACTIE_ID FROM FILM_INCH,

WHERE INCH_TAXA > (SELECT AVG ( INCHIRIAT_TAXA)

FROM FILM_INCHIRIAT)

TRANZACTIE_ID TRANZ_DATA

9 03/01/2005

10 03/01/2005

Subinterogări corelate

O subinterogare corelată (correlated subselect) este o subinterogare în care

interogarea internă referă valorile furnizate de interogarea externă. Aceste

subinterogari sunt mult mai puţin eficiente decât subinterogările necorelate, deoarece

interogarea internă trebuie să fie apelată pentru fiecare rând găsit de interogarea

externă.

Exemplu:

Proprietarul magazinului vrea să transmită prin poştă un cupon valoric tuturor

clienţilor care au plătit mai mult de 15$ pentru o singură tranzacţie de închiriere.

SELECT DISTINCT CLIENT_CONT_ID

FROM CLIENT_TRANZACTIE A

WHERE 15 < (SELECT SUM (INCHIRIAT_TAXA)

FROM FILM_INCHIRIATB

WHERE A.TRANZACTIE _ID = B.TRANZACTIE_ID)

CLIENT_CONT_ID

2

7

9

Observaţi pseudonimele asociate numelor de tabele din interogările

internă şi externă, precurn şi folosirea acestora în clauza WHERE a interogării

interne. Acesta este elementul de identificare al unei subinterogări corelate.

Interogarea externă selectează o lista de valori CLIENT_CONT_ID distincte din

tabelul CLIENT_TRANZACTIE. Fiecare valoare găsită este transmisă interogării

interne, care este rulată pentru a calcula suma taxelor de închiriere din tranzacţia

respectivă. Dacă suma taxelor de închiriere este mai mare sau egală cu 15, atunci

Page 140: Curs Sinteza SQL

clauza WHERE din interogarea externă ia valoarea logică „adevărat", iar rândul

CLIENT_ID este adăugat în setul de rezultate.

Vizualizări în linie

Foarte puţine implementări, printre care Oracle, permit folosirea unei

subinterogări în clauza FROM a unei interogări, într-o construcţie numită vizualizare

în linie (inline view). Această construcţie permite care setul de rezultate al unei

interogări să fie tratat ca şi cum ar fi un tabel sau o vizualizare predefinită. Iată un

exemplu:

• Această interogare află numărul maxim de închirieri ale unui singur film;

SELECT MAX(INCHIRIAT_NUMAR) AS MAX_INCHIRIAT_NUMAR

FROM (SELECT FILM_ID, NUMAR(*) AS INCHIRIAT_NUMAR

FROM FILM_INCHIRIAT GROUP BY FILM_ID)

MAX_INCH_NUMAR

5

Interogarea internă calculează numărul de închirieri pentru fiecare valoare

FILM_ID. Interogarea externă selectează valoarea maximă INCHIRIAT_NUMAR

din interogarea internă, tratată ca şi cum ar fi o vizualizare predefinită. Nu există nici

o limită în privinţa modurilor de utilizare a vizualizărilor în linie - puteţi chiar să le

uniţi cu alte tabele sau vizualizări.

Întrebări şi probleme

Alegeţi răspunsurile corecte pentru fiecare din următoarele întrebări cu

răspunsuri multiple, şi reţineţi că întrebările pot avea mai multe răspunsuri corecte.

l. O subinterogare

a. Poate fi folosită pentru a selecta valorile care vor fi aplicate condiţiilor din

clauza WHERE

b. Poate fi corelată sau necorelată

c. Reprezintă o cale puternică de calculare a coloanelor

d. Trebuie să nu fie încadrate în paranteze

e. Permite selectarea flexibilă a rândurilor

2. O uniune (join) fără o clauză WHERE sau o clauză JOIN

a. Are ca rezultat un mesaj de eroare

b. Nu returnează nici un rând din setul de rezultate

c. Reprezintă o uniune externă (outer join)

d. Reprezintă o uniune internă (inner join)

e. Are ca rezultat un produs cartezian

3. O uniune externă (outer join)

a. Poate fi scrisă în Oracle SQL folosind un simbol (+) în clauza FROM

b. Poate fi scrisă în Microsoft SQL Server folosind operatorul = sau =* în

clauza WHERE

Page 141: Curs Sinteza SQL

c. Returnează toate rândurile doar din unul dintre tabele

d. Returnează toate rândurile din unul sau din ambele tabele

e. Poate fi catre stânga, către dreapta sau completă

4. O auto-uniune (selfjoin)

a. Nu poate avea niciodată ca rezultat un produs cartezian

b. Poate fi o uniune internă sau o uniune externă

c. Rezolvă relaţiile recursive

d. Poate folosi o subinterogare pentru a limita şi mai mult rândurile selectate

e. Implică două tabele diferite

5. O uniune (Join)

a. Combină coloanele din două sau mai multe tabele în rezultatele unei

singure interogări

b. Combină rânduri din interogari multiple într-un singur set de rezultate

c. Este realizată ori de câte ori în clauza FROM sunt specificate mai multe

tabele

d. Necesită folosirea unei clauze JOIN

e. Necesită o listă de tabele separate prin virgule în clauza FROM

6. O uniune de egalitate (equijoin)

a. Este cunoscută şi sub numele de uniune externă (outerjoin)

b. Este cunoscută şi sub numele de uniune internă (innerjoiti)

c. Este cunoscută şi sub numele de auto-uniune (selfjoin)

d. Realizează întotdeauna legarea rândurilor folosind o condiţie de egalitate

(=)

e. Realizează întotdeauna legarea rândurilor folosind o condiţie de inegalitate

(<>)

7. Calificatorii numelor de coloane:

a. Pot fi nume de tabele

b. Pot fi numere care indică poziţia relativă a tabelelor dîn lista FORM

c. Pot fi pseudonime pentru numele de coloane , definite în clauza FORM

d. Pot fi pseudonime pentru numele

8.O uniune încruşişată este:

a. O uniune Naturală

b. N produs cartezian

c. O uniune externă

d. O uniune Internă

9. O clauză JOIN folosind cuvântul cheie USING

a. Nu poate fi folosită atunci când coloanele prin care se face legarea

tabelelor au nume diferite

b. Nu poate fi folosită atunci când coloanele prin care se face legarea

tabelelor au aceleaşi nume

c. Defineşte o uniune internă

d. Defineşte o uniune externă

e. Defineşte o auto-uniune

10. O subinterogare corelată

Page 142: Curs Sinteza SQL

a. Rulează mai eficient decât o subinterogare necorelată

b. Rulează mai puin eficient decât o subinterogare necorelată

c. Are o interogare internă care refera coloane din interogarea externă

d. Are o interogare externă care refera coloane din interogarea internă

e. Are o interogare internă care nu face nici o referire la coloanele din

interogarea externă

Scrieţi instrucţiunile SQL pentru următoarele probleme:

1. Afişaţi numele şi identificatorul de client ale tuturor persoanelor decedate

(valoarea DATA_MORTII nu este nulă) care încă au conturi de client.

2. Afişaţi numele angajatilor care au conturi de clienţi. Folosiţi uniuni pentru

a stabili ce clienţi sunt angajaţi şi ce angajaţi au conturi de clienţi.

3. Rescrieţi interogarea anterioară pentru a folosi subinterogări în loc de

uniuni.

4. Afişaţi numele de familie al fiecarui angajat, împreună cu numele de

familie al şefu1ui lor.

5. Afişaţi numărul de închirieri pentru fiecare format (DVD şi VHS).

6. Afişaţi numărul de identificare (FILM_ID) şi data la care trebuie returnate

(DATA_RETURNARII) pentru toate filmele închiriate şi încă nereturnate

(coloană RETURNAT_DATA din tabelul FILM_INCH conţine valori

nule), dar care nu au fost cumpărate (coloană DATA_VANZARII din

tabelul FILM_COPY conţine valori nule).

7. Afişaţi numarul de identificare şi titlul filmelor care nu au fost închiriate

niciodată.

8. Folosind subinterogări pentru a filtra rândurile. Afişaţi titlul filmelor

pentru care în inventar există o copie VHS (MEDIA_FORMAT = ‗V‘, iar

DATA_VANZARII are valoarea NULL) dar pentru care nu există copii

DVD (MEDIA_FORMAT = ‚D‘ ).

9. Rescrieţi interogarea anterioară folosind o uniune în local unei

subinterogări pentru a găsi filmele în format VHS.

10. Afişaţi toate filmele pentru care în inventar există mai multe copii în

acelaşi format.

Scrierea interogărilor avansate

În această parte se prezintă câteva subiecte avansate, şi anume:

Funcţii SQL avansate, inclusiv funcţii pentru caractere, matematice şi pentru

dată sau oră

O descriere a modului în care puteti beneficia de avantajele vizualizărilor

Informaţii despre expresia SQL CASE şi despre utilizarea acesteia pentru

construirea instrucţiunilor care includ porţiuni executate numai în anumite condiţii

predefinite.

Secţiunile următoare descriu funcţii care nu au fost prezentate dar

foarte utile. Pe lângă funcţiile pentru caractere şi matematice, sunt incluse câteva

funcţii pentru date şi ore. Reţineţi că toate funcţiile SQL au o trăsătură comună, în

sensul că returnează o singură valoare, aşa că sunt utile în diferite locuri din

instrucţiunile SQL, inclusiv în lista de coloane a comenzii SELECT şi în clauza

Page 143: Curs Sinteza SQL

WHERE. Vă reamintim că există un număr mare de funcţii specifice fiecărei

implementări, furnizate de diferiţi producători SGBD.

Funcţii pentru caractere

Funcţiile pentru caractere operează asupra datelor de tip text. Această secţiune

prezintă câteva funcţii frecvent folosite, pe lângă cele discutate în lecţia 3.

REPLACE

Funcţia REPLACE caută un şir de caractere şi înlocuieşte caracterele

găsite cu caracterele din şirul de înlocuire.

Sintaxa generală a funcţiei:

REPLACE (şir_de_caractere, şir_căutat, şir_de_înlocuire}

şir_de_caractere reprezintă şirul de caractere în care se face căutare şi, în

cele mai multe cazuri, este numele unei coloane dintr-un tabel, dar poate fi

orice expresie care are ca rezultat un şir de caractere.

şir_cautat este un şir format dintr-un caracter sau mai multe, care trebuie

căutate în sir_de_caractere.

şir_de_intocuire este şirul de caractere cu care se înlocuieşte orice apariţie

a şirului_cautat în şir_de_caractere.

Exemplu care înlocuieşte toate liniuţele de despărţire din numărul de telefon al

unei persoane cu puncte (sunt prezentate numai primele două rânduri din setul de

rezultate)

SELECT PERSOANA_TELEFON,

REPLACE(PERSOANA_TELEFON, '-', '.') AS DISPLAY_TELEFON

FROM PERSOANA;

PERSOANA_TE

LEFON

DISPLAY_TE

LEFON

230—229—8976 230.229.8976

401—617—7297 401.617.7297

LTRIM

Funcţia LTRIM elimină spatiile de la începutul unui şir de caractere. Sunt

eliminate numai spaţiile de la începutul şirului, cele din mijlocul şi de la sfârşitul

şirului sunt lăsate ca atare.

LTRIM (‗ String cu spaţii ‗)

Returnează: ‗String cu spaţii ‘

RTRIM

Page 144: Curs Sinteza SQL

Funcţia RTRIM este similar cu LTRIM, dar elimin spatiile de la sfârsitul unui

sir de caractere. Daca trebuie sa eliminati atât spatiile de la inceputul sirului, cat şi pe

cele de la sfarsit, puteti imbrica funcţiile LTRIM şi RTRIM, ca în urmatorul exemplu:

RTRIM(LTRIM (‗ String cu spatii ‗)

Returnează: ‗String cu spatii‘

NOTA: Oracle pune la dispoziţie o funcţie mai convenabilă, numită TRIM,

care elimină atât spaţiile de la începutul şirului, cât şi pe cele de la sfârşit. .

Funcţii pentru valori nule (NVL, ISNULL, IFNULL)

Oracle, Microsoft SQL Server şi My SQL pun la dispoziţie o funcţie care

înlocuieşte valorile nule cu o valoare specificată. Din nefericire, fiecare implementare

foloseste propriul nume pentru aceast funcţie: NVL în Oracle, ISNULL în SQL

Server şi IFNULL în MySQL.

Exemplele următoare selectează din tabelul FILM_INCHIRIAT, coloana

TAXA_INTARZIERE_SAU_PIERDERE(sau redunumită TAXA_PENALIZARE),

înlocuind valorile nule cu zero. A fost selectată tranzacţia 9 deoarece conţine două

filme, dintre care unul are o valoare nulă în coloana

TAXA_INTARZIERE_SAU_PIERDERE (un exemplu bun, care ilustreaza faptul că

valorile nule sunt transformate, în timp ce valorile nenule sunt lăsate ca atare.)

Oracle:

SELECT NVL(TAXA_INTARZIERE_SAU_PIERDERE, 0) AS

TAXA_INTARZIERE_SAU_PIERDERE

FROM FILM_INCHIRIAT WHERE TRANSACTIE_ID=9;

TAXA_INTARZIERE_SAU_PIE

RDERE

0

29.98

2 rows selected.

Microsoft SQL Server:

SELECT ISNULL(TAXA_INTARZIERE_SAU_PIERDERE, 0) AS

TAXA_INTARZIERE_SAU_PIERDERE

FROM FILM_INCHIRIAT WHERE TRANSACTIE_ID=9 ;

TAXA_INTARZIERE_SAU_PIE

RDERE

29.98

.00

(2 rows affected)

MySQL:

SELECT IFNULL(TAXA_INTARZIERE_SAU_PIERDERE, 0) AS

TAXA_INTARZIERE_SAU_PIERDERE

FROM FILM_INCHIRIAT WHERE TRANZACTIE_ID=9;

Page 145: Curs Sinteza SQL

TAXA_INTARZIERE_SAU_PIE

RDERE

29.98

0.00

2 rows în set (0.16 sec)

Se observă diferenţa de formatare a rezultatelor pentru clientul MySQL

în linia de comandă.

ASCII

Funcţia ASCII returnează valoarea din setul de caractere ASCII (un numar

între 0 şi 255) pentru un şir format dintr-un singur caracter.

De exemplu:

ASCII(‗ ‗) eturnează valoarea 32(codul ASCII pentru spaţiu)

ASCII(‗A‘) eturnează valoarea 65(codul ASCII pentru caracterul A)

ASCII(‗a ‗) eturnează valoarea 97(codul ASCII pentru caracterul a)

ASCII(‗1‗) eturnează valoarea 49(codul ASCII pentru caracterul 1)

CHAR (CHR)

Funcţia CHAR (numită CHR în Oracle şi DB2) returnează caracterul

corespunzator unei valori ASCII (un numar între 0 şi 255). Această funcţie este utilă

în special pentru concatenarea caracterelor care nu pot fi afişate sau sunt greu de

manipulat în SQL.

De exemplu:

CHAR(44) returnează o virgulă

CHAR(50) returneaza 2

Se poate folosi funcţiile CHAR şi ASCII consultând tabele cu caractere

şi codurile ASCII corespunzătoare uşor de gasit în Internet, de exemplu:

Amintim că operatorul de concatenare nu este ace1aşi pentru toate

implementările SGBD(‗+‗ pentru Microsoft SQL Server şi ‗||‘ pentru majoritatea

celorlalte sisteme).

Exemple cu funcţiile ASCII şi CHAR:

Să se găsească toate titlurile de filme care conţin un caracter Tab:

Microsoft SQL Server:

SELECT FILM_ID FROM FILM

WHERE FILM_TITLU LIKE ‗%‗+CHAR(9)+‘%‘;

FILM_ID

Valoare

ASCII

Caracter

9 Tab

10 Linie noua

13 Retur de car

(CR)

39 Apostrof

Page 146: Curs Sinteza SQL

(0 rows affected)

Oracle:

SELECT FILM_ID FROM FILM

WHERE FILM_TITLU LIKE ‗%‗ || CHR(9) || ‗%‗ ;

no rows selected

Să se găsească toate titlurile de filme care conţin un caracter apostrof:

SELECT FILM_ID FROM FILM

WHERE FILM_TITLU LIKE ‗%‗+CHAR(39)+‘%‘;

FILM_ID are valoarea 3 (Something's Gotta Give).

Funcţii matematice

Funcţiile matematice returnează rezultatul unei operaţii matematice şi, de

obicei, acceptă ca parametru de intrare o expresie numerică, care poate fi o valoare

literală, o valoare numerică dintr-o coloană a unui tabel sau orice expresie (inclusiv

rezultatul unei alte funcţii) care produce o valoarea numerică.

SIGN

Funcţia SIGN primeşte ca argument o expresie numerică şi returnează una

dintre următoarele valori, în funcţie de semnul numărului de intrare:

Valoare

returnata

Semnificatie

-1 Numărul de intrare este

negativ

0 Numărul de intrare este

zero

1 Numărul de intrare este

pozitiv

Null Valoarea de intrare este

nulă

Exemplu:

SELECT TAXA_PENALIZARE,

SIGN(TAXA_PENALIZARE) AS TAXA_SIGN

FROM FILM_INCHIRIERE

WHERE TAXA_PENALIZARE IS NOT NULL;

TAXA_PENALIZARE TAXA_SIGN

29.99 1

4 1

4 1

29.98 1

Page 147: Curs Sinteza SQL

SQRT

Funcţia SQRT primeşte ca argument o expresie numerică şi returnează

rădăcina pătrată a acesteia.

Sintaxa generală a funcţiei este: SQRT (expresie numerică)

Vom extrage radacina patrată din valorile TAXA_PENALIZARE nenule pe

care tocmai le-am vazut:

SELECT TAXA_INTARZIERE_SAU_PIERDERE,

SQRT (TAXA_PENALIZARE) AS TAXA_SQRT

FROM FILM_INCH

WHERE TAXA_INTARZIERE_SAU_PIERDERE IS NOT NULL;

TAXA_PENA

LIZARE

TAXA

_SQRT

29.99 5.4763

1263

4 2

4 2

29.98

5.47539953

CEILING (CEIL)

Funcţia CEILING returnează cel mai mic întreg mai mare sau egal cu valoarea

expresiei numerice furnizată ca parametru de intrare, adică rotunjeşte numărul prin

adăugire până la următorul număr întreg. Există câteva probleme interesante de

compatibilitate legate de denumire între implementarile SQL: Microsoft SQL Server

foloseşte numele CEILING, Oracle foloseşte numele CEIL, în timp ce DB2 şi

MySQL permite folosirea ambelor nume (CEIL şi CEILING).

Ca exemplu, să aplicăm funcţia CEILING asupra valorilor din coloana

TAXA_PENALIZARE :

SELECT TAXA_PENALIZARE,

CEILING (PENALIZARE) AS TAXA_CEILING

FROM FILM_INCHIRIERE

WHERE TAXA_PENALIZARE IS NOT NULL;

TAXA_INTARZIERE_SAU_PIE

RDERE

TAXA_C

EILING

4.00 4

4.00 4

29.99 30

29.98 30

FLOOR

Funcţia FLOOR este inversa logică a funcţiei CEILING — returnează

cel mai mare întreg mai mic sau egal cu valoarea expresiei numerice furnizată ca

Page 148: Curs Sinteza SQL

parametru de intrare, adică rotunjeşte numărul prin scădere până la următorul număr

întreg(parte întreagă).

Exemplu, în care se aplică funcţia FLOOR asupra valorilor din coloana

TAXA_PENALIZARE:

SELECT TAXA_PENALIZARE,

FLOOR(TAXA_INTARZIERE_SAU_PIERDERE) AS TAXA_FLOOR

FROM FILM_INCH WHERE TAXA_INTARZIERE_SAU_PIERDERE IS NOT

NULL;

TAXA_PENALIZARE TAXA_FLOOR

Funcţii pentru dată şi oră

Există foarte puţină consecvenţă în privinţa funcţiilor pentru dată şi oră

între diferiţii producători de sisteme SGBD, motivul este faptul ca producătorii au

dezvoltat propriile tipuri de date temporale înainte de stabilirea standardelor. Din

cauza acestei diversităţi, funcţiile pentru dată şi oră sunt prezentate pe scurt pentru

Microsoft SQL Server şî Oracle. Termenii scrişi cu caractere italice sunt definiţi în

notele care urmează după fiecare tabel, în toată această secţiune, termenul

data_si__ora înseamnă un şir de caractere care conţine informaţii despre dată şi oră,

într-un format acceptabil pentru sistemul SGBD –ul respectiv.

Funcţii pentru dată şi oră în Microsoft SQL Server

NOTA: Valoarea parte_de_dată este un parametru care specifică o parte a datei,

cum ar fi anul, luna, ziua, ora,minutul, secunda şi milisecunda.

4.00 4

4.00 4

29.99 29

29.98 29

Page 149: Curs Sinteza SQL

Funcţii pentru data şi orã în Oracle

Oracle are mai multe de 24 de funcţii pentru data şi ora. Retineţi că Oracle

numeşte acest tip de date DATE şi toate datele au o componentă pentru orã, care are

valoarea zero (reprezentând miezul noptii) atunci când nu este folosită. Funcţiile pe

care este cel mai probabil să le folosiţi sunt prezentate în tabelul următor:

NOTA:

• Cuvântul cheie pentru câmpul data_şi__ora este un cuvânt cheie care

specifică unul dintre câmpurile conţinute de o dată Oracle, respectiv YEAR,

MONTH, DAY, HOUR, MINUTE şi SECOND.

• Şir_pentru_formatare este un şir de simboluri care specifică formatul

folosit pentru dată atunci când aceasta este convertită în sau dintr-un şir de caractere.

Există peste 40 de simboluri diferite care pot fi folosite în şirurile de formatare (puteţi

găsi lista completă în documentaţia Oracle). De exemplu, şirul de formatare

'MM/DD/YYYY HH:MI' are ca rezultat o dată, ca şir de caractere, de forma

'12/01/2004 11:58‘, iar şirul de formatare 'DD-MON-RR' (formatul Oracle prestabilit)

are ca rezultat o dată de forma '01-Dec-04‘.

• Funcţia TO_CHAR poate fi folosită şi pentru transformarea valorilor

numerice în şiruri de caractere.

• Funcţia TRUNC poate fi folosita şi pentru trunchierea valorilor numerice,

având ca efect ştergerea cifrelor din dreapta punctului zecimal.

Funcţie Scop Parametri de intrare

DATEADD Returnează o nouă valoare data_si_ora, adăugând un interval la valoarea parte _de_data furnizata ca

parametru

parte_de_data, interval, data_si_ora

DATEDIFF Returnează numărul de intervale data_şi_ora trecute între două date

parte _de_data, data de început, dată de sfârşit

DATENAME Returnează un nume sub formă de text, reprezentând partea _de_dată selectată pentru valoarea data_si_ora furnizată ca intrare

porte _de_dată, data_si_ora

DATEPART

Returnează o valoare intreaga, reprezentand

partea_de_data selectata pentru valoarea data_si_ora furnizata ca intrare

parte_de_data, data_si_ora

DAY Returnează o valoare intreaga, reprezentand ziua conţinuta în valoarea data_si _ora furnizata ca intrare.

data_si_ora

GETDATE Returnează valoarea curenta data_si_ora furnizata de sistem

Nu are

GETUTCDATE Returnează valoarea curenta data_si_or UTC (Universal Coordinated Time)

Nu are

MONTH Returnează o valoare intreaga, reprezentand luna conţinuta în valoarea data_si_ora furnizata ca intrare

data_si_ora

Page 150: Curs Sinteza SQL

Folosirea avantajelor oferite de vizualizari

Amintim că o vizualizare (view) este o interogare stocată în baza de

date, care pune la dispoziţia utilizatorului bazei de date un subset particularizat de

date din unul sau mai multe tabele ale bazei de date. Microsoft Access foloseşte

termenul query (interogare) în loc de vizualizare. Frumuseţea vizualizărilor constă în

faptul că, după ce sunt create, pot fi interogate ca şi cum ar fi tabele reale. De fapt, nu

este nevoie ca utilizatorul să ştie dacă foloseşte o vizualizare sau un tabel real. Pot

exista unele restricţii la manipularea datelor (la inserare, actualizare şi ştergere) dar

interogările funcţionează pentru vizualizări la fel ca şi pentru tabele.

Vizualizările oferă şi alte avantaje:

Maschează coloanele pe care utilizatorul nu este nevoie sau nu trebuie să

le vadă

Maschează rândurile pe care utilizatorul nu este nevoie sau nu trebuie să le

vadă

Maschează operatiile complexe, precum uniunile

Cresc performanţele interogărilor

Funcţie Scop Parametri de intrare

ADD_MONTHS Adauga numarul de luni specificat la data

furnizata ca parametru

Data, numarul de luni (o

valoare pozitiva sau

negativa)

CURRENT_DATE Returnează data curenta în zona orara stabilita

pentru sesiunea bazei de date Nu are

EXTRACT Extrage campul data_si_ora specificat din data

furnizata ca intrare

Cuvant cheie pentru

data_si_ora, data

LAST_DAY Returnează data furnizata, cu ziua inlocuita cu

ultima zi a lunii respective data

MONTHS_BETWEEN

Returnează numarul de luni (inclusiv partea

fractionara) intre doua date furnizate ca intrare;

rezultatul este negativ daca a doua data este

inaintea primei

Prima data, a doua data

SYSDATE Returnează valoarea curenta data_si_ora furnizata

de sistem Nu are

TO_CHAR

Atunci cand este folosita pentru o data, funcţia

returnează un sir de caractere, în formatul

specificat de sirul_pentru_formatare

Data, sir_pentru_formatare

TO_DATE

Transforma sirul de caractere furnizat ca intrare

intr-o data formatata intern de Oracle, folosind

sirul_pentru_formatare ca tipar pentru a interpreta

conţinutul sirului de caractere

Data, sir_pentru_formatare

TRUNC

Trunchiaza o data la unitatea de timp specificata

de cuvantul cheie data_si_ora. Daca acest

parametru este omis, data este trunchiata la ziua curenta.

Data, cuvant cheie pentru

data_si_ora

Page 151: Curs Sinteza SQL

Exemplele din această secţiune prezintă vizualizări care vă oferă avantajele

menţionate mai sus. Vă amintiţi din Lecţia 2, că sintaxa generală pentru crearea unei

vizualizări este :

CREATE [OR REPLACE] VIEW nume_vizualizare AS

interogare_sql;

Exemple:

• Reguli evidente de confidenţialitate obligă administratorul magazinului să

ţină secrete datele de identificare ale angajaţilor (numerele de asigurări sociale) şi

salariile. Totuşi, există un număr de aplicaţii care necesită furnizarea unor informaţii

despre angajaţi, cum ar fi numele sau numele şefului lor (dacă există), în asemenea

situaţii, aveţi nevoie de o vizualizare care să poată fi folosită în siguranţă de un

dezvoltator, fără pericolul de a dezvălui în mod accidental informaţii confidenţiale.

Interogarea din vizualizare trebuie să realizeze o uniune (join) cu tabelul PERSOANA

pentru a afla numele angajatului şi (folosind o uniune externă) numele şefului

acestuia. Instrucţiunea SQL folosită pentru crearea vizualizării:

CREATE VIEW ANGAJAT_LISTA AS

SELECT A.PERSOANA_ID AS ID,

B.PERSOANA_PRENUME AS PRENUME,

B.PERSOANA_INITIALA AS INITIALA ,

B.PERSOANA_NUME_FAMILIE AS NUME,

C.PERSOANA_PRENUME AS MANAGER_PRENUME,

C.PERSOANA_NUME_FAMILIE AS MANAGER_NUME

FROM ANGAJAT A JOIN PERSOANA B

ON A.PERSOANA_ID = B.PERSOANA_ID

LEFT OUTER JOIN PERSOANA C

ON A.SUPERVISOR_PERSOANA_ID = C.PERSOANA_ID

View created.

După crearea vizualizării, puteţi să o interogaţi ca şi cum ar fi un tabel.

O interogare simplă făcută în vizualizarea pe care tocmai am creat-o:

SELECT NUME, MANAGER_NUME

FROM ANGAJAT_LISTA

ORDER BY NUME;

NUME MANAGER_NU

ME

Alexandr

u

Popescu Alexandru

Ionescu Alexandru

• Pentru crearea unui catalog cu filmele disponibile, aveţi nevoie de o listă cu

descrierile categoriilor MPAA şi cu descrierile genurilor.

Instrucţiunea SQL folosită pentru crearea vizualizării:

CREATE VIEW FILM_LISTA AS

SELECT A.FILM_ID, B.FILM_GEN_DESCRIERE AS GEN,

C.MPAA_RATING_COD AS RATING,

C.MPAA_RATING_DESCRIERE AS RATING_DESC,

Page 152: Curs Sinteza SQL

A.FILM_TITLU, A.RETAIL_PRET_VHS,

A.RETAIL_PRET_DVD, A.ANUL_PRODUCERII

FROM FILM A JOIN FILM_GEN B ON

A.FILM_GEN_COD = B.FILM_GEN_COD

JOIN MPAA_RATING C ON

A.MPAA_RATING_COD = C.MPAA_RATING_COD

Exemplu de interogare simplă care foloseşte vizualizarea în locul tabelelor de

bază:

SELECT GEN, RATING, FILM_TITLU

FROM FILM_LISTA

ORDER BY GEN, RATING, FILM_TITLU;

GEN RATING FILM_TITLU

Actiune şi Aventura PG-13 Master and Commander: The Far

Actiune şi Aventura PG-13 Pirates of the Caribbean: The

Actiune şi Aventura PG-13 The Day After Tomorrow

Actiune şi Aventura PG-13 The Italian Job

Actiune şi Aventura R Kill Bill: Vol. 1

Actiune şi Aventura R Man on Fire

Actiune şi Aventura R The Last Samurai

Comedie PG-13 50 First Dates

Comedie PG-13 Matchstick Men

Comedie PG-13 Something's Gotta Give

Comedie PG-13 The School of Rock

Drama PG-13 Big Fish

Drama R Cold Mountain

Drama R Lot în Translation

Drama R Monster

Drama R Mystic River

Drama R Road to Perdiction

Strain R Das Boot

Romantic PG-13 13 Going 30

Romantic PG-13 Two weeks notice

• Magazinul de produse video ar vrea să instaleze un chioşc informatizat în

secţiunea de filme pentru copii, astfel încât tinerii să poată căuta filmele online.

Dorim ca numai filmele din categoriile MPAA G, PG şi PG-13 să fie disponibile în

acest chioşc. În loc să se repete uniunea din vizualizarea FILM_LISTA dacă MPAA

ar modifica sistemul de clasificare, se poate folosi vizualizarea FILM_LISTA pentru

a crea o nouă vizualizare (adică se poate folosi o vizualizare pentru a crea o altă

vizualizare!

Exemplu:

CREATE VIEW COPII_FILM_LISTA AS

SELECT * FROM FILM__LISTA

WHERE RATING IN ('G', 'PG', 'PG-13')

Page 153: Curs Sinteza SQL

Rezultatele obţinute, folosind aceeaşi interogare ca şi pentru vizualizarea

FILM_LISTA:

SELECT GEN, RATING, FILM_TITLU

FROM COPII_FILM_LISTA

ORDER BY GEN, RATING, FILM _TITLU;

GEN RATING FILM TITLU

Actiune şi Aventura PG-13 Master and Commander: The Far

Actiune şi Aventura PG-13 Pirates of the Caribbean: The

Actiune şi Aventura PG-13 The Day After Tomorrow

Actiune şi Aventura PG-13 The Italian Job

Comedie PG-13 50 First Dates

Comedie PG-13 Matchstick Men

Comedie PG-13 Something's Gotta Give

Comedie PG-13 The School of Rock

Drama PG-13 Big Fish

Romantic PG-13 13 Going on 30

Romantic PG-13 Two Weeks Notice

Vizualizarea COPII_FILM_LISTA se bazează pe vizualizarea FILM_LISTA şi

poate să devină invalidă sau să nu mai funcţioneze corect dacă vizualizarea

FILM_LISTA este modificată. Vizualizările sunt instrumente puternice, care nu pot fi

ignorate.

Expresia CASE

Expresia CASE este o adăugire recentă, dar foarte importantă, la standardul

SQL. Pentru prima dată, părţi ale instrucţiunilor SQL pot fi executate condiţional. De

exemplu, o coloană din rezultatele interogării poate fi formatată în funcţie de valorile

conţinute pe o altă coloana.

Expresia CASE admite două forme generale:

Expresia CASE simplă

Sintaxa generală pentru forma simplă a expresiei CASE:

CASE expresie_ de_ intrare

WHEN expresie_de_comparare THEN expresie__rezultat [WHEN expresie

de_comparare THEN expresie_rezultat.. ] ELSE expresie_rezultat

END

notă:

Fiecare condiţie WHEN este evaluată sub forma expresie_de_intrare =

expresie_comparare şi, dacă rezultatul are valoarea TRUE logic, este returnată

valoarea expresie_rezultata şi nici o altă condiţie WHEN nu mai este evaluată.

Dacă nici una dintre condiţiile WHEN nu este evaluată ca adevărată şi exista o

condiţie ELSE, este returnată valoarea expresie_rezultat asociată condiţiei ELSE.

Page 154: Curs Sinteza SQL

Dacă nici una dintre condiţiile WHEN nu este evaluată ca adevărată şi nu

există o condiţie ELSE, este returnată o valoare nula.

De exemplu, se poate folosi expresia CASE pentru a transforma

valoarea MPAA_RATING_COD într-un mesaj simplu, care poate fi afişat la

terminalul de vânzare, pentru a aminti personalului magazinului să verifice vârsta

clienţilor în cazul filmelor cu o categorie MPAA mai mare de PG-13. Remarcaţi

plasarea cuvântului cheie AS imediat după cuvântul cheie END, pentru a asocia un

nume coloanei generate în setul de rezultate. Iată exemplul:

SELECT FILM_ID, MPAA_RATING_COD AS RATING,

CASE MPAA_RATING_COD

WHEN 'G' THEN ‚Toate varstele'

WHEN 'PG' THEN ‚Acordul parintilor‘

WHEN 'PG-13' THEN 'Peste 13 ani'

ELSE 'Peste 17 ani‘ END AS RATING_DESC

FROM FILM

ORDER BY FILM _ID;

FILM ID RATING RATING_DESC

1 R Peste 17 ani

2 R Peste 17 ani

3 PG-13 Peste 13 ani

4 PG-13 Peste 13 ani

5 R Peste 17 ani

6 PG-13 Peste 13 ani

7 PG-13 Peste 13 ani

8 R Peste 17 ani

9 PG-13 Peste 13 ani

10 R Peste 17 ani

Expresia CASE cu căutare

Expresie CASE cu căutare (searched CASE) permite folosirea unor condiţii de

comparare mai flexibile, deoarece fiecare condiţie este complet specificată, incluzând

şi operatorul de comparare. Sintaxa generală a expresiei:

CASE

WHEN condiţie THEN expresie_rezultat

[WHEN condiţie THEN expresie_rezultat. . . ]

ELSE expresie_rezultat

END

notă:

Fiecare condiţie poate fi orice expresie SQL care este evaluată ca adevărata

sau falsă.

Page 155: Curs Sinteza SQL

Condiţiile WHEN sunt evaluate secvenţial şi, dacă una este evaluată ca

adevărata, este returnata valoarea expresie_rezultat asociată şi nici o altă condiţie

WHEN nu mai este evaluata.

Dacă nici una dintre condiţiile WHEN nu este evaluată ca adevărată şi există o

condiţie ELSE, este returnată valoarea expresie_rezultat asociată condiţiei ELSE.

Dacă nici una dintre condiţiile WHEN nu este evaluata ca adevărată şi nu

exişti o condiţie ELSE, este returnată o valoare nulă.

De exemplu, considerăm o interogare care clasifică filmele în format VHS, în

funcţie de pret:

SELECT FILM_ID, RETAIL_PRET_VHS,

CASE

WHEN RETAIL_PRET__VHS IS NULL THEN ‚Not Available‘ ;

WHEN RETAIL_PRET_VHS < 10 THEN ‘Ieftin‘

WHEN RETAIL_PRET__VHS < 20 THEN ‘Convenabil‘

WHEN RETAIL PRET VHS < 40 THEN ‘Mediu‘

ELSE 'Scump'

END AS PRET_CATEGORIE

FROM FILM

ORDER BY FILM_ID;

FIL

M_ID

RETAIL_PRET_

VHS

PRET_CATEGOR

IE

1 58.97 Scump

2 15.95 Convenabil

3 14.95 Convenabil

4 11.95 Convenabil

5 24.99 Mediu

6 24.99 Mediu

7 14.95 Convenabil

8 50.99 Scump

9 12.98 Convenabil

10 49.99 Scump

Întrebări şi Probleme

Alegeţi răspunsurile corecte pentru fiecare din următoarele întrebări cu

răspunsuri multiple. Reţineţi că întrebările pot avea mai multe răspunsuri corecte.

1. Funcţiile SQL

a. Returnează un set de valori

b. Returnează o singură valoare

c. Pot fi folosite în clauza WHERE a unei instrucţiuni SQL

d. Pot fi folosite ca pseudonime pentru numele tabelelor intr-o instr. SQL

e. Pot fi folosite în lista de coloane a unei instrucţiuni SQL

2. Funcţia REPLACE

Page 156: Curs Sinteza SQL

a. Înlocuieşte un nume de tabel cu un nume de vizualizare

b. Înlocuieşte numele unei coloane cu pseudonimul coloanei

c. Înlocuieşte un şir de caractere dintr-o coloană cu un alt şir de caractere

d. Înlocuieşte toate valorile dintr-o coloană cu un alt set de valori

e. Înlocuieşte toate rândurile dintr-o vizualizare cu rânduri conţinând date

dintr-un alt tabel

3. Funcţia LTRIM

a. Elimină spaţiile de la sfârşitul şirurilor de caractere

b. Elimină spaţiile de la începutul şirurilor de caractere

c. Poate fi imbricată cu alte funcţii

d. înlocuieşte valorile nule cu alte valori în şirurile de caractere

e. Elimină spaţiile de la începutul şi de la sfârşitul şirurilor de caractere

4. Funcţia CHAR

a. Este numită CHR în unele implementări SQL

b. Este identică cu funcţia ASCII în unele implementări SQL

c. Returnează valoarea corespunzătoare unui caracter din setul de caractere

ASCII

d. Returnează caracterul corespunzător unei valori

e. Transformă o valoare numerică într-un şir de caractere

5. Funcţia SIGN

a. Returnează -l daca parametrul furnizat are valoare negativa

b. Returnează 0 dacă parametrul furnizat are valoarea zero

c. Returnează +1 dacă parametrul furnizat are o valoare pozitivă

d. Returnează 0 dacă parametrul furnizat are valoarea NULL

e. Returnează o valoare nulă dacă parametrul furnizat nu este un număr

6. Funcţia CEILING

a. Rotunjeşte un număr prin adăugire până la primul număr întreg

b. Rotunjeşte un număr prin scădere până la primul număr întreg

c. Returnează întotdeauna un număr întreg

d. Returnează un număr întreg sau o valoare nulă

e. Este numită CEIL în unele implementări SQL

7. Funcţia FLOOR

a. Rotunjeşte un număr prin adăugire până la primul număr întreg

b. Rotunjeşte un număr prin scădere până la primul număr întreg

c. Returnează întotdeauna un număr întreg

d. Returnează un număr întreg sau o valoare nulă

e. Este numită FLR în unele implementări SQL

8. Expresiile CASE

a. Permit executarea condiţională a clauzelor dintr-o instrucţiune SQL

b. Există sub două forme, respectiv statice şi dinamice

c. Exista sub două forme, respectiv cu căutare şi fara cautare

d. Există sub două forme, respectiv simple şi cu cautare

e. Există sub două forme, respectiv standard şi cu cautare

Scrieţi instrucţiunile SQL pentru următoarele probleme:

1. Afişaţi valorile MPAA_RATING_COD din tabelul MPAA_RATING, cu

liniuţele de despărţire înlocuite cu spaţii.

Page 157: Curs Sinteza SQL

2. Folosind funcţia CHAR (numită CHR în Oracle), afişaţi valorile FILM_ID

şi FILM_TITLU pentru toate filmele care conţin apostrofuri (caracterul

ASCII 39) în titlu.

3. Aflaţi valoarea ASCII a semnului de exclamare (!).

4. Aflaţi preţul mediu al filmelor în format DVD (coloana RETAIL_PRET

_DVD din tabelul FILM), cu media calculată rotunjită prin adăugire la cea

mai apropiată sumă fără zecimale.

5. Aflaţi preţul mediu al filmelor în format VHS (coloana

RETAIL_PRET_VHS din tabelul FILM), cu media calculată rotunjită prin

scădere la cea mai apropiată sumă fără zecimale.

6. Pentru o bază de date Oracle, generaţi comenzile SQL pentru eliminarea

tuturor restricţiilor referenţiale aflate în proprietatea utilizatorului curent.

Vizualizarea Oracle de tip catalog se numeşte USER_CONSTRAINTS, iar

restricţiile referenţiale au valoarea 'R' în coloana CONSTRAINT_TYPE.

Numele tabelului pe care se bazează restricţia se află în coloana

TABLE_NAME a vizualizării. Nu uitaţi că trebuie să folosiţi comanda

ALTER TABLE pentru eliminarea unei restricţii.

7. Pentru o bază de date Microsoft SQL Server, afişaţi toate restricţiile de tip

cheie externă. Folosiţi tabelul de sistem SYSOBJECTS, în care NAME este

numele restricţiei, iar coloana XTYPE are valoarea 'F' pentru restricţiile de

tip cheie externă.

8. Scrieţi o instrucţiune SQL care afişează fiecare cont de client

(CLIENT_CONT_ID) cu un şir de caractere bazat pe valoarea coloanei

COPIL_INCH_ALLOWED_INDIC, care să conţină textul „Poate fi

inchiriat de copii" dacă valoarea coloanei este 'Y' şi textul „Nu poate fi

inchiriat de copii" dacă valoarea este 'N'. Sugestie: Cel mai bine

funcţionează în acest caz o expresie CASE simplă.

9. Scrieţi o instrucţiune SQL care afişează fiecare film (FILM_ID) şi o valoare

pentru deceniu, în funcţie de valoarea coloanei ANUL_PRODUCERII sau

necunoscut), în acest caz v-ar fi de folos o expresie CASE cu cautare.

10. Scrieţi o instrucţiune SQL care afişează fiecare inchiriere a unui film

(tabelul FILM_INCH) cu valoarea TAXA_PENALIZAREclasificaţa astfel:

None (valoare nulă sau zero), Minor (valoare < 10) sau Major (valoare > 10) .

Lecţia 5. Limbajul de manipulare a datelor – DML

În această lecţie se prezintă instrucţiunile DML (Data Manipulation

Language), o parte a limbajului SQL folosită pentru intreţinerea datelor stocate în

tabele relaţionale ale bazei de date.

Limbajul DML este format din trei comenzi SQL:

INSERT Adaugă noi rânduri într-un table al bazei de date.

UPDATE Actualizeaza rândurile existente Într-un table al bazei de date.

DELETE Sterge rânduri dintr-un tabel al bazei de date

Instrucţiunile DML individuale afectează datele dintr-un singur tabel. Este

posibil ca într-o instrucţiune DML să referiţi şi o vizualizare care conţine date din mai

Page 158: Curs Sinteza SQL

multe tabele (adică o vizualizare care conţine o uniune de tabele), dar, în acest caz,

instrucţiunea DML poate referi numai coloane dintr-un singur tabel al vizualizării. Cu

alte cuvinte, atunci cand o instrucţiune DML foloseşte o vizualizare, toate coloanele

vizualizării referite în instrucţiunea DML trebuie să corespundă unor coloane dintr-un

singur tabel fizic al bazei de date.

Este foarte probabil ca sistemul SGBD folosit să pună la dispoziţie o formă

oarecare de tranzacţii, în care o serie de instrucţiuni DML sunt tratate unitar, adică un

grup de instructiuni care trebuie să reuşească toate sau sa eşueze toate. Această

caracteristică este foarte utilă atunci când instructiunile SQL sunt folosite în tranzacţii

comerciale.

SGBD va trata fiecare instrucţiune DML individuală ca pe o tranzactie.

Aceasta înseamna că, dacă apare o eroare la modificacfrea unui rând identificat de

instrucţiunea DML, sistemul DML va anula intreaga instrucţiune, asa că aceasta nu va

afecta nici unul din rândurile tabelului. Cu alte cuvinte, sistemul SGBD nu va permite

niciodată apariţia inconsecvenţelor în baza de date. De exemplu , dacă incerc să sterg

toate rândurile din tabelul FILM şi apare o eroare la ştergerea celui de-al treilea rând

(după ce au fost deja şterse primele două rânduri ), întreaga instrucţiune eşuează şi

sistemul SGBD reface (unii ar spune „ca prin magie‖) cele două rânduri şterse.

Instructiunile SQL din acestă lecţie presupune că sistemul SGBD pe care il

utilizaţi foloseste formatul AAAA-LL-ZZ pentru datele calendaristice.

Pentru bazele de date Oracle, instrucţiunea de mai jos modifică formatul

datelor calendaristice pentru sesiunea curenta (baza de date revine la formatul

prestabilit de fiecare dată când va reconectaţi la baza de date):

ALTER SESSION SET NLS_DATA_FORMAT=‘YYYY-MM-DD‘;

Un alt aspect de care este important să se ţină seama, sunt restricţiile definite

în tabelul referit de instrucţiunea DML. Sistemul SGBD nu va efectua în baza de date

nici o modificare care încalcă una din restricţii.

La formarea instructiunilor DML, trebuie să se ţină seama de urmatoarele

aspecte referitoare la restricţiile tabelului modificat:

Restricţii de tip cheie primară Atunci când inseraţi un nou rând într-un tabel, cheia primară a noului rând

trebuie sa fie unică în întregul tabel.Cand modificati valoarea unei chei primare (ceea

ce se intampla rareori), noua valoare trebuie să fie unică în întregul tabel.

Restricţii de unicitate Ca şi în cazul cheilor primare, coloanele pe care a fost definită o restricţie de

unicitate trebuie sa aibă valori unice în întregul tabel.

Restricţii NOT NULL O valoare nula (null) este o modalitate specială prin care sistemul SGBD

tratează valoarea unei coloane pentru a indica faptul ca valoarea coloanei respective

nu este cunoscută. O valoare nula nu este acelasi lucru un un spatiu liber, un sir vid

sau valoarea zero – este o valoare speciala care nu este egala cu nimic altceva.

În cazul instrucţiunilor INSERT, trebuie specificate valori pentru toate

coloanele cu restricţii NOT NULL.

În cazul instrucţiunilor UPDATE nu se pot inlocui valorile unei coloane cu

valori nule dacă pe coloana respectivă este definită p restricţie NOT NULL.

Dacă instrucţiunea DML referă o vizualizare , nu se poate sa o folosim intr-o

instrucţiune INSERT dacă una dintre coloanele tabelului cu o restricţie NOT

NULL(obligatorii) lipseşte din definirea vizualizării.

Page 159: Curs Sinteza SQL

Restricţii referenţiale Nu se poate insera sau actualiza valoarea unei chei externe decât dacă există

deja rândul părinte corespondent care conţine valoarea cheii în coloana cheii primare.

In sens invers, nu se poate şterge un rând părinte dacă există rânduri subordonate care

referă valoarea din rândul părinte, decât dacă restricţia a fost definită cu opţiunea ON

DELETE CASCADE. In general inserările în tabele trebuie făcute ierarhic (mai intai

randurile parinte, apoi randurile copii), iar ştergerile trebuie făcute în ordine inversă

(copiii inaintea părinţilor).

Restrictii de verificare (CHECK) O instructiune INSERT sau UPDATE nu

poate stoca într-o coloana o valoare care încalcă o restricţie CHECK definită pentru

coloana respectivă.

Instrucţiunea INSERT

Instrucţiunea SQL INSERT este folosită pentru inserarea noilor rânduri de

date în tabele. Instrucţiunea are două forme de bază: una în care valorile coloanelor

sunt specificate chiar în instrucţiune şi alta în care valorile sunt selectate dintr-un tabel

sau o vizualizare, folosind o subinterogare.

Inserarea unui singur rand de dete folosind clauza Values

Instrucţiunea INSERT care foloseşte o clauză VALUES poate crea un singur

rând la fiecare rulare, deoarece valorile pentru rândul de date respective sunt

specificate chiar în instrucţiune.

Iata sintaxa generală a instrucţiunii:

INSERT INTO nume_tabel_sau_vizualizare

[(lista_de_coloane)]

VALUES (lista_de_valori);

Se poate remarca următoarele:

Lista de coloane este opţională, dar dacă este inclusă trebuie sa fie incadrată în

paranteze.

Dacă lista de coloane este omisă, trebuie specificată o valoare pentru fiecare

coloană din tabel, în ordinea în care sunt definite coloanele în tabel. Este bine

ca întotdeauna să includeţi lista de coloane, deoarece opiterea acesteia face ca

instrucţiunea INSERT să fie dependentă de definiţia tabelului. Dacă o coloană

este modificată sau în tabel este adăugată o nouă coloană, chiar şi opţională,

probabil instrucţiunea INSERT va eşua la următoarea rulare.

Dacă lista de coloane este specificată, lista de valori trebuie să conţin o valoare

pentru fiecare coloană din listă, în aceeaşi ordine. Cu alte cuvinte, între lista de

coloane şi lista de valori trbuie să existe o corespondenţa unu-la-unu. Orice

coloana care lipseşte din listă va primi o valoare nulă, presupunund că valorile

nule sunt acceptate în coloana respectivă.

Cuvântul cheie NULL poate fi folosit în lista de valori pentru specificarea unei

valori nule pentru o coloană.

Page 160: Curs Sinteza SQL

În Microsoft SQL Server şi Sybase Adaptive Server nu puteţi insera valori într-

o coloană care a fost definită proprietatea IDENTITY. Proprietatea IDENTITY

este o metodă frecven folosită pentru a atribui valori secvenţiale unei chei

primare, cum ar fi coloana FILM_ID din tabelul FILM. Dacă pentru o coloană

a fost definită proprietatea IDENTITY, puteţi să omiteţi coloana respectivă din

instrucţiunea INSERT, iar sistemul SGBD va atribui cheii primare următoarea

valoare unică disponibilă. O altă soluţie este să dezactivaţi restricţia, folosind

următoarea instrucţiune:

SET identity_insert nume_tabel ON

Exemplul următor conţine două instrucţiuni INSERT, una care creează un nou

rând în tabelul FILM, cu o listă opţională de coloane, din care este omisă coloana

RETAIL_PRET_VHS, şi alta care creează un rând în tabelul FILM_COPII pentru

acelaşi timp, dar fără lista opţională de coloane.

INSERT INTO FILM

(FILM_ID, FILM_COD_GEN, MPAA_RATING_COD, FILM_NUME,

PRET_INCHIRIAT_DVD, AN_PRODUCERE)

VALUES (21,‘Drama‘,‘PG-13‘,‘Ray‘, 29.95, ‘2004‘);

INSERT INTO FILM_COPII

VALUES (21, 1, ‘2005-04-01‘,NULL,‘V‘);

Pentru Microsoft SQL Server şi Sybase Adaptive Server, dacă este definită

proprietatea IDENTITY pentru tabelul FILM, se poate folosi următoarea variantă a

primei instrucţiuni INSERT:

INSERT INTO FILM

(FILM_COD_GEN,MPAA_COD_VARSTE,FILM_NUME,

RETAIL_PRET_DVD,AN_PRODUCERE)

VALUES (‘Drama‘, ‘PG-13‘, ‘Ray‘, 29.95, ‘2004‘);

Inserări masive folosind instrucţiunea SELECT internă

Aşa cum se observă, este nevoie de foarte mult cod pentru a insera în tabel un

singur rând de date folosind o instrucţiune INSERT cu clauza VALUES.

O altă soluţie, care poate fi folosită pentru a insera rânduri multiple într-un

tabel , este forma care foloseşte o instrucţiune SELECT internă. Această formă este

utilă şi pentru stabilirea următoarei valori disponibile pentru o cheie primară cu valori

secvenţiale. De asemenea , poate fi folosită atunci când creaţi un tabel temporar

pentru testare şi vreţi să-l populaţi cu toate datele dintr-un alt tabel.

Sintaxa generală a instrucţiunii este

INSERT INTO nume_tabel_sau_vizualizare

[(lista_de_coloane)]

SELECT instructiune_select;

Se remarcă următoarele:

Lista de coloane este opţională, dar dacă este inclusă trebuie să fie încadrată în

paranteze.

Page 161: Curs Sinteza SQL

Dacă lista de coloane este omisă, instrucţiune SELECT internă trebuie să

furnizeze o valoare pentru fiecare coloană din tabel, în ordinea în care sunt

definite coloanele în tabel. Este bine ca întotdeauna să includeţi lista de

coloane, deoarece opiterea acesteia face ca instrucţiunea INSERT să fie

dependentă de definiţia tabelului. Dacă o coloană este modificată sau în tabel

este adăugată o nouă coloană, chiar şi opţională, probabil instrucţiunea

INSERT va eşua la următoarea rulare.

Dacă lista de coloane este specificată, instrucţiune SELECT internă să

furnizeze o valoare pentru fiecare coloană din lista de valori, în aceeaşi ordine.

Cu alte cuvinte, între lista de coloane şi setul de rezultate al instrucţiunii

SELECT trebuie să existe o corespondenţa unu-la-unu. Orice coloană care

lipseşte din listă va primi o valoare nulă, presupunund că valorile nule sunt

acceptate în coloana respectivă.

Cuvântul cheie NULL poate fi folosit în instrucţiunea SELECT pentru

specificarea unei valori nule pentru o coloană.

Ca exemplu, să presupunem că toate filmele sunt acum disponibile şi în limba

franceză. Tabelul FILM_LIMBA conţine rânduri pentru limba franceză pentru o parte

din filme, aşa că acum vrem să le adăugăm numai pe cele care lipsesc. Instrucţiunea

INSERT care va rezolva această problemă este:

INSERT INTO FILM_LIMBA

(FILM_ID, COD_LIMBA)

SELECT FILM_ID, ‘fr‘

FROM FILM FILM

WHERE FILM_ID NOT IN

( SELECT FILM_ID FROM FILM_LIMBA

WHERE COD_LIMBA =‘fr‘ );

Instrucţiunea UPDATE

Instrucţiunea UPDATE este folosită pentru actualizarea datelor din coloanele

unui tabel (sau ale unei vizualizări).

Sintaxa generală a instrucţiunii UPDATE:

UPDATE nume_tabel_sau_vizualizare

SET nume_coloana = expresie

[,nume_coloana = expresie...]

[ WHERE conditie];

Se remarcă următoarele:

Clauza SET conţine o listă cu una sau mai multe coloane, împreună cu o

expresie care specifică noua valoare pentru fiecare coloană. Aceasta este o listă

de perechi nume-valoare, separate prin virgule, cu un operator de egalitate între

fiecare nume şi valoare.

Expresia poate fi o constantă, un alt nume de coloană sau orice altă expresie pe

care SQL o poate transforma într-o singură valoare, care poate fi apoi atribuită

coloanei respective.

Clauza WHERE conţine o expresie care limitează rândurile actualizate. Dacă

această clauză este omisă, motorul SQL va încerca să actualizeze toate

rândurile din tabel sau din vizualizare.

Page 162: Curs Sinteza SQL

Exemple:

Un film a fost adăugat cu un preţ incorect. Instrucţiunea următoare va actualiya

două coloane din acelaşI rând a tabelului MOVIE.

UPDATE FILM

SET RETAIL_PRET_VHS = 29.95 ,

RETAIL_PRET_DVD = 34.95

WHERE FILM_ID = 21

Conducerea firmei de produse video a decis să crească salariul tuturor

funcţionarilor cu 10 procente. Această instrucţiune va actualiza o singură

coloană de pe mai multe rânduri, rotujind rezultatul la 2 zecimale cu funcţia

ROUND.

UPDATE ANGAJAT

SET ANGAJAT_PLATA_ORA = ROUND

(ANGAJAT_PLATA_ORA * 1.1, 2)

WHERE ANGAJAT_JOB_CATEGORY =‘C‘ ;

Instrucţiunea DELETE

Instrucţiunea DELETE şterge unul sau mai multe rânduri dintr-un tabel.

Instrucţiunea poate să folosească şi o vzualizare, dar numai dacă aceasta se bazează pe

un singur tabel (ceea ce înseamnă că instrucţiunile DELETE nu pot fi folosite pentru

vizualizări care conţin uniuni). În instrucţiunile DELETE nu sunt referite niciodată

coloane, doarece instrucţiunea şterge rânduri întregi de date, inclusiv toate valorile

datelor (toate coloanele) din rândurile afectate. Dacă vreţi să ştergeţi o singură valoare

din rândurile existente, folosiţi instrucţiunea UPDATE pentru a înlocui valorile

respective cu valori nule (presupunând că valorile nule sunt permise în acele coloane).

Sintaxa generală a instrucţiunii DELETE este

DELETE FROM nume_tabel_sau_vizualizare

[ WHERE conditie ];

Se remarcă următoarele:

Clauza WHERE este opţională. Totuşi, este folosită aproape întotdeauna,

deoarece o instrucţiune DELETE fără o clauză WHERE încearcă să şteargă

toate rândurile din tabel.

Atunci când este inclusă, clauza WHERE specifică rândurile care urmează să

fie şterse. Orice rând pentru care condiţia WHERE este evaluată ca adevărată

este şters din tabel.

Nu se pot şterge rânduri dacă se încalcă o restricţie referenţială. În general,

rândurile subordonate trebuie şterse înaintea rândurilor părinte.

Exemple:

Să se şteargă filmul adăugat mai devreme (cu FILM_ID = 21 ). Se observă că

trebuie să se ştergă mai întâi rândurile corespondente din tabelele

FILM_COPY şi FILM_LIMBA, deoarece acestea sunt rânduri „copii‖ ale

rândului din tabelul „FILM‖

Page 163: Curs Sinteza SQL

DELETE FROM FILM_COPY

WHERE FILM_ID = 21;

DELETE FROM FILM_LIMBA

WHERE FILM_ID = 21;

DELETE FROM FILM

WHERE FILM_ID = 21;

Să se şteargă din tabelul FILM_LIMBA toate rândurile pentru limba spaniolă

(COD_LIMBA='es' ). În multe implementări SQL se face diferenţierea literelor

mari de cele mici, caz în care valoarea codului de limbă trebuie specificată cu

litere mici pentru a se potrivi cu datele din tabel.

DELETE FROM FILM_LIMBA

WHERE COD_LIMBA =‘es‘;

Întrebări şi probleme

1. Limbajul DML include următoarele comenzi SQL:

a. INSERT

b. REMOVE

c. UPDATE

d. SELECT

e. DROP

2. O instrucţiune DML poate referi

a. Coloane din mai multe tabele

b. Coloane dintr-un singur tabel

c. O vizualizare care conţine coloane dintr-un singur tabel

d. Coloane ale unei vizualizări bazate pe un singur tabel

e. Coloane ale unei vizualizări bazate pe mai multe tabele

3. La formarea unei instrucţiuni DML, trebuie să tineti seama de următoarele

restricţii

a. Restricţii referenţiale

b. Restricţii de securitate

c. Restricţii NOT NULL

d. Restricţii de unicitate

e. Restricţii cheie primară

4. O instrucţiune INSERT cu o clauză VALUES

a. Trebuie să aibă o listă de coloane

b. Trebuie să aibă o listă de valori

c. Poate insera rânduri multiple la o singură rulare

d. Poate folosi cuvântul cheie NULL pentru a atribui valori nule coloanelor

e. Poate include o clauză WHERE

5. O instrucţiune INSERT cu o comandă SELECT imbricată este utilă pentru

a. Găsirea următoarei valori pentru o cheie primară atribuită secvenţial

b. Mutarea rândurilor dintr-un tabel în altul

Page 164: Curs Sinteza SQL

c. Popularea unui tabel de test cu date dintr-un alt tabel

d. Eliminarea rândurilor duplicate dintr-un tabel

e. Inserarea mai multor rânduri într-un tabel cu o singură instrucţiune

6. O instrucţiune INSERT cu o comandă SELECT imbricată

a. Trebuie să aibă două liste de coloane, una în clauza INSERT şi una în

b. Trebuie să aibă o instrucţiune SELECT internă care retumează un singur

rând de date

c. Poate folosi cuvântul cheie NULL pentru a atribui valori nule coloanelor

d. Poate include o clauză WHERE

e. Trebuie să aibă în instrucţiunea SELECT internă o listă de coloane care

corespunde cu lista de coloane din clauza INSERT sau cu coloanele din

tabelul în care sunt inserate datele

7. O instrucţiune UPDATE fără o clauză WHERE

a. Actualizează toate rândurile din tabel cu valori nule

b. încearcă să actualizeze toate rândurile din tabel

c. Eşuează şi returnează o eroare

d. Şterge toate rândurile din tabel

e. Are ca rezultat un produs cartezian

8. O instrucţiune DELETE fără o clauză WHERE

a. Actualizează toate rândurile din tabel cu valori nule

b. Eşuează si returnează o eroare

c. încearcă să şteargă toate rândurile din tabel

d. Are ca rezultat un produs cartezian

e. Trebuie să includă o listă de coloane

9. O instrucţiune UPDATE

a. Trebuie să includă o clauză SET

b. Trebuie să furnizeze o nouă valoare pentru cel puţin o coloană

c. Trebuie să includă o clauză WHERE

d. Poate atribui unei coloane valoarea unei alte coloane

e. Poate atribui unei coloane o listă de valori derivate dintr-o expresie

10. O instrucţiune DELETE

a. Poate include o listă opţională de coloane

b. Poate include o clauză WHERE opţională

c. Poate folosi cuvântul cheie FORCE pentru a forţa ştergerea rândurilor

d. Nu poate încălca restricţiile referenţiale ale tabelului

e. Poate avea o instrucţiune SELECT internă, ca parte a clauzei WHERE

11. Clauza SET dintr-o instrucţiune UPDATE poate atribui unei coloane o

valoare care este

a. O constantă

b. Numele unei alte coloane

c. O listă de valori

d. Orice expresie din care rezultă o singură valoare

e. Cuvântul cheie NULL

Page 165: Curs Sinteza SQL

12. Instrucţiunea SELECT internă a unei instrucţiuni INSERT poate include

a. O clauză WHERE

b. O clauză GROUP BY

c. Una sau mai multe funcţii de agregare

d. O uniune a mai multor tabele

e. O clauză UNION

Scrieţi instrucţiuni SQL pentru următoarele probleme

13. Folosind o instrucţiune INSERT cu o clauză VALUES, dar fără listă de

coloane, inseraţi în tabelul FILM_GENRE un nou rând, cu valorile FILM_COD_GEN

= TRAIN' şi FILM_DESCRIERE_GEN = Training'.

14. Folosind o instrucţiune INSERT cu o clauză VALUES si o listă de

coloane, inseraţi în tabelul FILM un nou rând, cu următoarele valori pentru date:

FILM_ID: 99

FILM_COD_GEN: 'TRAIN'

MPAA_COD_RATING: NR

FILM_NUME: ANGAJAT

Training Video

15. Folosind o instrucţiune INSERT cu o instrucţiune SELECT internă,

inseraţi în tabelul FILM_LIMBA un rând pentru limba japoneză

(COD_LIMBA = 'ja'), asociat cu toate filmele din tabelul FILM. (în prezent,

tabelul FILM_LIMBA nu conţine nici un rând pentru limba japoneză.)

16. Creaţi un tabel, numit TOTAL_INCHIRIERE, folosind instrucţiunea

CREATE de mai jos. Folosind o instrucţiune INSERT cu o instrucţiune SELECT

internă, inseraţi în tabelul TOTAL_INCHIRIEREun rând pentru fiecare film din

tabelul FILM INCHIRIERE, conţinând numărul total de închirieri şi suma totală

obţinută din închirierea filmului respectiv.

CREATE TABLE TOTAL_INCHIRIERE

(FILM_ID INTEGER NOT NULL,

NUMBER_OF_INCHIRIERES INTEGER NOT NULL,

TOTAL_COST_INCHIRIERES NUMERIC (7, 2) NOT NULL);

17. Ştergeţi toate rândurile din tabelul INCHIRIERE TOTAL.

18. Ştergeţi rândurile pentru limba japoneză, create la întrebarea 15.

19. Copia 1 a filmului 1 (FILM_ID = 1, NUMAR_COPIE = 1) a fost vândută

pe data de 15 ianuarie 2005. actualizaţi rândul respectiv din tabelul

FILM_COPII.

20. Actualizaţi tabelul FILM astfel încât să creşteţi cu 10 procente toate

preţurile pentru formatul VHS (RETAIL_PRET_VHS) care nu conţin valori

nule.

Page 166: Curs Sinteza SQL

.

BIBLIOGRAFIE

1. Ileana Popescu, Letiţia Vercescu, Proiectarea bazelor de date, Editura

2. Popescu Ileana, Modelarea bazelor de date, Editura Tehnică, 2001

3. Mariana Popa, Baze de date Editura FRM, 2006

4. Roger Jennings, Utilizare Access, Editura Teora, 1998

5. Chris Fehily, SQL- Învăţaţi SQL rapid şi uşor!, Editura B.I.C. ALL,

2004