Documente Academic
Documente Profesional
Documente Cultură
BAZE DE DATE 1
ÎN VISUAL FOXPRO
1
Lungu I., Bodea C., Bădescu G., Ioniţă C., Baze de date. Organizare, proiectare şi implementare, Editura ALL, 1995
8
Nivelul conceptual (sau global) este nivelul imediat superior celui fizic, datele fiind privite prin
prisma semanticii lor, punându-se accent pe conţinutul lor efectiv şi pe relaţiile care le leagă de alte date.
Întreaga bază de date este descrisă prin intermediul unui număr restrâns de structuri care, deşi relativ simple,
prin transpunerea la nivel fizic devin extrem de complexe. Toţi utilizatorii îşi exprimă cerinţele de date la
nivel conceptual, prezentându-le administratorului bazei de date, acesta fiind cel care are o viziune globală
asupra organizării bazei concretizată printr-o schemă conceptuală aferentă.
Nivelul extern este ultimul nivel de abstractizare la care poate fi descrisă o bază de date. El este dat de
viziunea programatorului de aplicaţii, care realizează programele de aplicaţii pentru manipularea datelor şi
structura logică (subschema) corespunzătoare descrierii datelor aplicaţiei. Dacă la nivel conceptual baza de
date era abordată în ansamblul ei, în practică, un utilizator sau un grup de utilizatori lucrează numai cu o
porţiune specifică a bazei de date, în funcţie de departamentul în care îşi desfăşoară activitatea şi atribuţiile
sale (lor). Pentru a simplifica interacţiunea utilizator-bază de date se recurge la nivelul extern, în care baza de
date se prezintă sub diferite machete, sub-scheme sau scheme externe specifice necesităţilor fiecăriu
utilizator sau grup de utilizatori.
Sistemul de gestiune al bazei de date reprezintă software-ul propriu-zis al acesteia asigurând
realizarea următoarelor activităţi:
• definirea structurii bazei de date;
• încărcarea datelor în baza de date;
• accesul la date (consultare, interogare);
• întreţinerea bazei de date (colectarea şi refolosirea spaţiilor goale, refacerea bazei de date în
cazul unui incident);
• reorganizarea bazei de date (restructurarea şi modificarea strategiei de acces);
• securitatea datelor.
Aşadar, sistemul de gestiune al bazei de date apare ca un sistem complex de programe care asigură
interfaţa între o bază de date şi utilizatorii acestuia. În acest context, sistemului de gestiune al bazei de date îi
revin o serie de obiective:
• asigurarea independenţei datelor: independenţa datelor trebuie privită din două puncte de
vedere: independenţa fizică a datelor ce face ca memorarea datelor precum şi tehnicile fizice de
memorare să poată fi modificate fără a determina rescrierea programelor de aplicaţie, iar
independenţa logică a datelor ce se referă la posibilitatea adăugării de noi articole de date sau
extinderea structuri conceptuale (globale), fără ca aceasta să impună rescrierea programelor
existente;
• asigurarea unei redundanţe minime şi controlate a datelor din baza de date: memorarea
datelor, în cazul bazelor de date, se face astfel încât fiecare dată să apară o singură dată; totuşi,
nu sunt excluse nici cazurile în care, pentru a realiza performanţe sporite, referitoare la timpul de
acces la date şi răspuns la solicitările uilizatorilor, să se accepte o anumită redundanţă a datelor,
în acest caz însă instituidu-se un control automat în vederea asigurării coerenţei datelor din bază;
• asigurarea unor facilităţi sporite de utilizare a datelor: aceasta presupune:
– folosirea datelor de către mai mulţi utilizatori în diferite scopuri;
– accesul cât mai simplu al utilizatorului la date;
– existenţa unor limbaje performante de regăsire a datelor;
– posibilitatea unui acces multicriterial, fără sortări suplimentare;
– utilizarea unui limbaj cât mai apropiat de limbajul natural, cu posibilitatea exploatării
în mod facil a bazei de date şi de către utilizatorii neinformaticieni;
• sporirea gradului de securitate a datelor împotriva accesului neautorizat la ele;
• asigurarea integrităţii datelor împotriva unor ştergeri intenţionate sau neintenţionate, prin
intermediul unor proceduri de validare, a unor protocoale de control concurent şi a unor
proceduri de refacere a bazei de date după incidente;
9
2
Năstase P., Cosăcescu L., Mihai F., ş.a., Baze de date. Microsoft Access 2002, Editura Teora, 1999
10
entităţii. Putem avea o dependenţă funcţională între identificatorii a două entităţi. O corespondenţă sau
asociere sau relaţie reprezintă o legătură logică între două sau mai multe realizări de entităţii. Rolul unei
entităţi este un nume care desemnează modul de participare al entităţii la o asociere. Identificarea asocierilor
se realizează prin rolurile entităţilor participante deci, concret, cu ajutorul identificatorilor entităţilor
respective. Mulţimea entităţilor care participă la o asociere formează colecţia acesteia, numărul acestora
reprezentând gradul sau dimensiunea asocierii. O corespondenţă între realizări diferite ale aceleeaşi
entităţi se numeşte asociere reflexivă, caz care se recomandă precizarea rolurilor fiecărei entităţi în cadrul
asocierii. O entitate poate participa la mai multe corespondenţe; în acelaşi timp, pot exista mai multe asocieri
între aceleaşi entităţi. Un subansamblu de entităţi ale aceluiaşi tip de entitate formează un subtip al entităţii
respective cu proprietăţi specifice.
În cadrul modelului EA de abstractizare a unui ansamblu de date trebuie să se ţină cont de
următoarele reguli:
• o asociere (relaţie) nu poate exista decât o singură dată între aceleaşi entităţi;
• numele entităţilor, corespondenţele (relaţiilor), rolurilor, atributelor trebuie să fie unice în cadrul
modelului conceptual, iar apoi în baza de date definită.
elementele componente, fie de3finind o proprietate distinctă a domeniului valorilor. Fie D1, D2, ......., Dn
domenii finite, nu neapărat disjuncte. Produsul cartezian D 1 x D2 x ......x Dn al domeniilor D1, D2, ...., Dn este
definit de mulţimea tuplurilor (V1,V2,.....,Vn) , unde V1є D1, …, Vn є Dn. O relaţie R pe mulţimile D1,
D2,....., Dn este o submulţime a produsului cartezian D1 x D2 x ......x Dn, deci o mulţime de tupluri. Relaţia
poate fi definită şi ca o mulţime finită de funcţii R = {f1, f2 ,...., fm} cu fj : {A1, A2,..., An} → D1 ∪ D2
∪ ....... ∪ Dn şi fj (Ai) є Di , în care asociem fiecărui domeniu Di un atribut Ai. Mulţimea numelor atributelor
corespunzătoare unei relaţii o numim schemă relaţională şi o notăm cu R (A1, A2,....., An). Putem reprezinta
o relaţie printr-un tabel bidimensional în care fiecare linie corespunde unui tuplu, iar fiecare coloană unui
domeniu din produsul cartezian, de fapt unui atribut. Numele atributului exprimă de obicei semnificaţia
valorilor din calcul coloanei respective. Numărul atributelor defineşte gradul relaţiei, iar numărul de tupluri
din relaţie defineşte cardinalitatea relaţiei.
Atunci când inserăm tupluri într-o relaţie, de multe ori un atribut este necunoscut sau neaplicabil.
Pentru a reprezenta acest atribut a fost introdusă o valoare convenţională în relaţie, şi anume valoarea null.
În ceea ce priveşte un tabel de tip view (vizualizare, filtru, relaţie virtuală) acesta reprezintă o filtrare a
tabelului iniţial necesară unei anumite abordări, unei anumite aplicaţii. Spunem că un tabel de tip view
reprezintă o relaţie virtuală, deoarece datele pe care le conţine nu sunt în realitate memorate, fiind stocată
numai definiţia vizualizării. Utilizarea vizualizărilor este, în anumite situaţii, avantajoasă, asigurând
securitatea tabelului iniţial, care este astfel protejat de ştergeri, modificări, etc., dar prezintă şi limitări în
prelucrarea datelor.
Operatorii modelului relaţional definesc operaţiile care se pot efectua asupra relaţiilor, în scopul
realizării funcţiilor de prelucrare asupra bazei de date. Modelul relaţional oferă două mulţimi de operatori pe
relaţii şi anume: algebra relaţională şi calculul relaţional. Operatorii algebrei relaţionale sunt fie operatori
tradiţionali pe mulţimi (UNION, INTERSECT, PRODUCT, DIFFERENCE), fie operatori relaţionali
speciali (PROJECT, SELECT, JOIN, DIVISION). Calculul relaţional este de două tipuri : orientat pe tupluri
sau orientat pe domenii, reprezentând o adaptare a calculului predicatelor la domeniul bazelor de date. Pe
baza unor predicate iniţiale, prin aplicarea unor operatori ai calculului cu predicate (conjuncţia, disfuncţia,
4
negaţia, cuantificatorul existenţial şi cel universal) se pot defini noi predicate, noi relaţii. Conform
echivalenţei dintre algebra relaţională şi calculul relaţional demonstrate de Ullmann, orice relaţie posibil de
definit în algebra relaţională poate fi definită şi în cadrul calculului relaţional, şi reciproc.
3 3
Obs. Nu trebuie confundat termenul de relaţie (tabel) cu noţiunea de relaţie (asociere) introdusă în cadrul paragrafului
1.1.1
4
Popescu I., Baze de date relaţionale, Editura Universităţii din Bucureşti, 1996
12
Regulile de integritate sunt aserţiuni pe care datele conţinute în baza de date trebuie să le satisfacă.
Trebuie făcută distincţia între regulile structurale care sunt inerente modelării datelor şi regulile de
funcţionare (comportament) care sunt specifice unei aplicaţii particulare. Există trei tipuri de constâ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 şi care sunt definite în raport cu noţiunea de cheie a unei
relaţii. O mulţime minimală de atribute ale căror valori identifică un tuplu unic într-o relaţie reprezintă o
cheie pentru relaţia respectivă. Fiecare relaţie are cel puţin o cheie de identificare. Dacă există mai multe
chei de identificare, atunci acestea se numesc chei candidat. Una dintre cheile candidat va fi aleasă de către
administratorul bazei de date pentru a identifica efectiv tupluri şi ea va primi numele de cheie primară, iar
celelalte chei candidat vor purta numele de chei alternative sau alternate. Modelul relaţional serveşte la
reprezentarea entităţilor din lumea reală şi a asocierilor dintre acestea. Modelarea asocierilor dintre entităţi
impune recurgerea la conceptul de cheie externă. Aceasta reprezintă un atribut/grup de atribute dintr-o
relaţie R1 ale cărui/căror valori sunt definite pe acelaşi domeniu/aceleaşi domenii ca şi cheia primară a unei
alte relaţii R2 şi care are rolul de a modela asocierea dintre entităţile reprezentate prin relaţiile R1 şi R2. În
acest context, R1 este denumită relaţie care referă, iar R2 poartă numele de relaţie referită.
Cu aceste considerente, cele trei reguli de integritate structurală se referă la :
• unicitatea cheii: cheia primară trebuie să fie unică şi minimală;
• integritatea entităţii: atributele cheii primare trebuie să fie diferite de valoarea null;
• integritatea referirii: o cheie externă trebuie ori să fie null în întregime, ori să corespundă la o
valoare a cheii primare asociate.
Fig. 1.2 Crearea unei baze de date. Definirea structurii unei tabele componente
Memo acest tip de date se foloseşte pentru prelucrarea textelor, adică a şirurilor
de caractere de dimensiuni mari sau variabile, în câmpul de tip „memo”
memorându-se un indicator spre textul salvat într-un fişier distinct de
tipul .FTP (4 octeţi)
Pe lângă aceste caracteristici, pentru tabele incluse într-o bază de date se pot efectua şi următoarele
precizări pentru câmpurile din structura lor:
• pentru fiecare câmp se poate stabili un format implicit de afişare a datelor (Display → Format);
• pentru fiecare câmp în parte se poate stabili o machetă pentru introducerea datelor (Display →
Input Mask);
• se poate stabili un titlu nou pentru fiecare câmp; acesta va apare în antetul vizualizării
conţinutului tabelei (Display → Caption);
• o valoare iniţială implicită pentru fiecare câmp; la adăugării unei noi înregistrări, câmpurile
acesteia vor fi iniţializate cu aceste valori implicite (Field Validation → Default value);
• pentru fiecare câmp se poate impune o regulă de validare a valorilor (Field Validation → Rule)
şi eventual un mesaj care să fie afişat pe ecran în cazul nerespectării condiţiei de validare impuse
(Field Validation → Message); regula de validare la nivel de câmp constă dintr-o expresie
logică, ce va fi evaluată la orice modificare a valorii câmpului respectiv; dacă valoarea rezultată
în urma evaluării expresiei de validare este false, atunci noua valoare a câmpului nu va fi
acceptată şi se va afişa un mesaj de eroare standard sau unul specificat de utilizator.
La nivelul tabelei în ansamblu (figura 1.3), pot fi precizate: o regulă de validare la nivel de
înregistrare (la modificarea unei înregistrări) şi, eventual, un mesaj de eroare, în cazul nerespectării acestei
reguli, precum şi secvenţe de cod care să fie executate la inserarea unei noi înregistrări, la actualizarea
(modificarea) sau la ştergerea uneia existente. Validarea la nivel de înregistrare (Record Validation → Rule)
se declanşează după cea la nivel de câmp, dar înaintea secvenţelor de cod asociate evenimentelor de
manipulare a tabelei.
Adăugarea unei înregistrări, modificarea datelor dintr-o înregistrare existentă precum şi ştergerea unei
înregistrări a tabelei constituie trei evenimente de manipulare a datelor dintr-o tabelă inclusă într-o bază de
date. Pentru fiecare dintre aceste evenimente se poate specifica câte o secvenţă de cod care să fie executată la
apariţia acestuia. Secvenţele de cod asociate evenimentelor de manipulare a unei tabele se declanşează după
validările la nivel de câmp şi la nivel de înregistrare.
Fig. 1.4 Localizarea, în acces direct, a înregistrării ce conţine în nr_leg valoarea 1005
Legarea tabelelor între ele în cadrul modelului relaţional a impus alte două tipuri de indecşi,
cel candidat şi cel cheie:
• indexul candidat în cadrul unei tabele pot exista mai multe câmpuri (sau mai precis mai multe
criterii) care să asigure identificarea unică a înregistrărilor tabelei şi care vor sta la baza definirii
indexilor de acest tip; spre deosebire de indexul unic, cel candidat va împiedeca încărcarea într-o
înregistrare a unor valori care, după evaluarea cheii de indexare, conduc la valori existente în
tabelă;
• indexul de tip cheie primară: se va alege dintre potenţialii indecsi de tip candidat şi va juca un
rol important în legarea tabelelor.
Tipurile de indecşi prezentate (normali, unici, candidaţi şi de tip cheie primară) impun anumite
restricţii de acces, în funcţie de valorile cheii de indexare. Accesul la înregistrările tabelei este din ce în ce
mai restrictiv, în ordinea: indecşi normali, unici, candidat sau de tip cheie primară.
5
Lupulescu M., Muntean M., Dănăiaţă D., Medii de programare, Editura Mirton, Timişoara, 2000
19
Cu ajutorul câmpurilor A şi B, legătura dintre tabelele T1 şi T2 poate fi unul dintre următoarele trei
tipuri:
• 1:1 (one-to-one): unei valori V din câmpul A îi corespunde o unică valoare din câmpul B;
• 1:n (one-to-many): unei valori V din câmpul A îi corespund mai multe valori din câmpul B;
• n:1 (many-to-one): unei valori V din câmpul B îi corespund mai multe valori din câmpul A;
• m:n (many-to-many): unei valori din câmpul A, ce se regăseşte în mai multe înregistrări ale
tabelei T1, îi corespund mai multe valori din câmpul B.
Dintre acestea, în Visual FoxPro sunt implementate doar primele trei tipuri de relaţii. Lipsesc relaţiile
de tipul m:n, deoarece ele se pot reduce la două relaţii, una de tipul n:1 şi alta de tipul 1:n prin intermediul
unor tabele suplimentare intercalate între primele două.
Un alt criteriu de clasificare a relaţiilor dintre tabele este cel al momentului definirii lor. Din acest
punct de vedere există:
• relaţii temporare sau dinamice, care sunt create prin comenzi introduse în programele de
prelucrare, deci sunt disponibile numai la rularea acestora. În afara programelor de prelucrare,
relaţiile respective nu există;
• relaţii permanante, care sunt create automat de sistem la deschiderea bazei de date care conţine
tabelele legate; aceste relaţii sunt disponibile imediat ce este deschisă baza de date, deoarece
sunt memorate în fişierul bazei de date.
La crearea unei relaţii permanente între două tabele este necesară îndeplinirea unor condiţii
prealabile şi anume:
• tabelul primar trebuie să fie indexat cu un index candidat sau primar;
• tabelul referit poate fi indexat cu orice fel de index, de acesta depinzând însă tipul relaţiei
definite.
Condiţia indexării tabelului primar cu un index candidat sau primar determină stabilirea numai a unor
relaţii permanente de tip 1:1 sau 1:n, deoarece acest tip de index împiedică existenţa, în tabelul primar, a
mai multor înregistrări cu aceeaşi valoare a cheii de indexare. Dacă dorim crearea unei relaţii de tip n:1,
aceasta trebuie văzută dinspre tabelul referit înspre tabelul primar. Desigur că prin aceasta se inversează
rolurile primar – referit între tabele. Dacă dorim neapărat ca tabelul primar să-şi păstreze acest rol pentru o
altă relaţie, se poate crea o vedere (view) din cele două tabele legate, vedere care va deveni noul tabel primar
pentru relaţia respectivă.
În esenţă, legătura între două tabele constă într-un cậmp comun ce există în ambele tabele. În felul
acesta se leagă o înregistrare din primul tabel de (prima) înregistrarea corespunzătoare din tabelul referit,
adică legătura se stabileşte pe baza unor valori egale în cậmpul de legătură.
20
6
Muntean M., Baze de date în sisteme informatice, Editura Mirton, Timişoara, 2002
21
Fig. 1.7 Adăugarea unei noi înregistrări în tabela copil a unei relaţii
Ştergerea unei înregistrări din tabelul primar al unei relaţii este de asemenea gestionată prin
intermediul integrităţii referenţiale. În acest caz, avem la dispoziţie următoarele opţiuni:
• ignorare (Ignore) – se permite această ştergere, indiferent dacă în tabelul referit există sau nu
înregistrări legate de înregistrarea primară ştearsă;
• restricţionare (Restrict) – opreşte ştergerea, generând un mesaj de eroare, atunci când există
înregistrări corespunzătoare în tabela referită;
• ştergere în cascadă (Cascade) – se şterg automat toate înregistrările din tabelul referit legate de
înregistrarea primară ştearsă.
Modificarea unor date din tabelul primar, ce afectează relaţia dintre tabele, este de asemenea tratată
prin regulile integrităţii referenţiale în felul următor:
• ignorare (Ignore) – se permit modificările respective, chiar dacă prin aceasta înregistrările
referite corespunzătoare rămân „în aer“, adică fără corespondent în tabelul primar;
• restricţionare (Restrict) – atunci când există înregistrări corespunzătoare în tabela referită,
modificarea este oprită şi este generat un mesaj de eroare;
• modificare în cascadă (Cascade) – sunt modificate automat toate înregistrările din tabelul
referit conform noii valori a cheii relaţiei.
În cadrul bazei de date curent deschise, <bază_de_date> se va crea tabela <tabelă1>. Aceasta va
conţine câmpurile <câmp1>, <câmp2>, ...<câmpn>. Fiecărui câmp i se vor preciza tipul <tip>, lungimea
<lungime> şi dacă este cazul numărul de zecimale <zecimale>.
Pentru ca într-un câmp să poată fi memorată o valoare nulă, se va apela la argumentul NULL din
sintaxa generală a comenzii. Împiedicarea acestui lucru se va face specificând clauza NOT NULL pentru
câmpul respectiv. În absenţa acestor specificări, câmpul se va comporta conform setării curente stabilite prin
comanda SET NULL ON | OFF. Pentru fiecare câmp se poate impune o regulă de validare a valorilor
acestora – CHECK <expl1>. Dacă condiţia <expl1> nu permite existenţa unui câmp necompletat, atunci
adăugarea unei înregistrări vide (de exemplu prin comanda APPEND BLANK) nu va fi posibilă şi va fi
generat un mesaj de eroare. Acest mesaj de eroare poate fi stabilit de către programator prin intermediul
clauzei ERROR <text1> (ERROR <text2>).
De asemenea, pentru fiecare câmp poate fi stabilită o valoare iniţială implicită – DEFAULT <expr2>,
la adăugarea unui noi înregistrări, câmpurile acesteia vor fi iniţializate cu valorile implicite specificate.
Dacă se doreşte definirea unui index de tip cheie primară, atunci se va apela la clauza PRIMARY KEY
în definirea câmpului ale cărui valori vor sta la baza generării indexului. Acesta va avea acelaşi nume ca şi
câmpul.
Se poate defini un index unic pe baza valorilor unui câmp al tabelei (UNIQUE), acesta va face ca
numai prima dintre înregistrările ce conţin aceeaşi valoare a cheii de indexare să fie accesibilă.
Tabela <tabelă1> creată prin comanda CREATE TABLE | DBF poate constitui un tabel referit într-o
relaţie permanentă, al cărei tabel primar se specifică prin <tabelă 2>. Revenind la figura 1.5, câmpul B este
cel căruia i s-a ataşat clauza REFERENCE <tabelă2>, iar câmpul A din tabelul primar, este cel pe baza
valorilor căruia s-a construit indexul <etichetă_index1>. În absenţa clauzei TAG <etichetă_index1> se ia în
considerare indexul de tip cheie primară al tabelului primar <tabelă2>.
Odată cu creerea tabelei <tabelă1> se poate defini şi un index de tip cheie primară al acesteia, ce are
are la bază o combinaţie de câmpuri ale tabelei şi care va asigura identificarea unică a înregistrărilor tabelei.
Cu valorile lui <expr3>, reprezentând combinaţia de câmpuri dorită, se va forma <etichetă_index2>. Clauza
PRIMARY KEY <expr3> TAG <etichetă_index2> nu va putea fi folosită, dacă s-a definit deja un index de
tip cheie primară cu valorile unui câmp (clauza PRIMARY KEY ataşată câmpului respectiv). Reamintim, că
o tabelă poate avea un singur index de tip cheie primară. Clauza UNIQUE <expr4> TAG <etichetă_index3>
crează un index candidat pe baza valorilor lui <expr4>, ce reprezintă un câmp sau o combinaţie de câmpuri
din tabela nou creată. Trebuie menţionat că, câmpul/câmpurile pe baza căruia/cărora s-a construit indexul de
tip cheie primară nu poate/pot apare în <expr4>. De asemenea, o tabelă poate avea mai mulţi indecşi de tip
candidat.
Clauza FOREIGN KEY <expr5> TAG <etichetă_index4> [NODUP] permite definirea unui index
normal (regular) <etichetă_index4>, pe baza valorilor cheii de indexare <expr5>, pentru tabela <tabelă1>,
fiind esenţială în stabilirea unei relaţii de tipul 1:n cu tabela primară <tabelă3>. Dacă se include specificarea
NODUP în clauză, se va creea un index de tip candidat pentru <tabelă1>, ce va constitui tabelul referit din
relaţia stabilită cu tabela primară <tabelă3>. Noua tabelă <tabelă1> poate fi creată şi cu ajutorul unui tablou,
ce conţine numele, tipul, lungimea şi precizia pentru fiecare câmp al tabelei. Conţinutul lui <tablou> va fi
stabilit în prealabil cu ajutorul funcţiei AFIELDS( ).
Considerând situaţia prezentată în figura 1.6, la nivel de comenzi Visual FoxPro, avem următoarele:
Baza de date <conta> conţine tabelele <conturi> şi <operatii>, între care s-a definit o relaţie de
tipul 1:n pe baza valorilor câmpului <simbol> ce apare în ambele tabele. Ambele tabele sunt indexate după
câmpul <simbol>, pentru tabela primară s-a generat o etichetă index de tip cheie primară, iar pentru tabelul
referit s-a creat un index normal (Regular), în conformitate cu tipul relaţiei 1:n.
Odată creată tabela <tabela1>, se poate apela la comenzile COPY STRUCTURE EXTENDED TO şi
CREATE …FROM pentru a crea o nouă tabelă, <tabela2>, cu o structură identică, utilizậnd următoarea
secvenţă de comenzi :
24
USE <tabela1>
COPY STRUCTURE EXTENDED TO <tabelă_structură>
CREATE <tabela2> FROM <tabelă_structură>
Comanda INDEX ON nu permite definirea unui index de tip cheie primară, foarte important în
problemele ce vizează integritatea referenţială a tabelelor legate între ele prin relaţii. Pe baza valorilor lui
<expr>, care poate reprezenta un câmp sau o combinaţie de câmpuri ale tabelei curent deschise, se poate
genera o <etichetă_index>, în cadrul indexului structural ataşat tabelei (.CDX), de tip unic sau candidat.
<câmpA> face parte din structura tabelului primar <tabelă1>, iar valorile sale se vor căuta printre
valorile câmpului <câmpB> din tabela referită <tabelă2>. Pe baza valorilor din <câmpB> s-a definit indexul
<etichetă_indexB>. Cu aceste considerente, se poate defini o relaţie temporară între <tabelă1> şi <tabelă2>
conform grupului de comenzi Visual FoxPro de mai sus. Relaţia dintre cele două tabele funcţionează în
modul următor: mutarea indicatorului de înregistrări din tabelul primar determină evaluarea succesivă a lui
<câmpA>. În funcţie de valorile acestuia, indicatorul de înregistrări al tabelului referit se va plasa pe prima
înregistrare pentru care valoare (<câmpB>) = valoare (<câmpA>).
Exemplificând această metodologie pentru baza de date din figura 1.8, vom obţine următoarea
secvenţă de comenzi :
Nucleul SQL din Visual FoxPro, spre deosebire de alte sisteme de gestiune a bazelor de date
relationale, prevede posibilitatea de ştergere a unui cậmp din structura unei tabele.
Este permisă modificarea tipului oricărui cậmp din structura unei tabele. Dacă cậmpul conţine
valori, se va încerca conversia acestora în conformitate cu noul tip stabilit pentru cậmp. În cazul unei
incompatibilităţi între noul tip şi vechiul tip al cậmpului, informaţia din cậmpul supus modificării de tip se
va pierde. Nu este recomandată modificarea tipului cậmpurilor de tip cheie primară sau candidat.
În ceea ce priveşte lungimea cậmpurilor, acestea pot fi deopotrivă mărite sau micşorate, la
micşorare trebuie avută însă în vedere trunchierea ce operează inevitabil.
8. NULL şi neNULL
Pentru unele atribute poate fi instituită la crearea tabelei obligativitatea valorilor nenule. În timp,
aceasta poate fi modificată într-un sens sau în celălalt.
9. Adăugarea/anularea restricţiilor
Restricţiile de tip cheie primară (PRIMARY KEY), de unicitate (UNIQUE), referenţială (FOREIGN
KEY) şi de comportament (CHECK) pot fi declarate ulterior creării tabelei sau pot fi anulate.
• Stabilirea unei chei primare şi crearea indexului corespunzător
ALTER TABLE <tabelă1>
ADD PRIMARY KEY <expr1> TAG <etichetă_index1>
procedura – frmmain_Activate
open database gest_mat
use stocuri order cod alias stocuri in 1
procedura – cmdInregistrare_Click
mat = val (thisform.cbocod.text)
if thisform.optiongroup1.option1.value = 1
nume_tabela = rtrim(thisform.cbocod.text) + "_Intrari.dbf"
cantitate = "Intrare"
else
nume_tabela = rtrim(thisform.cbocod.text) + "_Iesiri.dbf"
cantitate = "Iesire"
endif
if not file ((nume_tabela))
create table &nume_tabela (cod_mat N(10), data_op D(8) default { / / },;
&cantitate N(10), foreign key cod_mat tag cod_mat references stocuri)
28
use
select 1
seek mat
if not found( )
append blank
replace cod with mat
endif
endif
select 2
use &nume_tabela alias operatii
append blank
replace cod_mat with mat,;
&cantitate with val (thisform.txtcantitate.value),data_op with date( )
select 1
replace stoc with stoc + operatii.&cantitate
use in 2
procedura – cmdQuit_Click
close tables
close databases
thisform.release
29
Dintr-o bază de date necesară unei contabilităţi informatizate fac parte şi tabelele “plan_ctb” şi
“solduri” – figura 1.10, în prima tabelă fiind memorat planul de conturi, iar în cea de-a doua tabelă soldurile
30
iniţiale la începutul exerciţiului contabil. Între cele două tabele se defineşte o relaţie de tipul 1 :1 pe baza
simbolurilor conturilor.
Pentru tabela “plan_ctb” se vor defini validări la nivel de cậmp, iar pentru tabela referită “solduri”
validări la nivel de înregistrare. Acestea din urmă sunt impuse de faptul că, un cont de activ poate avea
numai un sold iniţial debitor, iar un cont de pasiv un sold iniţial creditor.
Condiţia de validare la nivel de cậmp este dată de expresia
tip_cont = “Activ” .or. tip_cont = “Pasiv”,
iar regula impusă la nivelul înregistrărilor tabelei “solduri” este următoarea :
plan_ctb.tip_cont = “Activ” .and. sid >= 0 .and. sic = 0 .or.;
plan_ctb.tip_cont = “Pasiv” .and. sic >= 0 .and. sid = 0
În formularea celei de-a doua condiţii s-a apelat la cậmpul “tip_cont” al tabelei “plan_ctb”, acest
lucru fiind posibil datorită relaţiei existente între cele două tabele.
Fig. 1.12 Efectul regulii de validare definite la nivelul înregistrărilor tabelei “solduri”
procedura – cmdcreare_Click
nr1 = val(thisform.text1.text)
nr2 = val(thisform.text2.text)
nr3 = val(thisform.text3.text)
nr4 = val(thisform.text4.text)
for i = 1 to 4
nr_note = "nr"+ltrim (str(i))
31
nume_tabela = "anul"+ltrim(str(i))
create table &nume_tabela (nr_leg N(10) primary key ;
references date_pers, n1 N(2) check n1>0 and n1<11)
for j = 2 to &nr_note
nume_camp = "n"+ltrim(str(j))
alter table &nume_tabela add column &nume_camp N(2);
check &nume_camp >0 and &nume_camp<11
next j
next i