Sunteți pe pagina 1din 18

Câteva problemele ale formelor normalizate 2 şi 3

Marin Fotache

Proiectarea bazelor de date

Ca să folosesc un termen elevat şi, cu ocazia asta, să-mi descarc un pic sufletul, aşa negru
cum este el (sufletul), constat nepuntincios că am o anumită propensiune pentru subiecte
banale (pentru cei neatenţi, propensiune este termenul elevat de care vorbeam). M-a
încercat şi mă încearcă senzaţia că, alături de politică şi fotbal, la normalizarea bazelor de
date ne pricepem cu toţii. Ba chiar şi multe cărţile şi publicaţiile străine la care am avut
acces on şi off line conferă normalizării un aer de clasat, iar când e vorba de exemple,
încep a debita teoreme şi demonstraţii…

Mă intrigă şi amuză faptul că, mai întotdeauna, atunci când am fost pus în situaţia de a
elabora schema unei baze de date pentru o problemă/aplicaţie practică (deci, invitabil,
reală) au apărut elemente ce au pus la grea încercare fundamentul teoretic al normalizării.
Din experienţă şi cazuistica lucrului cu studenţii de la specializarea Informatică
Economică, vă prezint astăzi câteva asemenea cazuri care, în marea majoritate a lucrărilor
dedicate proiectării bazelor de date, sunt eludate sau sever simplificate pentru a evita
durerile de cap. Mă refer chiar la autori celebri, precum Date, Teorey, Riordan, Connolly,
Begg şi Strachan, Flemming şi von Halle sau Celko.

Acum doi ani (PCReport nr. 92/mai 2000), v-am prezentat un material despre prima
forma normală. Mă aşteptam la oarecare răceală atât din partea redacţiei, cât şi a
cititorilor, dat fiind că subiectul părea a fi unul entry-level în proiectarea bazelor de date,
în vădită contradicţie cu nivelul cititorilor revistei. N-aş zice că entuziasmul provocat de
articol a fost unul deşănţat, dar am avut suficiente motive pentru a prinde ceva curaj şi
iată-mă-s prezentându-vă câteva găselniţe ale 2NF şi 3NF. Cât despre forma normalizată
Boyce-Codd sau 4NF şi 5NF, aici lucrurile sunt şi mai pestriţe, după cum probabil vom
vedea într-un material viitor (care, dacă ar fi să respect ritmul, l-aş trimite redacţiei peste
exact un an).

Pentru o scurtă încălzire, vă reamintesc că în proiectarea bazelor de date există două


abordări. Prima este de tip top-down, şi porneşte de la modelele datelor elaborate în etapa
de analiză şi proiectare a sistemului/aplicaţiei, modele materializate în diagrame E-R
(entitate-relaţii) care sunt apoi transformate în tabele relaţionale. A doua se derulează în
sens invers, pornind de la informaţiile de bază care sunt atribute. Pe baza identificării
legăturilor dintre atribute (depedenţele funcţionale, multivaloare, de joncţiune), se
elaborează formele normalizate ale bazei de date (1NF, 2NF, … 5NF). Prima abordare
prezintă atuul legării de fazele din "amonte" ale procesului de dezvoltare a
sistemului/aplicaţiei şi se recomandă pentru aplicaţii complexe. A doua este mai
riguroasă, mai directă, dar devine obositoare, chiar insuportabilă, atunci când numărul
atributelor este mare.
Respectând adevarul istoric, trebuie spus că normalizarea nu este exclusă în
metodologiile de tip top-down. Cel mai târziu, după generarea relaţiilor din diagramele
entităţilor şi relaţiilor (asociaţiilor), are loc verificarea "normalizatăţii". Deci, oricum am
face, de normalizare e greu de scăpat.

Reţeta clasică a normalizării este:

• se inventariază toate atributele şi se constituie astfel relaţia universală (de


pornire);
• se determină cheia primară a relaţiei universale şi se reprezintă toate depedenţele
funcţionale (DF) ce decurg de aici;
• se inventariază toate depedenţele funcţionale revelante şi ireductibile dintre
atributele relaţiei universale;
• se elimină depedenţele parţiale prin ruperea relaţiei universale în relaţii cu schemă
mai simplă;
• din relaţiile obţinute se elimină dependenţele tranzitive, prin spargerea succesivă a
relaţiilor în altele cu schema din ce în ce mai simplă, astfel încât nici una din
tabelele finale nu conţine dependeţe parţiale sau tranzitive;
• se identifică eventualele dependenţe multivaloare şi, dacă există asemenea
depedenţe, se operează noi descompuneri ale tabelelor ce vor fi, astfel, în 4FN;
• se încearcă determinarea eventualelor depedenţe de joncţiune şi, pe baza acestora,
reelaţiile sunt aduse în 5FN;

