Biblioteca
Tutora
BibliotecaInformatică și TIC › clasa a X-a

Baze de date

Introducere în conceptele fundamentale ale bazelor de date relaționale și ale limbajului SQL.

Bacalaureat

Concepte generale și modelul relațional

O bază de date este o colecție organizată de date, structurată astfel încât informația să poată fi stocată, căutată și modificată eficient. Programul care o administrează se numește SGBD — Sistem de Gestiune a Bazelor de Date (exemple: MySQL, PostgreSQL, SQLite, Oracle). Distincția cerută la examen: baza de date este colecția de date, SGBD-ul este software-ul care o gestionează — nu sunt sinonime.

În modelul relațional, datele stau în tabele:

Regula de aur a modelului: fiecare celulă conține o singură valoare atomică — nu liste de valori. Dacă un elev are mai multe numere de telefon, ele nu se înghesuie într-o celulă, ci se mută într-un tabel separat.

Avantajele bazelor de date față de fișierele obișnuite: eliminarea redundanței (aceeași informație stocată o singură dată), integritatea datelor impusă prin reguli, accesul concurent al mai multor utilizatori și interogarea printr-un limbaj standard — SQL (Structured Query Language).

Chei primare și chei externe

Cheia primară (primary key) este coloana — sau combinația de coloane — care identifică unic fiecare înregistrare dintr-un tabel. Proprietăți obligatorii: valorile ei sunt unice și nu pot fi NULL. Exemple bune: CNP-ul, un id numeric generat automat. Exemplu prost: numele — două persoane pot avea același nume.

Cheia externă (foreign key) este o coloană dintr-un tabel care face referire la cheia primară a altui tabel, creând legătura dintre ele. În tabelul note, coloana id_elev este cheie externă către tabelul elevi: fiecare notă „știe” al cui e.

Cheia externă impune integritatea referențială: nu poți insera o notă pentru un id_elev care nu există în tabelul elevi și nu poți șterge un elev care are încă note asociate (decât dacă regula de ștergere prevede altceva). Aceasta este plasa de siguranță care împiedică apariția înregistrărilor „orfane”.

Tipurile de relații între tabele:

Confuzia clasică: cheia externă NU trebuie să fie unică — același id_elev apare la toate notele elevului respectiv; unicitatea e proprietatea cheii primare.

Interogarea datelor: SELECT, WHERE, ORDER BY

Instrucțiunea SELECT extrage date dintr-un tabel. Forma de bază:

WHERE filtrează liniile care intră în rezultat: `SELECT * FROM elevi WHERE media >= 9;`. În condiții se folosesc operatorii de comparație (=, <, >, <=, >=, <> pentru diferit), operatorii logici AND, OR, NOT, plus:

ORDER BY sortează rezultatul: `ORDER BY media DESC, nume ASC` — descrescător după medie, iar la egalitate alfabetic după nume. Fără DESC, sortarea este implicit ASC (crescătoare).

Ordinea clauzelor este fixă și se cere ca atare: SELECT ... FROM ... WHERE ... ORDER BY ... — un ORDER BY pus înaintea lui WHERE este eroare de sintaxă.

Modificarea datelor: INSERT, UPDATE, DELETE

Cele trei instrucțiuni care schimbă conținutul tabelelor:

Avertismentul care apare în toate manualele și în viața reală: UPDATE sau DELETE fără clauza WHERE afectează TOATE înregistrările tabelului. `DELETE FROM elevi;` golește tot tabelul — fără confirmare, fără avertisment. Reflexul corect: scrii întâi un SELECT cu aceeași condiție WHERE, verifici ce linii returnează, abia apoi transformi interogarea în UPDATE sau DELETE.

Distincții de vocabular cerute la examen:

La INSERT, valorile de tip text și dată se scriu între apostrofuri, iar încălcarea unei constrângeri (cheie primară duplicată, cheie externă inexistentă) face ca instrucțiunea să fie respinsă de SGBD.

Funcții agregate și gruparea datelor

Funcțiile agregate calculează o singură valoare dintr-o mulțime de linii:

Toate ignoră valorile NULL (cu excepția lui COUNT(*), care numără liniile indiferent de conținut). De aceea AVG(media) pe o coloană cu valori lipsă împarte doar la numărul valorilor existente.

GROUP BY împarte liniile în grupuri și aplică funcțiile agregate pe fiecare grup: `SELECT clasa, AVG(media) FROM elevi GROUP BY clasa;` produce câte o linie pentru fiecare clasă. Regula strictă: în SELECT pot apărea doar coloanele din GROUP BY și funcții agregate — o coloană negrupată și neagregată este o eroare (ce nume ai afișa pentru un grup întreg?).

