Invatare Atomica

Chei si relatii intre tabele

Cheia primara, indexul, cheia externa si relatia unu-la-mai-multi — cum tii doua tabele legate corect, fara date rupte.

Progres lectie:
0%
🎯

Obiectivul lectiei

Vei intelege de ce fiecare tabel dintr-o baza de date are nevoie de o cheie primara, cum o alegi corect, ce este un index si la ce ajuta, si cum se leaga doua tabele printr-o cheie externa intr-o relatie unu-la-mai-multi, protejata de integritatea referentiala.

Dupa aceasta lectie vei putea:

  • Sa definesti ce este o cheie primara si sa explici de ce orice tabel are nevoie de una
  • Sa alegi corect o cheie primara pentru un tabel dat (cheie naturala vs. AutoNumber)
  • Sa setezi cheia primara a unui tabel in Access, in Vizualizare Proiectare (Design View)
  • Sa explici ce este un index si cand merita adaugat pe un camp
  • Sa identifici cheia externa si relatia unu-la-mai-multi dintre doua tabele
  • Sa activezi integritatea referentiala si sa explici exact ce permite si ce blocheaza ea

Incearca singur!

Provocare — inainte sa citesti:

O firma mica de instalatii tine toate comenzile clientilor intr-un singur tabel Excel: pe fiecare rand scrie din nou numele clientului, adresa si telefonul lui, langa detaliile comenzii respective. Clientul Popescu Ion a facut deja 5 comenzi in acest an — asadar numele, adresa si telefonul lui apar scrise de 5 ori, o data pe fiecare rand.

Intr-o zi, Popescu Ion isi schimba numarul de telefon. Scrieti mai jos: ce probleme poate crea faptul ca datele lui sunt copiate pe 5 randuri diferite, si cum ati organiza voi altfel aceste informatii ca sa nu se mai intample asta?

💡 Ai nevoie de un indiciu?

Ganditi-va la un depozit de piese: daca acelasi furnizor ar avea adresa lui scrisa separat pe fiecare factura in loc de o singura fisa de furnizor la care se face trimitere, o greseala de scriere pe o singura factura ar crea confuzie — care adresa e cea corecta?

Solutia din baze de date este sa tii datele clientului o singura data, intr-un tabel separat, si sa faci legatura cu comenzile lui printr-un numar de identificare. Asta invatam azi.

1

Cheia primara — ce este si de ce e obligatorie

Inainte de definitie, o reamintire rapida: intr-un tabel, fiecare rand este o inregistrare (o intrare completa — de exemplu toate datele unui singur client), iar fiecare coloana este un camp (o singura informatie despre acea inregistrare — de exemplu doar numele, sau doar telefonul).

Cheia primara (Primary Key) este campul (sau combinatia de campuri) dintr-un tabel care identifica in mod unic fiecare inregistrare. Doua reguli obligatorii: valoarea cheii primare nu se poate repeta la doua inregistrari diferite si nu poate ramane necompletata (nu poate fi goala).
Analogie din viata reala:

Codul numeric personal (CNP) identifica fiecare persoana in mod unic — nu exista doi oameni cu acelasi CNP. La fel, codul de bare al unei piese dintr-un depozit identifica exact acea piesa, chiar daca in depozit exista alte piese cu denumire asemanatoare.

De ce conteaza: fara o cheie primara, doua inregistrari ar putea avea exact aceleasi date si nu ai avea cum sa le deosebesti cand vrei sa modifici sau sa stergi doar una dintre ele. In plus, Access foloseste cheia primara ca punct de legatura cand construiesti relatii intre doua tabele — subiectul urmator al acestei lectii.
2

Cum alegi cheia primara

Exista doua strategii pentru a alege o cheie primara: cheie naturala — un camp care exista deja in datele reale si e cu adevarat unic (ex. CNP), sau cheie artificiala (surogat) — un numar generat automat de Access, fara legatura cu continutul, prin tipul de camp AutoNumber (Numerotare automata). In practica, cheia artificiala de tip AutoNumber este cea mai folosita solutie, pentru ca nu depinde de date care s-ar putea totusi repeta sau schimba.
Greseala tipica:

Cineva alege campul Nume ca si cheie primara, crezand ca doi angajati nu vor avea niciodata acelasi nume. Cand apare al doilea "Popescu Ion", Access refuza sa salveze acel rand — nu iti permite sa introduci o valoare care exista deja in campul-cheie, pentru ca ar incalca regula de unicitate.