Până la un punct, reţeta este simplă şi chiar simpatică. Din păcate, realitatea este mai
complicată, uneori, pur şi simplu, refuzând să se supună teoriei ! În cele ce urmează ne
vom ocupă doar de primele etape din cele prezentate mai sus.

Dependenţe funcţionale

Formal, dacă notăm relaţia R {A1, A2,...., An}:

unde: R este numele relaţiei, iar Ai sunt atributele relaţiei R, şi prin X şi Y două
subansamble ale ansamblului {A1, A2,...., An}, se spune că există o dependenţă
funcţională între X şi Y dacă şi numai dacă :

- fiecare apariţie (valoare) a lui X poate fi asociată unei singure apariţii a lui Y,

- două apariţii identice ale lui X nu pot fi asociate decât aceleiaşi apariţii a lui Y.

Se notează X —→ Y.

Într-o prezentare şi mai explicită, Date defineşte dependenţa funcţională după cum
urmează: Dată fiind o relaţie R, subansamblul de atribute Y din R depinde funcţional de
subansamblul X (tot din R), dacă şi numai dacă, ori de câte ori două tupluri din R
prezintă aceeaşi valoare pentru X, obligatoriu valoarea celor două tupluri este identică
şi pentru Y.
Implicit, în orice relaţie R există dependenţele funcţionale: cheia lui R —→ celelalte
atribute ale lui R.

O dependenţă funcţională în care scopul (destinaţia) este alcătuit dintr-un singur atribut
se numeşte dependenţă funcţională canonică sau dependenţă funcţională în formă
canonică.

Există dependenţe funcţionale care prezintă în partea stângă (sursa dependenţei


funcţionale sau determinantul) două sau mai multe atribute. Acestea sunt dependenţele
funcţionale cu sursa compusă. Revenim la un exemplu simplu prezentat în articolul de
anul trecut.

LOCALITĂŢI

CodPoştal OraşComună Sat Judeţ


5319 Vînători Vînători Vrancea
5319 Vînători Jorăşti Vrancea
5319 Vînători Mirceştii-Vechi Vrancea
5613 Roznov Roznov Neamţ
5613 Roznov Slobozia Neamţ
5300 Focşani NULL Vrancea

Figura 1. Relaţia LOCALITĂŢI

un oraş sau o comună au un singur cod poştal:

(1) CodPoştal —→ OraşComună

(2) CodPoştal —→ Judeţ

într-o comună sunt mai multe sate: CodPoştal §/§ Sat

Dependenţe funcţionale totale şi a doua formă normalizată (2NF)

Noţiunea de dependenţă funcţională totală a fost introdusă de Melkanoff. O dependenţă


funcţională Data1 —→ Data2 este elementară dacă nu există nici o Dată3 ca
subansamblu al Data1, care să verifice dependenţa funcţională Dată3 —→ Dată2.

Formal, dacă X = { Ai, Aj,...., Ak } reprezintă un grup de atribute ale relaţiei R, iar Am
un atribut al aceleiaşi relaţii, unde Am § X. Se spune că există o dependenţă funcţională
totală între X şi Am dacă:

1. X —→ Am ,
2. nu există nici un subansamblu S de atribute, S § X, pentru care S —→ Am .

Dependenţa funcţională totală mai este denumită şi elementară, plină, deplină sau
completă, prin opoziţie cu depedenţele parţiale, sau incompete.

Începând cu a doua formă normală, relaţiile pot fi decupate în sub-relaţii, în scopul


diminuării problemelor legate de stocare şi actualizare. În general, atunci când într-o
relaţie R există o DF de tip X —→ Y şi X nu este cheie candidată, este sigur că R conţine
o anumită doză de redundanţă [Date00].

Jan Heath a demonstrat că orice relaţie alcătuită din trei atribute, notat( R(X, Y, Z), în
care există dependenţa funcţională X —→ Y poate fi descompusă în două relaţii R1(X,
Y) şi R2(X, Z) [Heath71]; R1 şi R2 reprezentă proiecţiile relaţiile R pe atributele X şi Y,
respectiv X şi Z. Esenţial este faptul că descompunerea să se facă fără pierdere de
informaţii, adică R să poată fi "recompusă" prin joncţiunea tabelelor R1 şi R2. Astfel, se
poate rezolva problema cheii primare a relaţiei universale, în cazurile încălcării restricţiei
de entitate (un atribut din cheia primară prezintă valori nule).

O relaţie se află în 2NF dacă:

1. Se află în 1NF.

2. Toate DF ce leagă cheia primară la celelalte atribute sunt DF elementare (totale).

Problema trecerii unei relaţii din prima în a doua formă normală se pune numai când
cheia primară a relaţiei este compusă din mai multe atribute. Într-o formulare mai lejeră,
se poate spune că o relaţie în 2FN nu conţine DF parţiale între atributele-cheie şi
celelalte atribute.

În general, trecerea de la 1NF la 2NF se poate realiza după următoarea succesiune de


paşi:

a) Se inventariază toate dependenţele dintre atributele relaţiei, cu excepţia celor în care