HAVING filtrează grupurile, după agregare, pe când WHERE filtrează liniile, înainte de grupare — distincția cea mai testată din tot capitolul:

O funcție agregată nu poate apărea în WHERE (la momentul filtrării liniilor, agregatul nu e încă calculat); locul ei de filtrare este exclusiv HAVING. Ordinea completă a clauzelor: SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY.

Interogări pe mai multe tabele: JOIN

Informația reală e împrăștiată în mai multe tabele — elevii într-unul, notele în altul — iar JOIN le recombină pe baza legăturii dintre cheia externă și cheia primară:

`SELECT e.nume, n.nota FROM elevi e JOIN note n ON e.id = n.id_elev;`

Clauza ON spune cum se potrivesc liniile: fiecare notă se lipește de elevul cu id-ul corespunzător. Aliasurile (e, n) scurtează scrierea și devin obligatorii când coloane din tabele diferite poartă același nume.

Tipurile de join cerute la examen:

Capcana fundamentală: un JOIN fără condiția ON (sau cu FROM elevi, note fără WHERE de legătură) produce produsul cartezian — fiecare linie din primul tabel combinată cu fiecare linie din al doilea: 30 de elevi × 200 de note = 6000 de linii fără sens. Dacă rezultatul unei interogări are suspect de multe linii, prima verificare este condiția de join.

Join-urile se pot înlănțui pe mai mult de două tabele, iar la relațiile m:n trecerea se face prin tabelul de legătură: elevi JOIN inscrieri JOIN cursuri.

De reținut

SGBD
Sistem de Gestiune a Bazelor de Date — programul care creează, administrează și interoghează bazele de date; baza de date este colecția de date, SGBD-ul este software-ul
cheie primară
coloana sau combinația de coloane care identifică unic fiecare înregistrare a unui tabel; valorile ei sunt obligatoriu unice și diferite de NULL
cheie externă
coloană care face referire la cheia primară a altui tabel, realizând legătura dintre tabele și impunând integritatea referențială; valorile ei se pot repeta
integritate referențială
regula prin care orice valoare a unei chei externe trebuie să existe drept cheie primară în tabelul referit, împiedicând apariția înregistrărilor orfane
DML și DDL
DML (SELECT, INSERT, UPDATE, DELETE) manipulează datele din tabele; DDL (CREATE, ALTER, DROP) definește și modifică structura tabelelor
WHERE
clauza care filtrează liniile înainte de grupare; nu poate conține funcții agregate — acestea se filtrează cu HAVING, după grupare
GROUP BY
clauza care împarte liniile în grupuri după valorile coloanelor indicate, astfel încât funcțiile agregate să se calculeze separat pe fiecare grup
funcții agregate
COUNT, SUM, AVG, MIN, MAX — funcții care calculează o singură valoare dintr-o mulțime de linii; ignoră valorile NULL, cu excepția lui COUNT(*)
INNER JOIN
operația care combină liniile a două tabele pe baza condiției ON, păstrând doar perechile cu corespondent în ambele tabele
LEFT JOIN
join care păstrează toate liniile tabelului din stânga, completând cu NULL coloanele tabelului din dreapta acolo unde nu există corespondent

Greșeli frecvente

Greșit: Testarea valorilor lipsă cu camp = NULL
Corect: NULL nu este egal cu nimic, nici cu el însuși; singura formă corectă este camp IS NULL, respectiv camp IS NOT NULL
Greșit: Filtrarea cu funcții agregate în WHERE, de exemplu WHERE AVG(media) > 8
Corect: WHERE se evaluează înainte de grupare, când agregatele nu există încă; condițiile pe funcții agregate se scriu în HAVING, după GROUP BY
Greșit: Rularea unui UPDATE sau DELETE fără clauza WHERE
Corect: Fără WHERE, instrucțiunea afectează toate înregistrările tabelului; se verifică întâi condiția printr-un SELECT, apoi se rulează modificarea
Greșit: Impunerea unicității valorilor pentru cheia externă
Corect: Unicitatea este proprietatea cheii primare; cheia externă se repetă firesc — într-o relație 1:n, același id apare la toate înregistrările copil
Greșit: JOIN fără condiția ON de legătură între tabele
Corect: Fără condiția de potrivire se obține produsul cartezian — fiecare linie combinată cu fiecare linie; condiția ON leagă cheia externă de cheia primară referită