Comparatie directa:
GRESIT — Nume folosit ca si cheie primara
Nume (cheie primara?)Functie
Popescu IonElectrician
Popescu IonLacatus mecanic

Al doilea rand nu poate fi salvat asa cum e — Access semnaleaza o eroare de valoare duplicata in cheia primara.

CORECT — id_angajat (AutoNumber) ca si cheie primara
id_angajatNumeFunctie
1Popescu IonElectrician
2Popescu IonLacatus mecanic

Acum cei doi angajati coexista fara probleme, pentru ca id_angajat este diferit (1, respectiv 2), chiar daca numele e identic.

Cum setezi cheia primara in Access (pas cu pas):

1. Deschide tabelul in Vizualizare Proiectare (Design View) — clic dreapta pe numele tabelului in panoul din stanga si alege aceasta optiune, sau butonul corespunzator din fila Home/Pornire.
2. Da clic pe randul campului pe care vrei sa il faci cheie primara (ex. id_angajat).
3. Clic dreapta pe bara gri din stanga randului si alege optiunea Cheie primara (Primary Key) din meniul aparut — sau apasa butonul cu pictograma unei chei din grupul de instrumente al filei de proiectare a tabelului.
4. Langa numele campului apare simbolul unei chei mici — semn ca operatia a reusit.
5. Salveaza tabelul (Ctrl+S).

Cand creezi un tabel nou direct in modul Vizualizare Foaie de date (Datasheet View) — ecranul in care vezi tabelul ca un grid cu randuri si coloane, asemanator unei foi de calcul, spre deosebire de Vizualizare Proiectare unde vezi doar structura campurilor — Access adauga automat un camp numit ID, de tip AutoNumber, si il seteaza singur ca si cheie primara — de aceea majoritatea tabelelor din Access au un camp ID la inceput.

3

Indexul — cauta rapid fara sa parcurgi tot tabelul

Un index este o structura interna suplimentara pe care Access o construieste pentru un anumit camp, astfel incat sa poata gasi si sorta rapid dupa acel camp, fara sa parcurga tabelul rand cu rand de la inceput. Cheia primara are automat un index unic; poti adauga indexuri si pe alte campuri, dupa care cauti sau sortezi frecvent.
Analogie din viata reala:

Indexul alfabetic de la finalul unui manual iti spune direct la ce pagina apare un termen — nu citesti toata cartea ca sa il gasesti. Un index de tabel functioneaza la fel: Access "stie" deja unde sa caute, in loc sa verifice fiecare inregistrare pe rand.

Cum adaugi un index in Access:

In Vizualizare Proiectare (Design View), selectezi campul dorit (ex. campul judet dintr-un tabel de Clienti, daca il cauti des) si, in panoul de proprietati de jos, la proprietatea Indexed (Indexat), alegi:

Yes (Duplicates OK) — index simplu, valorile se pot repeta (potrivit pentru un camp precum judet, unde multi clienti pot fi din acelasi judet)
Yes (No Duplicates) — index cu unicitate impusa, ca la cheia primara (potrivit pentru un camp precum CNP, chiar daca nu e el cheia primara aleasa)

De ce nu indexezi orice camp: fiecare index trebuie actualizat de fiecare data cand adaugi sau modifici o inregistrare, ceea ce incetineste usor scrierea datelor noi. De aceea se indexeaza doar campurile dupa care se cauta sau se sorteaza des, nu toate campurile din tabel.
4

Cheia externa — legatura spre alt tabel

O cheie externa (Foreign Key) este un camp dintr-un tabel care contine valoarea cheii primare dintr-un alt tabel, folosit ca sa faca legatura intre cele doua. Spre deosebire de cheia primara, cheia externa se poate repeta — arata la ce inregistrare din celalalt tabel apartine randul curent, nu identifica unic randul in care se afla.
Exemplu concret — o firma cu clienti si comenzi:

Tabelul CLIENTI tine datele fiecarui client o singura data:

id_clientnumetelefon
1Popescu Ion0742 111 222
2Ionescu Maria0745 333 444
3Vasilescu Radu0746 555 666

Tabelul COMENZI tine comenzile, iar campul id_client este cheia externa — arata din CLIENTI cine a facut fiecare comanda, fara sa mai copieze numele si telefonul pe fiecare rand:

id_comandadataid_client (cheie externa)valoare (lei)
10103.03.20261450
10205.03.20261220
10306.03.20262900
10407.03.20263150

Observa ca valoarea 1 apare de doua ori in coloana id_client din COMENZI (comenzile 101 si 102) — asta e permis pentru o cheie externa, pentru ca acelasi client poate avea mai multe comenzi. In schimb, id_comanda ramane unic, pentru ca este cheia primara a tabelului COMENZI.

Atentie la tipul de date al cheii externe: campul id_client din COMENZI NU se creeaza ca AutoNumber, desi id_client din CLIENTI este AutoNumber. In Vizualizare Proiectare a tabelului COMENZI, il creezi cu tipul de date Number (Numar) si proprietatea Field Size (Dimensiune camp) setata pe Long Integer (Numar intreg lung) — este singura combinatie pe care Access o accepta intre o cheie primara AutoNumber si cheia ei externa. Daca lasi id_client tot AutoNumber in COMENZI, campurile nu se mai potrivesc ca tip de date si relatia din pasii urmatori nu se poate crea.

5

Relatia unu-la-mai-multi (1-la-N)

Cand un rand dintr-un tabel (ex. un client) poate corespunde mai multor randuri din alt tabel (ex. mai multe comenzi), dar fiecare rand din al doilea tabel corespunde unui singur rand din primul, spunem ca cele doua tabele sunt legate printr-o relatie unu-la-mai-multi (1-la-N, notata si 1:N). Este cel mai frecvent tip de relatie dintr-o baza de date.
Cum se citeste relatia din exemplul CLIENTI–COMENZI:

Partea "1" = tabelul CLIENTI (un singur client cu id_client = 1: Popescu Ion).
Partea "N" = tabelul COMENZI (Popescu Ion apare de 2 ori ca id_client — comenzile 101 si 102).
Un client poate avea 0, 1 sau mai multe comenzi. O comanda apartine intotdeauna unui singur client — nu are sens ca o comanda sa fie "pe jumatate" a doi clienti diferiti.

Cum creezi relatia in Access (pas cu pas):

1. Deschide fila Database Tools (Instrumente baze de date) din ribbon.
2. Apasa butonul Relationships (Relatii).
3. Daca tabelele CLIENTI si COMENZI nu sunt deja afisate, adauga-le din fereastra care apare (Show Table / Afisare tabel).
4. Cu mouse-ul, trage campul id_client din tabelul CLIENTI peste campul id_client din tabelul COMENZI.
5. Se deschide fereastra Edit Relationships (Editare relatii) — verifici ca cele doua campuri sunt corect asociate.
6. Apasa Create (Creeaza) pentru a salva relatia.

Dupa acest pas, intre cele doua tabele apare o linie subtire in fereastra Relationships — asta arata ca legatura exista, dar inca fara niciun simbol pe ea. Abia dupa ce bifezi Enforce Referential Integrity (pasul urmator, explicat in ATOM 6) linia devine mai groasa la capete si apar cifra "1" langa CLIENTI si semnul infinit "∞" langa COMENZI — asa arata Access vizual relatia 1-la-N confirmata. (Access nu afiseaza niciodata litera "N" pe linie — doar simbolul ∞.)

6

Integritatea referentiala — regula care nu lasa date rupte

Integritatea referentiala (Referential Integrity) este o regula pe care o activezi la crearea relatiei si care impiedica Access sa salveze date incoerente intre cele doua tabele: nu poti adauga in COMENZI o comanda cu un id_client care nu exista in CLIENTI, si nu poti sterge din CLIENTI un client care mai are comenzi legate de el — decat daca stergi mai intai comenzile respective.
Cum o activezi:

La pasul 5 din crearea relatiei (fereastra Edit Relationships), bifezi caseta Enforce Referential Integrity (Impune integritatea referentiala), apoi apesi Create.

Optional, mai apar doua casete: Cascade Update Related Fields (actualizeaza automat id_client-ul in COMENZI daca il modifici in CLIENTI) si Cascade Delete Related Records (sterge automat si comenzile atunci cand stergi clientul). Le bifezi doar daca esti absolut sigur ca vrei acest comportament — in mod normal, pentru comenzi deja facturate, NU vrei ca stergerea unui client sa iti stearga si istoricul comenzilor.

Greseala tipica:

Cineva incearca sa stearga direct din tabelul CLIENTI un client care are deja comenzi, fara sa observe legatura. Daca integritatea referentiala este activata (fara stergere in cascada), Access refuza stergerea si afiseaza o eroare legata de inregistrari asociate in alt tabel. Nu este un bug — este exact protectia care te impiedica sa ramai cu comenzi fara client valid in spate.

De ce conteaza: fara integritate referentiala, o simpla greseala de tastare (id_client = 9 cand clientul 9 nu exista) ar crea o comanda "orfana", pe care nimeni nu ar putea sa o mai lege corect de un client — devizul sau factura acelei comenzi ar deveni imposibil de intocmit corect.
7

Recapitulare si conexiuni

Cheia primara identifica unic fiecare inregistrare dintr-un tabel; indexul face cautarile si sortarile rapide; cheia externa leaga un tabel de altul; relatia unu-la-mai-multi descrie cum un rand "parinte" poate avea mai multe randuri "copil"; iar integritatea referentiala se asigura ca aceasta legatura nu se rupe niciodata prin date incoerente.
Lantul relatiilor din exemplul de azi:

CLIENTI (id_client = cheie primara)
  ↓ legatura prin cheia externa id_client
COMENZI (id_comanda = cheie primara, id_client = cheie externa)
  ↓ protejata de
Integritate referentiala — nicio comanda fara client valid, niciun client sters cat timp mai are comenzi

Conexiune cu urmatoarea lectie:

Acum ca cele doua tabele sunt corect legate, urmatorul pas este sa introduci datele mai usor si mai sigur decat direct in tabel. In lectia urmatoare vei invata cum se creeaza formulare (forms) — ecrane prietenoase de introducere a datelor, construite pe baza tabelelor CLIENTI si COMENZI.

De retinut pentru activitatile practice:

Cheia primara — unica, niciodata goala; de preferat AutoNumber cand nu ai un camp natural sigur unic.
Indexul — viteza la cautare/sortare, doar pe campurile folosite des.
Cheia externa — repeta valoarea cheii primare din alt tabel; se poate repeta ea insasi.
Relatia 1-la-N — "1" langa tabelul parinte, "N" (infinit) langa tabelul copil.
Integritate referentiala — blocheaza comenzi orfane si stergeri care ar lasa date incoerente.

Exercitii practice

Exercitiul 1 (Nivel minim) — Alegerea cheii primare

Un tabel ANGAJATI dintr-un service auto are campurile: Nume, Prenume, Functie, Telefon. Explica de ce niciunul dintre aceste campuri nu este o alegere sigura pentru cheia primara si propune ce camp ar trebui adaugat in tabel, cu ce tip de date, pentru a avea o cheie primara buna.

Vezi rezolvarea

Niciunul din Nume, Prenume, Functie, Telefon nu e sigur ca cheie primara: Nume si Prenume se pot repeta (doi angajati numiti la fel, exact cazul din lectie cu Popescu Ion), Functie se repeta aproape sigur (mai multi electricieni), iar Telefon ar putea fi teoretic unic, dar nu e garantat — un angajat poate sa nu aiba telefon completat inca, iar cheia primara nu poate ramane goala.

Solutia: adaugi campul id_angajat, cu tipul AutoNumber (Numerotare automata) — o cheie artificiala (surogat) generata de Access, care nu depinde de continutul datelor si e mereu unica.

Exercitiul 2 (Nivel standard) — Cheie externa si relatie

Ai doua tabele intr-o baza de date pentru un depozit de piese: PRODUSE (id_produs — cheie primara, denumire, pret) si MISCARI_STOC (id_miscare — cheie primara, id_produs, cantitate, data). Date concrete: in PRODUSE exista id_produs = 10 (Filtru ulei, 35 lei) si id_produs = 20 (Placute frana, 90 lei). In MISCARI_STOC exista trei randuri cu id_produs = 10 si un rand cu id_produs = 20. Identifica: (a) care camp este cheia externa in MISCARI_STOC si spre ce tabel arata, (b) ce tip de relatie exista intre PRODUSE si MISCARI_STOC, argumentand pe baza celor 3 randuri cu id_produs = 10.

Vezi rezolvarea

a) Cheia externa in MISCARI_STOC este campul id_produs — el contine valori care sunt cheia primara din tabelul PRODUSE, deci arata spre PRODUSE.