destinaţia este un atribut component al cheii primare.

b) Se trec în revistă toate dependenţele care au ca sursă (determinant) un atribut sau sub-
ansamblu de atribute din cheia primară.

c) Pentru fiecare atribut (sau sub-ansamblu) al cheii de la pasul b), se creează o relaţie
care va avea drept identificator primar atributul (subansamblul) respectiv, iar celelalte
atribute vor fi cele care apar ca destinaţii în dependenţele de la pasul b).

Cheia primă a relaţiei LOCALITĂŢI din figura 1 prezintă problema nulităţii unuia dintre
atributele componente, deoarece singura combinaţie plauzibilă - (CodPoştal, Sat) -
încalcă restricţia de entitate (pentru liniile care se referă la oraşe valoarea atributului Sat
este NULL) Cu toate acestea se poate scrie:
(1) (CodPoştal, Sat) —→ OraşComună

(2) (CodPoştal, Sat) —→ Judeţ

Dar:

(3) CodPoştal —→ OraşComună

(4) CodPoştal —→ Judeţ

deci (1) şi (2) sunt DF parţiale.

Ţinând seama de acest lucru, relaţia poate fi ruptă astfel:

ORAŞE_COMUNE {CodPoştal, OraşComună, Judeţ}

şi

SATE {CodPoştal, Sat}

al căror conţinut este prezentat în figura 2.

Figura 2. Relaţia LOCALITĂŢI adusă în 2NF cu rezolvarea problemei cheii primare

Pentru a verifica justeţea ruperii relaţii iniţiale în cele două noi tabele, ar trebui ca prin
joncţiunea ORASE_COMUNE cu SATE să obţinem LOCALITĂŢI. Şi, într-adevăr prin
fraza standard SQL-92:

SELECT oc.codpostal, orascomuna, sat, judet


FROM orase_comune oc LEFT OUTER JOIN sate s
ON oc.codpostal=s.codpostal

rezultatul are acelaşi conţinut informaţional ca şi LOCALITĂŢI. Atenţie, însă, folosim


joncţiunea externă, şi nu cea naturală (sau echijoncţiunea).

Avantajele descompunerii în cele două relaţii sunt vizibile. Mai întâi, ambele sunt în 1NF
şi au cheie primară. În al doilea rând, se elimină redundenţele. În LOCALITĂŢI, dacă o
comună are şase sate, de şase ori apare şi codul poştal al comunei, şi denumirea comunei
şi a judeţului. Acum însă, denumirea comunei şi judeţului apare o singură dată în relaţia
ORAŞE_COMUNE. De asemenea, pentru fiecare oraş apare o singură înregistrare în
ORAŞE_COMUNE şi, firesc, nici una în SATE.

Forme normalizate optimale

Dacă avem în vedere teorema lui Heath, ruperea unei relaţii în mai multe tabele poate fi
făcută cu oarecare frenezie. Astfel, în LOCALITATI, pe baza DF: CodPoştal —→
OraşComună şi CodPoştal —→ Judeţ, baza de date poate fi adusă în 2FN şi astfel:

CODPOST_ORCOM {CodPoştal, OraşComună }


CODPOST_JUD {CodPoştal, Judeţ}

şi

SATE {CodPoştal, Sat}

Este clar că avem de-a face cu o exagerare, deşi toate cele trei relaţii respectă cu sfinţenie
condiţiile formei a doua normale. De cele mai multe ori, în normalizare se aplică
principiul obţinerii celui mai mic număr de relaţii care să răspecte condiţiile uneia sau
alteia dintre formele normalizate.

Dependenţe funcţionale directe/tranzitive şi a treia formă normalizată

O dependenţă funcţională Dată1 —→ Dată2 este directă atunci când nu există o Dată3
care angajează o dependenţă funcţională tranzitivă de genul: Dată1 —→ Dată3 —→
Dată2.

Prima definiţie a celei de-a treia forme normale a unei relaţii poate fi formulată relativ
simplu şi incremental, prin raportare la 2NF. O relaţie se află în 3NF dacă:

1. Se găseşte în 2NF.

2. Toate atributele care nu aparţin cheii primare nu depind funcţional de un alt atribut
(ansamblu de atribute) care nu face parte din cheie.

A doua condiţie poate fi exprimată şi în maniera: toate dependenţele funcţionale care


leagă cheia primară de celelalte atribute sunt directe (netranzitive).

Trecerea din 2NF în 3NF presupune eliminarea DF tranzitive şi se poate face, pentru o
relaţie, în următoarea manieră:

a) Se identifică toate atributele ce nu fac parte din cheie şi care sunt surse ale unor
dependenţe funcţionale.

b) Pentru toate atributele identificate la punctul a), se constituie câte o relaţie în care
cheie primară va fi atributul respectiv, iar celelate atribute destinaţiile din dependenţele
considerate.
Operaţiile a) şi b) se repetă şi pentru relaţiile "proaspăt" obţinute prin decompoziţie.

Câteva probleme ale depedenţelor funcţionale şi normalizării

Chiar pentru cazuri simple, ansamblul tuturor DF într-o bază de date poate să devină
extrem de stufos. De aceea, în procesul normalizării trebuie avut în vedere un echilibru
între:

identificarea tuturor DF ce reflectă restricţii, reguli ale fenomenului / procesului modelat,


şi

includerea în setul DF numai a celor relevante, din care, adică a unui ansamblu minimal
din care, prin reguli de genul celor de mai sus, se pot obţine toate celelalte DF.

În cele ce urmează sunt prezentate trei categorii de situaţii destul de problematice în


procesul aducerii bazei de date în 3FN: depedenţele funcţionale simetrice şi care decurg
din calitatea de cheie candidată, dependenţe aparent tranzitive şi dependenţe tranzitive
necanonice.

Dependenţe simetrice şi care decurg din calitatea de cheie candidată

Deseori, o bază de date sau relaţie prezintă mai multe chei candidat. Alegerea dintre
acestea a cheii primare are în vedere, pe lângă unicitate, compoziţie minimală şi valori
nenule ale oricărui atribut component, şi elemente ce ţin de facilitatea utilizării: uşurinţa
reţinerii (de către utilizator), lungime cât mai mică, constanţă în timp etc.

În procesul normalizării, problemele ridicate de aceste depedenţe reciproce dintre cheile


candidat trebuie tratate cu prudenţă. În general, este recomandat ca, din ansamblul DF al
unei relaţii să fie eliminate toate cele în care sursa este o cheie candidat şi păstrarea
numai celor în care determinantul este atributul cheie primară.

Spre exemplu, luăm în discuţie următoarea relaţie ce conţine informaţii despre firmele
client: R {CodClient, DenClient, Adresa, CodPoştal, Localitate, Judet, CodFiscal}.
Relaţia are trei chei candidate: CodClient, DenClient şi CodFiscal. La modul riguros, ar
trebuie scris:

(1) CodClient —→ DenClient

(2) CodClient —→ Adresa

(3) CodClient —→ CodPostal

(4) CodClient —→ Localitate

(5) CodClient —→ Judeţ


(6) CodClient —→ CodFiscal

(7) DenClient —→ CodClient

(8) DenClient —→ Adresa

(9) DenClient —→ CodPostal

(10) DenClient —→ Localitate

(11) DenClient —→ Judeţ

(12) DenClient —→ CodFiscal

(13) CodFiscal —→ CodClient

(14) CodFiscal —→ DenClient

(15) CodFiscal —→ Adresa

(16) CodFiscal —→ CodPostal

(17) CodFiscal —→ Localitate

(18) CodFiscal —→ Judeţ

Toate cele 18 dependenţe funcţionale sunt corecte şi totale. Perechile (1) şi (7), (6) şi
(13), (12) şi (14) sunt însă simetrice. Pe de altă parte, datorită dependenţei (8), ar însemna
că (2) este tranzitivă: CodClient —→ DenClient —→ Adresa, ceea ce e o exagerare.
Deşi nu elimină toate necazurile, pentru simplificare se recomandă alegerea unuia dintre
cele trei atribute drept cheie primară şi eliminarea tuturor depedenţelor funcţionale de
decurg din calitatea de cheie candidată a celorlalte atribute. Astfel, dacă am "unge" drept
cheie primară atributul CodClient, atunci dintre cele 18 dependenţe am păstra numai
primele şase, la care se adaugă cele în care sursa este CodPoştal.

După cum vom vedea în alt material, atunci când cheile candidate sunt compuse, discuţia
se complică şi mai mult, iar forma "clasică" a 3FN prezintă o serie de inadvertenţe.
Dealtminteri, aşa a "apărut" BCNF (Boyce-Codd Normal Form).