Test — 6 întrebări ca la examen

1. Care dintre următoarele afirmații despre cheia primară este adevărată?
  1. poate conține valori NULL dacă sunt rare
  2. identifică unic fiecare înregistrare și nu admite NULL
  3. trebuie să fie obligatoriu de tip numeric
  4. poate avea valori duplicate dacă tabelul e mic
Vezi răspunsul
identifică unic fiecare înregistrare și nu admite NULL. Cheia primară cere simultan unicitate și absența lui NULL — altfel nu ar mai identifica unic înregistrările. Distractorul cu tipul numeric e tentant pentru că id-urile numerice sunt frecvente, dar o cheie primară poate fi și text (de exemplu CNP stocat ca șir).
2. Interogarea SELECT nume FROM elevi WHERE nume LIKE 'M_r%' returnează:
  1. numele care conțin literele M și r oriunde
  2. numele care încep cu M, au exact un caracter oarecare, apoi r, apoi orice
  3. doar numele de exact trei litere care încep cu M
  4. numele care se termină cu r
Vezi răspunsul
numele care încep cu M, au exact un caracter oarecare, apoi r, apoi orice. În șabloanele LIKE, _ ține locul exact unui caracter, iar % oricărei secvențe, inclusiv vide: se potrivesc Mara, Marin, Mirel. Prima variantă ignoră poziționarea impusă de șablon — % și _ nu înseamnă „conține”, ci fixează structura șirului.
3. Diferența dintre WHERE și HAVING este:
  1. WHERE filtrează liniile înainte de grupare, HAVING filtrează grupurile după agregare
  2. sunt interschimbabile, diferă doar sintaxa
  3. HAVING filtrează liniile, WHERE filtrează grupurile
  4. WHERE se folosește doar la UPDATE, HAVING doar la SELECT
Vezi răspunsul
WHERE filtrează liniile înainte de grupare, HAVING filtrează grupurile după agregare. WHERE acționează pe linii individuale, înaintea lui GROUP BY, de aceea nu poate conține funcții agregate; HAVING acționează pe grupurile deja formate și tocmai de aceea acceptă agregate. Varianta c enunță exact inversul — capcana standard a acestei perechi.
4. Tabelul note conține 20 de înregistrări, dintre care 4 au valoarea NULL în coloana nota. Ce returnează SELECT COUNT(*), COUNT(nota) FROM note?
  1. 20 și 20
  2. 16 și 16
  3. 20 și 16
  4. 16 și 20
Vezi răspunsul
20 și 16. COUNT(*) numără toate liniile (20), pe când COUNT(nota) numără doar valorile nenule din coloană (16). Cine crede că cele două forme sunt echivalente alege 20 și 20 — exact diferența de comportament față de NULL pe care o testează întrebarea.
5. Pentru a afișa elevii care NU au nicio notă în tabelul note, interogarea corectă folosește:
  1. INNER JOIN între elevi și note
  2. LEFT JOIN de la elevi la note, cu condiția n.id_elev IS NULL
  3. DELETE FROM note WHERE id_elev IS NULL
  4. GROUP BY id_elev fără HAVING
Vezi răspunsul
LEFT JOIN de la elevi la note, cu condiția n.id_elev IS NULL. LEFT JOIN păstrează toți elevii, iar la cei fără note coloanele din note rămân NULL — condiția IS NULL îi selectează exact pe aceștia. INNER JOIN, distractorul principal, face fix opusul: elimină din rezultat elevii fără corespondent în note.
6. Ce efect are instrucțiunea DELETE FROM elevi; executată fără clauza WHERE?
  1. șterge tabelul elevi, cu structură cu tot
  2. returnează eroare de sintaxă, WHERE fiind obligatoriu
  3. șterge toate înregistrările, dar tabelul gol continuă să existe
  4. șterge doar prima înregistrare din tabel
Vezi răspunsul
șterge toate înregistrările, dar tabelul gol continuă să existe. DELETE fără WHERE afectează toate liniile — sintaxa e perfect validă, ceea ce o face atât de periculoasă — dar structura tabelului rămâne. Ștergerea tabelului însuși, prima variantă, este treaba comenzii DDL DROP TABLE, distincția de vocabular cerută la examen.
Deschide varianta interactivă — cu AI care îți explică
← Structuri de date avansateSisteme de operare →
BiologieChimieEconomieFilosofieFizicăGeografieInformatică și TICIstorieLogică și argumentareMatematicăPsihologieLimba și literatura română