b) Relatia este unu-la-mai-multi (1-la-N): partea „1” e produsul cu id_produs=10 (Filtru ulei) din PRODUSE, iar partea „N” sunt cele 3 randuri din MISCARI_STOC care au toate id_produs=10 — un singur produs corespunde mai multor miscari de stoc, dar fiecare miscare de stoc apartine unui singur produs (nu are sens ca o miscare sa fie „pe jumatate” a doua produse diferite).

Exercitiul 3 (Nivel performanta) — Integritate referentiala in actiune

La depozitul din exercitiul anterior, integritatea referentiala este activata intre PRODUSE si MISCARI_STOC (fara stergere in cascada). Un coleg incearca sa stearga din PRODUSE inregistrarea cu id_produs = 10 (Filtru ulei), pentru ca produsul nu se mai vinde. Access refuza stergerea si afiseaza o eroare. (a) Explica exact de ce se intampla asta, avand in vedere ca exista 3 randuri in MISCARI_STOC cu id_produs = 10. (b) Propune doua solutii posibile pentru ca produsul sa poata fi totusi eliminat din uz, si spune care dintre ele pastreaza istoricul miscarilor de stoc si care il pierde.

Vezi rezolvarea

a) Integritatea referentiala interzice stergerea unei inregistrari din PRODUSE cat timp mai exista randuri in MISCARI_STOC care se leaga de ea prin cheia externa id_produs — daca Access ar permite stergerea, cele 3 randuri ramase in MISCARI_STOC ar deveni „orfane”, cu un id_produs care nu mai exista nicaieri in PRODUSE.

b) Doua solutii posibile:

  1. Sterge intai cele 3 randuri din MISCARI_STOC, apoi sterge produsul — pierde istoricul miscarilor de stoc pentru acel produs.
  2. Nu stergi produsul, ci adaugi un camp nou de tip Da/Nu (de exemplu Discontinuat) si il bifezi la acel produs, in loc sa il stergi — pastreaza intact tot istoricul din MISCARI_STOC, iar produsul poate fi ascuns din listele curente printr-un filtru pe acest camp.

Ce ai invatat astazi

  • Cheia primara identifica unic fiecare inregistrare — nu se repeta, nu poate fi goala
  • Alegerea cheii: cheie naturala (ex. CNP) sau cheie artificiala AutoNumber; evita campuri precum Nume
  • Setarea cheii primare in Access: Design View → clic dreapta pe camp → Primary Key
  • Indexul face cautarile si sortarile rapide; se aplica doar pe campurile cautate des (Indexed: Yes/No)
  • Cheia externa preia valoarea cheii primare dintr-un alt tabel si poate sa se repete
  • Relatia unu-la-mai-multi (1-la-N): un rand parinte, mai multe randuri copil
  • Relatia se creeaza in Database Tools → Relationships, prin tragerea campului comun
  • Integritatea referentiala blocheaza comenzi/inregistrari orfane si stergerile care le-ar crea

Vrei mai mult?

Provocare: Creeaza tabelele Profesori (id_profesor AutoNumber cheie primara, Nume) si Clase (id_clasa AutoNumber cheie primara, Denumire, id_profesor cheie externa). Leaga-le in Database Tools -> Relationships, bifeaza Enforce Referential Integrity. Apoi incearca doua lucruri si noteaza ce mesaj da Access: (1) adauga in Clase un id_profesor care nu exista in Profesori; (2) sterge un profesor care are deja o clasa legata.

  • De ce crezi: Integritatea referentiala blocheaza ambele actiuni de mai sus, dar Access nu blocheaza deloc doi profesori cu acelasi Nume in tabel. De ce regula de unicitate se aplica strict pe cheia primara (id_profesor), dar nu si pe un camp text obisnuit ca Nume, chiar daca in realitate ar fi util sa nu ai doi profesori identici scrisi la fel?
  • Deschidere: Orice site cu conturi de utilizator foloseste exact acest mecanism: emailul (sau id-ul de cont) e cheie primara la tine, iar orice comanda, postare sau mesaj are o cheie externa spre contul tau. Daca stergi un cont fara integritate referentiala, ramai cu comenzi orfane fara proprietar — genul de bug care sparge rapoartele unui magazin online real.

Urmatoarea lectie

Continua cu Formulare — cum creezi ecrane de introducere a datelor bazate pe tabelele CLIENTI si COMENZI, mai usor de folosit decat editarea directa in tabel.

Continua →