DF aparent tranzitive dar care conţin informaţii neredundante

Să luăm un exemplu foarte simplu: R{Profesor, Birou, Catedră, Telefon} care conţine
date despre "domiciliul" în facultate al fiecărui profesor.

Un profesor are un singur birou (Birou identifică fără ambiguitate sala respectivă):
(1) Profesor —→ Birou

Un profesor face parte dintr-o singură catedră:

(2) Profesor —→ Catedră

Într-un birou pot "locui" mai mulţi profesori (deşi, uneori, lucrul acesta îi nemulţumeşte
profund):

Birou §/§ Profesor

Fiecare birou este arondat unei singure catedre (Economie politică, Contabilitate etc.):

(3) Birou —→ Catedră

Fiecare birou are un număr de telefon unic:

(4) Birou —→ Telefon

Din (3) ar reieşi că (2) este DF tranzitivă, iar relaţia ar trebui descompusă numai în:

R1 {Birou, Catedră, Telefon}

R2 {Profesor, Birou}

Apare însă o situaţie ce aruncă în aer algoritmul nostru: un profesor are un birou alocat
altei catedre ! Situaţia este reală. Catedrele pot opera, temporar sau definitiv, schimburi
de birouri. Pentru profesorii care ocupă un birou alocat altei catedre, schema bazei
alcătuită din R1 şi R2 furnizează eronat răspunsul la întrebarea: Din ce catedră face parte
fiecare profesor ?

O soluţie ar fi să se delimiteze, semantic, catedrele care deţin birouri şi catedrele la care


sunt afiliaţi profesorii: R { Profesor, CatedrăProfesor, Birou, CatedrăBirou, Telefon}:

(1) Profesor —→ Birou

(2) Profesor —→ CatedrăProfesor

(3) Birou —→ CatedrăBirou

(4) Birou —→ Telefon

Noua schemă ar fi:

R1 {Birou, CatedrăBirou, Telefon}


R2 {Profesor, CatedrăProfesor, Birou}

Se poate obiecta că ambele atribute, CatedrăBirou şi CatedrăProfesor, se referă la


aceeaşi entitate, deci seamănă a redundanţă. Cu toate acestea, soluţia elimină problema
pierderii de informaţii, deci poate fi însuşită la proiectarea schemei bazei de date.

Dependenţe tranzitive necanonice

În exemplele de până acum am avut în lucrat cu depedenţe funcţionale în formă canonică


- cele în care destinaţia este alcătuită dintr-un singur atribut. Lucrurile nu sunt grozav de
complicate, identificarea depedenţelor fiind o operaţiune lesnicioasă. Din păcate, în unele
situaţii este posibil ca tranzitivitatea să se stabilească prin depedenţe a căror destinaţie
este compusă din două sau mai multe atribute.

La normalizarea relaţiilor este recomandabil ca, în situaţia unor dependenţe funcţionale


de genul: A —→ B, A —→ C, A —→ D, A —→ E, dependenţe ce derivă din rolul de
cheie primară pe care îl îndeplineşte atributul A, să se verifice dacă nu cumva există:

fie o dependenţă funcţională simplă, de genul B —→ D,

fie o dependenţă funcţională cu sursa compusă, de genul (B,C) —→ D.

Dacă una din cele două afirmaţii de mai sus este adevărată, atunci dependenţa funcţională
A —→ E nu este directă.

Primul caz

Luăm în discuţie tabela COMENZI, prezentată în figura 3, tabelă care gestionează


comenzile pe care firma noastră le-a trimis furnizorilor (în care solicităm
materialele/produsele/serviciile de care avem nevoie). Pe baza unei comenzi, un furnizor
trimite produsele solicitate, întocmind o factură din care ne va fi remis un exemplar.

Figura 3. Tabela COMENZI

Stabilim următoarele restricţii: o comandă are un număr unic, stabilit de întreprinderea


noastră, fiind întocmită pentru un singur furnizor; pentru o comandă, furnizorul va
întocmi o singură factură.

Astfel, atributul NrComanda este cheia primară . Ca urmare, se poate scrie:

NrComanda —→ Nrfactură (1)

NrComanda —→ CodFurnizor (2)

NrComanda —→ Datafactură (3)


NrComanda —→ Valoare (4)

NrComanda —→ TVADeduct (5)

Facturile sunt întocmite de furnizori (care le numerotează independent între ei):

(Nrfactură, CodFurnizor) —→ Datafactură (6)

(Nrfactură, CodFurnizor) —→ Valoare (7)

(Nrfactură, CodFurnizor) —→ TVADeduct (8)

