ALTE DOCUMENTE
|
||||
Concepte avansate ale bazelor de date
Modelarea relationala permite modelarea datelor prin cât mai multe tabele. Între aceste tabele trebuie definite relatii .
Mai întâi, putem sa stabilim relatii permanente între tabelele componente ale unei baze de date, Existenta relatiilor asigura integritatea datelor la actualizarile ce se fac în tabelele aflate în relatii, de exemplu modificând codul într-o tabela el este actualizat automat si în celelalte tabele legate prin relatii. De asemenea, extragerea datelor din mai multe tabele (pe baza interogarilor ) are la baza relatiile dintre tabele.
Apoi, se pot defini vederi ale tabelelor cu date , vederi care sunt niste tabele virtuale având anumite câmpuri din tabelele originale. În sfârsit, putem realiza conexiuni de accesare al datele furnizate de alte sisteme, de alte SGBD-uri, la alte tipuri de baze de date .
1. Relatii între tabelele unei baze de date :
Dupa cum s-a vazut la partea de prezentare a modelului relational , modelul relational implica de fapt organizarea datelor în tabele legate între ele prin relatii.
Sa consideram un exemplu tipic de lucru. Fie un tabel produse.dbf ce stocheaza informatiile despre produsele dintr-un magazin si contine mai multe câmpuri printre care un câmp furnizor , ce precizeaza firma de la care s-a achizionat produsul. Sigur, am putea memora acest câmp în tabelul produse . Totusi , se observa ca memorarea întregii denumiri a furnizorului nu este avantajoasa , deoarece pot fi mai multe produse cu acelasi furnizor, consumând în mod inutil memorie. Solutia consta în a folosi 2 tabele, primul tabel produse .dbf pastrând în loc de denumire un cod ( mult mai scurt ), iar al doilea tabel, sa-i spunem furnizori.dbf, va pastra codul împreuna cu denumire (pentru o firma aceasta va aparea o singura data , chiar daca ea furnizeaza mai multe produse ).
Varianta initiala produse.dbf fara relatii între tabelele bazei de date
Denumire produs |
Furnizor |
Cantitate |
|
Faina |
S.C. Import Export Cereale SA Lugoj | ||
Malai |
S.C. Import Export Cereale SA Lugoj | ||
Lapte |
S.C. Lactate SA Deva | ||
Gris |
S.C. Import Export Cereale SA Lugoj |
Varianta cu doua tabele având stabilita o relatie
Tabele produse.dbf
Denum. produs |
CodF |
CodF |
Furnizor |
||||
|
S.C. Import Export Cereale SA Lugoj |
||||||
Malai |
S.C. Lactate SA Deva |
||||||
Lapte | |||||||
Gris |
Dupa cum am vazut în cursul de modele de date exista exista trei tipuri de relatii:
unu-la -unu - adica o înregistrare din tabela parinte este în relatie cu alta din tabela copil.
unu-la -mai-multe- adica o înregistrare din tabela parinte este în relatie cu mai multe din tabela copil. Acest tip de relatie are si o varianta mai-multe-la unu, considerata de unii autori ca un al patrulea tip de relatie.
mai-multe-la -mai-multe- adica o înregistrare din tabela parinte este în relatie cu mai multe din tabela copil, iar o înregistrare din tabel copil este în relatie cu mai multe din cea parinte. 252g69c
În ceea ce priveste Visual Foxpro, aici sunt posibile primele 2 ( sau trei daca consideram si accea varianta) . În schimb relatia 3 (care este cea mai complexa) se poate obtine prin introducerea unei tabele suplimentare între cele doua tabele si folosirea relatiei 2 si a relatiei 2'
Pentru a putea stabili relatii permanete între doua tabele, va trebui sa indexam înainte cele doua tabele astfel :
tabela parinte sa fie indexata cu un index candidat sau primar.
tabela copil sa fie indexata cu orice fel de index ( dupa tipul de index se va stabili de fapt tipul relatiei respective).
În felul acesta vom putea , deocamdata, sa stabilim relatii de tipul unu-la-unu sau unu-la-mai-multe .
Pentru a stabili legatura efectiva între tabele de date, vom deschide baza de date si vom activa Constructorul de baze de date. Presupunând ca s-au creat indecsii corespunzatori, se executa clic simplu pe indexul candidat sau primar care da expresia relatiei parinte si se trage cu mouse-ul peste indexul (de orice tip) care da expresia relatiei din tabela copil, dupa cum se observa în figura de mai jos.
Tipul indexului codf al tabelei parinte furnizori da tipul relatiei : daca este de tip normal sau unic se va stabili o relatie de tipul unu-la-unu.. Daca indexul este de tip candidat sau cheie primara, relatia va fi de tip unu-la-mai-multe ( asa cum este si în exemplul din figura).
Regulile de actualizare a tabelelor legate între ele prin relatii (Integritatea referentiala )
Integritatea referentiala se refera la o multime de reguli impuse tabelelor între care s-au stabilit relatii. Aceste reguli sunt necesare deoarece deseori se doreste modificarea unor date dintr-o tabela, datele acelea afecteaza relatia dintre aceasta tabela si o alta. Daca Visual Foxpro nu ar avea aceste reguli si nu le-ar verifica , legaturile dintre tabele ar fi ineficiente si pâna la urma inutile.
De exemplu, avem relatia anterioara între tabelul parinte furnizori.dbf si tabelul copil produse.dbf. Ele sunt legate în relatie dupa câmpul CodF ce reprezinta codul de identificare al fiecarui furnizor (numele câmpurilor de legatura nu este obligatoriu sa fie acelasi ).Sa consideram urmatoarele situatii care pot sa apara :
un anumit produs nu se mai cauta si prin urmare el nu se va mai pastra în tabela produse .dbf, eventual va trebui sters. În cealalta tabela, avem în schimb un furnizor la care de unde se aduce produsul respectiv. Daca ar fi existat un singur produs furnizat de acelasi furnizor , atunci prin stergerea produsului din tabela copil produse.dbf ar fi presupus si stergerea înregistrarii din tabela furnizori. În schimb, mai ales pe exemplul nostru, daca sunt mai multe produse cu acelasi furnizor, stergerea unui produs nu ar trebui sa duca si la stergerea înregistrarii cu furnizorul respectiv, înregistrare aflata în a doua tabela (ne ramân produse fara furnizori) .
aceeasi situatie anterioara poate sa apara si la modificarea datelor . De exemplu, daca se modifica codul furnizorului , ce se va întâmpla ?
Astfel de situatii pot fi rezolvate (trebuie rezolvate) cu ajutorul integritatii referentiale. Aceasta se aplica în cazul modificarii acelor date dintr-o înregistrare care afecteaza realatia dintre tabele. Exista mai multe evenimentele care conduc la modificari ale cheii de legatura, evenimente tratate de integritatea referentiala :
adaugarea unei înregistrari noi ;
stergerea unei înregistrari;
modificarea datelor unei înregistrari, date care afecteaza relatia.
Pentru fiecare dintre aceste situatii , avem mai multe reguli pe care putem sa le stabilim , ele aplicându-se în aceste situatii.
Pentru cazul adaugarii de noi înregistrari în tabela copil a unei relatii, exista urmatoarele optiuni :
ignorare (Ignore) - adica se permite adaugarea noii înregistrari în tabela copil , indiferent daca exista sau nu o înregistrare corespunzatoare în tabela parinte .
restrictionare (Restrict) - adica sa se genereze o eroare atunci când se încearca adaugarea unei înregistrari în tabela copil, fara a avea corespondent în tabela parinte a relatiei. Situatia aceasta ar aparea daca introducem un nou produs în tabela produse, produs care nu are furnizor în tabela furnizori .
Pentru cazul stergerii unei înregistrari din tabela parinte , integritatea referentiala ne ofera urmatoarele reguli de aplicat:
ignorare (Ignore) - adica se permite stergerea înregistrari în tabela parinte, indiferent daca exista sau nu înregistrari în tabela copil legate de aceasta înregistrare .
restrictionare (Restrict) - adica sa se genereze o eroare si se opreste stergerea, atunci când se încearca steregerea unei înregistrari din tabela parinte la care exista înregistrari corespondente în tabela copil.
stergere în cascada (Cascade) - se sterg automat toate înregistrarile din tabela copil legate de înregistrarea parinte stearsa . De exemplu , daca se renunta la un furnizor se va sterge înregistrarea din tabela parinte si automat toate produsele din tabela copil.
În sfârsit, modificarile unor date din tabela parinte, modificari care sa afecteze relatia dintre tabele, sunt tratate si ele de regulile integritatii referentiale , dupa cum urmeaza :
ignorare (Ignore) - adica se permite modificarea înregistrari în tabela parinte, indiferent daca vor ramâne înregistrari nelegate în tabela copil .
restrictionare (Restrict) - adica sa se genereze o eroare si sa se poreasca modificarea atunci când se încearca modificarea unei înregistrari din tabela parinte , înregistrare ce are corespondent în tabela copil a relatiei.
modificarea în cascada (Cascade) - sunt modificate automat toate înregistrarile din tabela copil conform noii valori a cheii relatiei. De exemplu, daca modificam codul unei furnizor din tabelul furnizori.dbf , automat sa se modifice codul si în tabela produse.dbf , pentru a putea mi departe sa cunoastem furnizorii corecti pentru produse.
Cum se introduc regulile de integritate ? Pentru aceasta, în fereastra Constructorului de baze de date se executa dublu clic pe relatia respectiva (pe linia care leaga tabelele), deschizându-se pe ecran un meniu rapid ca în figura de mai jos:
Din acest meniu se alege comanda Edit Relationship, comanda ce va deschide o alta fereastra de dialog ca în figura urmatoare :
Reguli
pentru actualizare Reguli pentru
adaugare
Dupa ce se fixeaza câmpurile
de legatura, se va alege va apasa butonul Referential Integrity, buton
care va avea ca efect deschiderea unei ferestre în care vom seta regulile:
2. Vederi
Vederile reprezinta un tip special de tabele, un fel de tabele virtuale , construite pe baza datelor din unul sau mai multe tabele sau vederi, legate între ele prin relatii.
Vederile sunt folosite atunci când se doreste o alta structura a tabelelor bazelor de date), structura construita pe baza scheletului unor tabele care exista. Vederile pot contine câmpuri din mai multe tabele sau alte vederi. Vederile sunt incluse în bazele de date , ele neputând fi folosite decât daca baza de date este deschisa. Pentru ca sunt de fapt tabele, vederile sunt tratate si prelucrate ca orice tabel.
Exemplu : Vom considera exemplul anterior în care aveam doua tabele produse.dbf si furnizori.dbf. Daca am avea nevoie de un tabel care sa contina denumire produs, cantitate si denumire furnizor ( nu cod furnizor) ar trebui sa-l cream si sa depunem date acolo. Totusi, datele necesare exista deja în cele doua tabele, dar noi nu dispunem de o tabela care sa contina exact câmpurile amintite : denumirea produsului si cantitatea se gasesc în tabelul produse.dbf iar denumirea furnizorului se gaseste în tabelul furnizori.dbf . Dar, noi avem stabilita o legatura între cele doua tabele. Prin urmare, vom construi o vedere , vedere inclusa în baza de date putând fi folosita ca orice tabel.
În momentul construirii unei vederi , se stabileste o legatura între tabelele sursa si aceasta . Acest lucru are ca efect principal actualizarea automata a datelor din vedere în momentul modificarii datelor din tabelel sursa. În schimb, daca modificam datele din vedere nu totdeauna este posibil sa se actualizeze datele din sursa.. Mai mult, când este posibil, acest lucru se realizeaza prin intermediul unor parametrii ce se precizeaza la construirea vederii.
Pentru a construi vederi se foloseste un constructor special, numit Constructor de vederi. El permite crearea a doua tipuri de vederi : vederi locale si vederi la distanta.. Lansarea lui se face , fie din meniul rapid cu comenzile New Local View sau New Remote View, fie din fereastra de comenzi database Designer. Vederile la distanta se folosesc pentru a accesa date din alte tiprui de tabele decât cele din Visual Foxpro. Mai mult, prin intermediul vederilor la distanta se pot realiza aplicatii client -server ( vom vedea acest lucru la subiectul legat de tehnologiile client-server). Pentru ca vederile se construiesc asemanator cu interogarile ( Query) , le vom rediscuta dupa capitolul de interogari .
3. Tehnici de proiectare a bazelor de date .
Cel mai important lucru pe care îl putem face când începem sa ne construim o noua aplicatie este sa ne proiectam cu grija structura tabelelor . Pe de alta parte, un set de tabele bine proiectat nu numai ca va va rezolva problemele cerute , dar ne va da raspuns la probleme pe care nici nu le anticipati.
Visual Foxpro se bazeaza pe modelul de date relational propus de Codd în 1970. Urmând doar câteva reguli specifice multimilor, el a demonstrat ca putem manevra datele cu usurinta.Tehnica lui a devenit cunoscuta sub numele de normalizarea datelor. Teoria bazelor de date relationale graviteaza în jurul conceptului de utilizare a câmpurilor cheie pentru definirea relatiilor dintre tabele. Cu cât vom avea mai multe tabele, cu cât mai multe relatii sunt cerute de Foxpro pentru a putea conecta si gestiona datele din tabele .
Proiectarea unei tabele implica specificarea structurii sale ( am vazut ca asta înseamna precizarea câmpurilor si a caracteriticilor acestora) dar si a cheilor folosite pentru identificarea datelor . Ideea de baza este aceea de a împarti datele unei baze de date complexe în mai multe tabele simple si stabilirea legaturilor între acestea. Pentru asta se construieste baza de date împreuna cu tabelel aferente si , apoi, se trece la ameliorarea structurii prin aplicarea tehnicii normalizarii tabelelor.
Ce este de fapt normalizarea ? Normalizarea unei baze de date reprezinta procesul de transformare succesiva a unei baze de date relationale în vederea aducerii sale la o forma standard optimizata. Ea se realizeaza în trepte. la fiecare pas, baza de date este trecuta într-o noua forma standard, numita forma normala. procesul de aducere la o anumita forma normala consta, de fapt, în eliminarea unei anumite anomalii, a unei anumite dependente nedorite între date, a unei anumite redundante.
Nu trebuie sa ramânem cu impresia ca normalizarea datelor este o conditie obligatorie în lucrul cu datele organizate relational, ea repezinta un mijloc de optimizare a aplicatiei (prin accesarea optima a datelor ) .
Furnizor.......... ..... ...... .. Nr.ord.registru com................ Nr.înregis.fisc........................ Localitate.......... ..... ...... Judetul.......... ..... ...... ..... Contul.......... ..... ...... ..... Banca.......... ..... ...... ...... |
FacturaSeria FR Nr.444444 |
Cumparator........................... Nr.ord.registru com............... Nr.înregis.fisc........................ Localitate.............................. Judetul.......... ..... ...... .... Contul.......... ..... ...... ..... Banca.......... ..... ...... ...... |
||||||||
Nr.Crt |
Denumirea produselor |
U.M. |
Cantitatea |
Pret unitar (fara TVA) |
Valoarea |
Valoare TVA lei |
||||
Semnatura si stampila |
Date privind expeditia ....... Numele delegatului ....... Mijlocul de transport...... |
Total |
||||||||
Semnatura De primire |
Total de plata |
|||||||||
O factura însoteste actul de vânzare-cumparare a unuia sau mai multor articole (produse sau servicii). Ea este compusa dintr-un antet, care contine date referitoare la actul de vânzare în ansamblul sau (date despre vânzator si cumparator data calendaristica la care se face vânzarea, numarul de înregistrare al facturii, etc) si dintr-o sectiune în care sunt descrise articolele (produsele) ce fac obiectul vânzarii (denumirea, cantitatea si pretul unitar, TVA etc.). Numarul de articole vândute printr-o singura factura difera de la caz la caz, adica este variabil de la o factura la alta.
Vom propune pentru început o structura a bazei de date FACTURI formata dintr-o singura tabela, de urmatoarea forma:
FACTURI |
||||||
Numar factura |
Data |
Seria |
Vânzator (denumire, cod fiscal, cont, banca) |
Cumparator (denumire, cod fiscal, cont, banca) |
Mijloc de transport | |
Observam ca fiecare factura este identificata printr-un cod numeric (numarul facturii), care, pentru a putea fi folosit pe post de cheie primara a tabelei, trebuie sa fie unic în cadrul bazei de date - câmpul a fost subliniat, pentru a pune în evidenta aceasta functie a sa. În structura de mai sus nu a fost detaliata partea referitoare la articolele facturii.
Aducerea bazei de date la prima forma normala FN1
Pentru a trece o baza de date la prima forma normala - FN1 - trebuie eliminate câmpurile compuse (sau neatomice) si cele repetitive. Primul tip de câmpuri amintit (cele compuse) este format din acele câmpuri care reprezinta o concatenare a mai multor valori. În exemplul de mai sus câmpul Vânzator (la fel si Cumparator) reprezinta de fapt o concatenare a mai multor date simple: codul vânzatorului, denumirea, codul sau fiscal, contul si banca.
Câmpul Vânzator , fiind unul compus, se va "sparge" în mai multe câmpuri elementare, dupa cum se vede în figura de mai jos:
FACTURI |
|||||||||
Numar factura |
Data |
Seria |
Cod vânzator |
Denumire vânzator |
Cod fiscal vânzator |
Cont vânzator |
Banca vânzator |
Cod cumparator | |
|
Cel de-al doilea tip de câmpuri care trebuie prelucrate în aceasta etapa (de trecere la prima forma normala) este cel al câmpurilor repetitive. Acestea descriu acelasi tip de entitati, numarul lor fiind însa variabil.
Pentru a pune în evidenta câmpurile repetitive, sa detaliem structura tabelei Facturi, în sectiunea referitoare la articolele facturilor.
FACTURI |
||||||||||
Numar factura |
Articol 1 |
Articol 2 |
Articol 3 |
|||||||
Cod |
Denumire |
Unitate de masura |
Cantitate |
Cod |
Cod | |||||
Observam în structura de mai sus ca într-o înregistrare a tabelei Facturi (în care este memorata complet o singura factura) apar date referitoare la trei articole. Prin urmare, o factura memorata în aceasta baza de date poate contine maximum trei articole, Am putea mari acest numar la, sa zicem, 20. Acum, numarul de articole poate satisface un contabil nepretentios, dar ce se întâmpla daca majoritatea facturilor contin 1 sau 2 articole ? În acest caz, majoritatea înregistrarilor bazei de date vor contine 18 sau 19 articole necompletate, ceea ce constituie o mare risipa de spatiu de memorare.
Câmpurile Articol 1, Articol 2, Articol 3, puse în evidenta în exemplul de mai sus, reprezinta câmpuri repetitive. Ele trebuie eliminate din baza de date, operatie care se face astfel: se introduce în baza de date un singur asemenea câmp. o factura urmând a se întinde acum pe mai multe înregistrari ale tabelei (atâtea înregistrari câte articole are factura) . Pentru a tine evidenta articolelor din cadrul unei facturi, vom introduce în tabela un nou câmp, pe care îl vom denumi Numar articol.
Noua structura a bazei de date Facturi va fi urmatoarea:
FACTURI |
|||||||||
Numar factura |
Data |
Seria |
Cod vânzator |
Denumire vânzator |
Numar articol |
Cod articol |
Denumire articol | ||
Observam în structura de mai sus ca, pentru identificarea unei înregistrari din tabela, se folosesc doua câmpuri : numarul facturii si numarul articolului din cadrul acesteia. Prin urmare, noua cheie a tabelei va fi construita prin concatenarea celor doua câmpuri (subliniate în structura de mai sus).
Aducerea bazei de date la a doua forma normala [FN2]
O data baza de date adusa la prima forma normala, se trece la urmatoarea etapa de optimizare (normalizare), cea de aducere la a doua forma normala - FN2. Aceasta a doua forma a bazei de date se caracterizeaza prin faptul ca nu contine dependente functionale partiale, ceea ce înseamna ca toate câmpurile tabelei depind doar de cheia primara a acesteia (nu de parti ale acesteia).
O data operate schimbarile anterioare, în tabela facturi apar o serie de anomalii ce trebuie eliminate. Sa observam câmpul Data (si alte câmpuri din antetul facturii), care nu depind biunivoc de noua cheie primara a tabelei, formata din câmpurile Numar factura si Numar articol , ci doar de o parte a acesteia, adica de câmpul Numar factura. Acesta este un exemplu de dependenta functionala partiala ce trebuie eliminata din tabela, pentru ca ea sa fie de forma FN2.
Solutia este mutarea câmpurilor care formeaza antetul facturii (care depind doar de Numar factura ) într-o noua tabela, împreuna cu câmpul de care depind (adica Numar factura) . Noile tabele le vom numi ANTET si ARTICOLE, pastrând numele de FACTURI pentru întreaga baza de date.
ARTICOLE
|
|
|||||||||||
Numar factura |
Data |
Seria |
Cod vânzator |
Numar factura |
Numar articol |
Cod articol | ||||||
|
Fiecare factura va fi memorata în baza de date (care acum este compusa din doua tabele) prntr-o singura înregistrare în tabela ANTET si una sau mai multe înregistrari în tabela ARTICOLE (atâtea înregistrari câte articole contine factura). Legatura dintre cele doua tabele este realizata printr-un câmp comun, Numar factura.
Observam, de asemenea, cheile celor doua tabele: Numar factura în tabela ANTET si combinatia Numar factura - Numar articol în tabela ARTICOLE.
Aducerea bazei de date la o treia forma normala (FN3)
A treia forma normala a unei baze de date se remarca prin faptul ca nu contine dependente functionale tranzitive. Aceste dependente se obtin atunci când un câmp X depinde de un alt câmp Y, care, la rândul lui, depinde de un altul Z. În acelasi timp, X depinde si direct de Z. Aceste dependente din cadrul unei tabele trebuie eliminate, în caz contrar putând aparea o serie de anomalii nedorite . Sa luam, de exemplu, câmpul Denumire vânzator, care depinde biunivoc de câmpul Cod Vânzator ( fiecare vânzator, identificat printr-un cod unic, are o denumire unica). La rândul lui , câmpul Cod vânzator depinde biunivoc de câmpul cheie primara al tabelei Antet, adica de câmpul Numar factura. Dar câmpul Denumire vânzator depinde si direct de câmpul Numar factura, deoarece fiecare factura are o singura denumire de vânzator.
Eliminarea acestei dependente se realizeaza prin construirea unei noi tabele folosite la memorarea datelor despre vânzatorii înscrisi pe facturi. Dar cum acceasi situatie se întâlneste si în cazul datelor despre cumparatori, vom construi o tabela mai generala, în care vom introduce toti vânzatorii si cumparatorii, tabela pe care o vom denumi Clienti . În aceasta tabela vom introduce toate câmpurile continând date despre clienti, împreuna cu codul acestora si cu cheia primara a tabelei din care au fost extrase câmpurile (adica Numar factura din tabela Antet ) . În tabela Antet va ramâne câmpul Cod vânzator ( si Cod Cumparator) , pentru a face astfel legatura între cel doua tabele. Prin urmare, vom avea urmatoarea structura a tabelei :
|
CLIENŢI |
|
||||||||||||||||||||||||||||
|
Cod client |
Denumire |
Cod fiscal |
|
||||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||||||
Antet |
Data |
Seria |
Cod vânzator |
Cod cumparat |
|
|||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
|
ARTICOLE |
|||||||||||||||||||||||||||||
|
Numar factura |
Numar articol |
Cod articol | |||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||
Aceeasi problema apare si în cazul produselor din componenta articolelor , care sunt caracterizate de Cod, Denumire si Unitate de masura . Câmpul Denumire depinde de Cod Articol, care , la rândul lui, depinde de cheia primara a tabelei Articole (combinatia dintre Numar, Factura si Numar articol) . Prin urmare vom construi o noua tabela , numita Produse, cu urmatoarea structura.
ANTET |
||
|
CLIENŢI |
||
ARTICOLE |
||
| ||
ANTET |
||
Conchizând , baza de date FACTURI , va contine tabele urmatoare :
ANTET |
|||||
Numar factura |
Data |
Seria |
Cod vânzator |
Cod cumparator |
ARTICOLE |
|||||
Numar factura |
Numar înregistrare |
Cod produs |
Cantitatea |
CLIENŢI |
||||||
Cod client |
Denumire |
Cod fiscal |
Cont |
Banca |
Adresa |
PRODUSE |
||||
Cod produs |
Denumire |
Unitate de masura |
|