În virtutea ultimelor trei dependenţe funcţionale, rezultă că dependenţele (3), (4) şi (5)
sunt tranzitive.

NrComanda —→ (Nrfactură, CodFurnizor) —→ Datafactură

NrComanda —→ (Nrfactură, CodFurnizor) —→ Valoare

NrComanda —→ (Nrfactură, CodFurnizor) —→ TVADeduct

Pe baza tranzitivităţii, tabela COMENZI se poate sparge în două relaţii


FACTURI_PRIMITE şi COMEZI_FACTURI, ca în figura 4 - Eliminarea DF tranzitive
din tabela COMENZI

La drept vorbind, nu trebuie un talent deosebit de cârcotaş pentru a recunoaşte că


economia de spaţiu şi diminuarea redundanţei sunt mai degrabă simbolice, dacă nu chiar
lucrurile se complică prin introducerea unei restricţii refererenţiale şi, normal, prin
apariţia de două ori a atributelor de legătură NrFactură şi CodFurnizor.

Există, totuşi, un merit indiscutabil al noilor relaţii. În relaţia COMENZI nu se poate


prelua nici o factură fără a-i cunoaşte comanda (eterna problemă a restricţiei de entitate -
nici un atribut component al cheii nu poate avea nule). Practica economico-financiară de
la noi, dar şi din alte părţi cunoaşte suficiente cazuri în care firmele primesc facturi direct,
fără a înainta o comandă prealabilă. Utilizând proaspetele tabele, FACTURI_PRIMITE şi
COMENZI_FACTURI, o factură fără comandă va apărea numai în prima din cele două
relaţii. Deşi am adăugat, şi nu eliminat (aşa cum, generos, sună unul dintre obiectivele
normalizării) redundanţă, noua structură este mai "sănătoasă" din punct de vedere
relaţional.

Al doilea caz

Pentru un plus de credibilitate, să luăm cazul unei baze de date pentru evidenţierea
rezultatelor studenţilor din sesiunile de pe parcursul unui universitar:
R {Matricol, NumePren, An, Modul, Spec, Grupa, CodDisc, DenDisc, NrCredDisc,
CodProf, NumeProf, GradProf, DataEx, SalaEx, Nota}

Atribut Descriere Tip


O comibaţie de litere şi cifre
Matricol CHAR
ce identifică în mod unic un student
NumePren Numele şi prenumele studentului CHAR
An Anul de studiu NUMERIC
Modulul de studiu: este o literă ce
Modul CHAR
desemnează un grup de specializări
Specializarea (��de la contabilitate,
Spec CHAR
��de la Informatică economică etc.)
Grupa Grupa de studiu NUMERIC
Codul disciplinei din planul de
CodDisc CHAR
invăţământ al specializării
DenDisc Denumirea disciplinei CHAR
NrCredDisc Numărul de credite alocat disciplinei NUMERIC
CodProf Codul profesorului CHAR
NumeProf Numele profesorului CHAR
P �profesor, C �conferenţiar, L - lector,
GradProf CHAR
A �asistent, P-preparator,
A �din afară (colaborator)
DataEx Data examenului DATE
SalaEx Sala de desfăşurare a examenului CHAR
Nota Nota obţinută NUMERIC

Tabel 1. Dicţionarul datelor pentru baza de date EXAMENE

Pentru simplificare, am luat în calcul numai studenţii de la profilul Economic, lungă


durată (4-5 ani), cursuri de zi.

O linie din R reprezintă rezultatul obţinut de un student la o disciplină într-o sesiune de


examinare. Spre exemplu, un student (matricol EL001103) poate obţine la disciplina
Microeconomie (cod AE1001) nota 4 (scuze) în prima sesiune de examinare - ianuarie
2001 (data examenului: 19 ianuarie 2001) şi nota 9 în a doua sesiune de examinare -
februarie 2001 (data ex: 14/02/2001). Cei mai puţin dispuşi la efort se pot califica în faze
superioare ale competiţiei (sesiunea mai 2001 s.a.m.d.).
Acestea fiind spuse, cheia primară a relaţiei R este (Matricol, CodDisc, DataEx), pe baza
căreia pot fi scrise următoarele DF:

(1) (Matricol, CodDisc, DataEx) —→ NumePren

(2) (Matricol, CodDisc, DataEx) —→ An

(3) (Matricol, CodDisc, DataEx) —→ Modul

(4) (Matricol, CodDisc, DataEx) —→ Spec

(5) (Matricol, CodDisc, DataEx) —→ Grupa

(6) (Matricol, CodDisc, DataEx) —→ DenDisc

(7) (Matricol, CodDisc, DataEx) —→ NrCredDisc

(8) (Matricol, CodDisc, DataEx) —→ CodProf

(9) (Matricol, CodDisc, DataEx) —→ NumeProf

(10) (Matricol, CodDisc, DataEx) —→ GradProf

(11) (Matricol, CodDisc, DataEx) —→ SalaEx

(12) (Matricol, CodDisc, DataEx) —→ Nota

Relaţia R este în prima formă normalizată. Pentru a demonstra că nu este în 2FN trebuie
să găsim în ansamblul DF (1)- (12) măcar o DF parţială. Lucru destul de simplu, dacă
ţinem seamă de următoarele DF în care sursa o constituie unul dintre atributele
componente ale cheii.

Matricolul identifică în mod unic un student înscris la o specializare într-un an de studii.

(13) Matricol —→ NumePren

(14) Matricol —→ An

(15) Matricol —→ Modul

(16) Matricol —→ Spec

(17) Matricol —→ Grupa

CodDisc identifică în mod unic fiecare discplină din planul de învăţământ al specializării:
(18) CodDisc —→ DenDisc

(19) CodDisc —→ NrCredDisc

Pe baza ultimelor şapte DF, relaţia universală R se poate descompune astfel:

R1 {Matricol, NumePren, An, Modul, Spec, Grupa}

R2 { CodDisc, DenDisc, NrCredDisc}

R3 {Matricol, CodDisc, CodProf, NumeProf, GradProf, DataEx, SalaEx, Nota}

Cele trei relaţii sunt în 2NF.

Aducerea BD în 3NF echivalează cu eliminarea depedenţelor tranzitive din R1, R2 şi R3.


În R1 singurele DF existente sunt (13)-(17), deci această relaţie este în 3NF. Nici R2 nu
conţine depedenţe tranzitive; în schimb R3 da:

CodProf identifică în mod unic un profesor:

(20) CodProf —→ NumeProf

(21) CodProf —→ GradProf

Pe baza DF (20) şi (21), putem spune că (9) şi (10) sunt tranzitive, aşa încât rupem R3 în
R31 {CodProf, NumeProf, GradProf } şi R32 {Matricol, CodDisc, CodProf, DataEx,
SalaEx, Nota}.

Astfel, în 3NF, relaţia universală R are o schemă alcătuită din patru relaţii, după cum
urmează:

STUDENTI {Matricol, NumePren, An, Modul, Spec, Grupa}

DISCIPLINE { CodDisc, DenDisc, NrCredDisc }

PROFESORI {CodProf, NumeProf, GradProf }

NOTE1 {Matricol, CodDisc, CodProf, DataEx, SalaEx, Nota}

Nici una din cele patru relaţii nu conţine DF tranzitive. Cu toate acestea, schema este
departe de a fi optimă. Faţă de DF discutate, mai există două restricţii neluate în calcul în
normalizare:

La o serie de curs (seriile de curs se constituie, pentru fiecare disciplină, la nivel de an,
modul, specializare) titular este un singur profesor:
(22) (CodDisc, An, Modul, Spec) —→ CodProf

Studenţii unei specializări susţin examenul la o disciplină în aceeaşi sală (şi acceaşi zi):

(23) (An, Modul, Spec, DataEx) —→ SalaEx

Să recapitulăm: în relaţia NOTE există DF:

(8) (Matricol, CodDisc, DataEx) —→ CodProf

dar şi

(22) (CodDisc, An, Modul, Spec) —→ CodProf

Deoarece există DF (24): Matricol —→ (An, Modul, Spec)

rezultă ca (8) este o DF necanonică, aşa încât relaţia NOTE1 s-ar descompune în:

DISC_SPEC_PROFI { CodDisc, An, Modul, Spec, CodProf}

şi

NOTE2 {Matricol, CodDisc, DataEx, SalaEx, Nota}

Câştigul este considerabil. Analog se poate proceda cu DF (23), discuţia transferându-se


în relaţia NOTE2, în care, din calitatatea de cheie primară a celor trei atribute există
depedenţa:

(11) (Matricol, CodDisc, DataEx) —→ SalaEx

dar şi DF:

(23) (An, Modul, Spec, CodDisc, DataEx) —→ SalaEx.

Pe baza depedenţei (24), relaţia NOTE2 se sparge în

SALI_EX {An, Modul, Spec, CodDisc, DataEx, SalaEx }

şi

NOTE {Matricol, CodDisc, DataEx, Nota}

Ajungem, astfel la o cu totul altă structură a bazei de date, mult mai bună decât
precedenta:

STUDENTI {Matricol, NumePren, An, Modul, Spec, Grupa}


DISCIPLINE { CodDisc, DenDisc, NrCredDisc }

PROFESORI {CodProf, NumeProf, GradProf }

DISC_SPEC_PROFI { CodDisc, An, Modul, Spec, CodProf}

SALI_EX {An, Modul, Spec, CodDisc, DataEx, SalaEx }

NOTE {Matricol, CodDisc, DataEx, Nota}

Aducerea relaţiilor în 3NF prin grafuri ale DF

Modul în care a fost prezentată transformarea sucesivă a relaţiei universale iniţiale în


1FN, 2NF şi 3NF prin descompuneri succesive are certe valenţe pedagogice şi
aplicabilitate practică. Descompunerea nu este însă singura manieră de normalizare a unei
baze de date relaţionale. Philip A. Bernstein este autorul unui model de normalizare prin
sinteza unor relaţii binare (construite pe baza DF) în relaţii mai mari şi, astfel, aducerea
bazei în 3FN [Bernstein76]. Chris Date reproşează modelului (şi Bernstein acceptă
observaţia) că operaţiunile executate în cadrul algoritmului de sinteză sunt exclusiv de
natură sintactică şi nu ia în considerare latura semantică. Însă exemplul luat de Date
pentru a pune în dificultate algoritmul de sinteză constituie o capcană şi pentru varianta
descompunerii (cel puţin, eu am căzut în ea).

Cu toate acestea, lucrurile pot fi sensibil simplificate utilizănd reprezentarea grafică a DF


prin grafuri şi matrice ale dependenţelor. Ţinând seama că în 3NF relaţiile nu trebuie să
conţină depedenţe parţiale şi tranzitive, se va reprezenta grafic acoperirea minimală.
Pentru majoritatea cazurilor întâlnite în practică, construirea grafului dependenţelor
funcţionale ce alcătuiesc acoperirea minimală, este una din cele mai simple şi la
îndemână modalităţi de aducere a bazei de date în 3NF. Aceasta deoarece dependenţele
parţiale şi tranzitive sunt foarte uşor de identificat şi eliminat. Dintre modalităţile de
reprezentare a depedenţelor funcţionale, cele mai consacrate sunt diagrama, graful şi
matricea DF. În ceea ce mă priveşte, folosesc de ani buni graful DF pe care îl prefer
pentru simplitate şi mai ales expresivitate.

Într-un graf al dependenţelor funcţionale, acestea sunt reprezentate prin săgeţi ce leagă
sursa şi destinaţia. La dependenţele funcţionale simple săgeata uneşte cele două atribute.
Când sursa este compusă, se foloseşte un conector care leagă, în prima instanţă,
atributele-determinant, iar săgeata uneşte acest conector cu atributul destinaţie.

Astfel, pentru baze de date COMENZI, graful DF este reprezentat în figura 5, iar pentru
baza de date EXAMENE în figura 6.
Figura 5. DF tranzitive necanonice

Într-un graf al dependenţelor funcţionale, depedenţele tranzitive, canonice sau necanonice


se observă mult mai lejer.

Figura 6. Graful DF pentru baza de date EXAMENE

Pe baza grafului DF, schema bazei de date poate fi adusă relaţiile direct în 3FN
constituindu-se câte o relaţie pentru fiecare sursă de DF, celelalte atribute fiind toate
destinaţiile respectivei surse. Fireşte atributul sau atributele sursă vor fi cheile primare ale
fiecăreia dintre tabele. Din figura 6 pot fi construite direct relaţiile din finalul paragrafului
precedent.

La tabelele obţinute în acest mod, este necesară uneori adăugarea unei relaţii care conţine
numai cheia primară compusă a relaţiei universale R, aceasta cu precădere în situaţiile în
care cheia primară a relaţiei universale nu apare ca sursă în graf şi, în plus, cheia primară
nu prezintă problema nulităţii vreunuia dintre atributele componente.

Mai trebuie spus că pentru 4FN şi 5FN graful nu prezintă prea mare importanţă, câtă
vreme depedenţele multivaloare şi de joncţiune nu sunt reprezentate, iar pentru BCFN
utilitatea este limitată.

Bibliografie

Bernstein, A.B. - Synthesizing Third Normal Form Relations from Functional


Dependencies, ACM TODS 1, no.4, dec. 1976. Preluare din [Date00], pp. 377-378

[Date00] Date, C.J. - An Introduction to Database Systems, 7th edition, Addison-Wesley,


Reading, Massachussets, 2000
[Heath71] Heath, I.J. - Unacceptable File Operations in a Relational Database,
Proc.1971 ACM SIGFIDET Workshop on Data Description, Access and Control, nov.
1971