1. Modelul relational: tabele, chei, relatii
-- Creare tabele cu PK si FK
CREATE TABLE Clase (
id_clasa INTEGER PRIMARY KEY,
denumire TEXT NOT NULL
);
CREATE TABLE Elevi (
id_elev INTEGER PRIMARY KEY,
nume TEXT NOT NULL,
clasa TEXT,
medie REAL,
id_clasa INTEGER REFERENCES Clase(id_clasa)
);
CREATE TABLE Note (
id_elev INTEGER REFERENCES Elevi(id_elev),
id_materie INTEGER,
nota INTEGER,
PRIMARY KEY (id_elev, id_materie) -- PK compusa
);
PK (Primary Key): identifica unic fiecare rand; nu poate fi NULL, nu poate contine duplicate.
FK (Foreign Key): refera PK-ul altei tabele; asigura integritatea referentiala.
PK compusa: (id_elev, id_materie) impreuna identifica unic fiecare nota.
2. SELECT: filtrare, sortare, grupare
SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT. Functii de agregare: COUNT, SUM, AVG, MIN, MAX.-- 1. Elevi din 12A cu medie > 8, descrescator: SELECT nume, medie FROM Elevi WHERE clasa = '12A' AND medie > 8 ORDER BY medie DESC; -- 2. Media pe clase cu HAVING: SELECT clasa, AVG(medie) AS medie_clasa, COUNT(*) AS nr_elevi FROM Elevi GROUP BY clasa HAVING AVG(medie) > 8;
-- Interogare 1 (12A, medie>8, DESC): Ana Popescu | 9.50 Maria Popa | 8.20 -- Interogare 2 (HAVING AVG>8): 12A | medie_clasa=8.40 | nr_elevi=3 12B | medie_clasa=8.90 | nr_elevi=2
3. JOIN: combinarea datelor din mai multe tabele
-- INNER JOIN: doar elevii cu clasa existenta in Clase SELECT e.nume, c.denumire FROM Elevi e INNER JOIN Clase c ON e.id_clasa = c.id_clasa; -- Output: Ana-12A | Ion-12B (Ioana fara clasa - LIPSA) -- LEFT JOIN: toti elevii, NULL daca clasa nu exista SELECT e.nume, c.denumire FROM Elevi e LEFT JOIN Clase c ON e.id_clasa = c.id_clasa; -- Output: Ana-12A | Ion-12B | Ioana-NULL -- JOIN pe 3 tabele (note >= 9): SELECT e.nume, m.denumire, n.nota FROM Elevi e JOIN Note n ON e.id_elev = n.id_elev JOIN Materii m ON n.id_materie = m.id_materie WHERE n.nota >= 9; -- Output: Ana-Informatica-10 | Ana-Matematica-9
4. Manipularea datelor: INSERT, UPDATE, DELETE
WHERE la UPDATE si DELETE pentru a evita modificarea tuturor randurilor!-- INSERT: adauga un elev nou INSERT INTO Elevi (id_elev, nume, clasa, medie) VALUES (6, 'Elena Mihai', '12A', 8.75); -- UPDATE: modifica media unui elev specific (WHERE obligatoriu!) UPDATE Elevi SET medie = 9.00 WHERE id_elev = 2; -- DELETE: sterge un elev specific DELETE FROM Elevi WHERE id_elev = 5; -- PERICOL: fara WHERE afecteaza TOATE randurile! -- UPDATE Elevi SET medie = 10; <-- NU face asta!
# Inainte UPDATE: Ion Ionescu | medie=7.80 # Dupa UPDATE id_elev=2: Ion Ionescu | medie=9.00 # INSERT verificat (id=6): # 6 | Elena Mihai | 12A | 8.75
5. Subinterogari (subqueries)
= (o valoare), IN (lista de valori), EXISTS (existenta).-- Elevii cu media PESTE media generala:
SELECT nume, medie FROM Elevi
WHERE medie > (SELECT AVG(medie) FROM Elevi);
-- Elevii care au nota la Informatica (IN + subquery):
SELECT nume FROM Elevi WHERE id_elev IN (
SELECT id_elev FROM Note
WHERE id_materie = (
SELECT id_materie FROM Materii
WHERE denumire = 'Informatica'
)
);
# Media generala: 8.42 # Elevi cu medie > 8.42: Ana Popescu | 9.50 Dan Radu | 9.10 # Elevi cu nota la Informatica: Ana Popescu Dan Radu
6. Normalizare: 1NF, 2NF, 3NF
# NENORMALIZAT (incalca 1NF): valori ne-atomice # id | elev | note | clasa # 1 | Ana | 9, 10, 8 | 12A <-- lista in celula! # Dupa 1NF: valori atomice, PK compusa # Note(id_elev, id_materie, nota) PK=(id_elev, id_materie) # Incalcare 2NF: Elevi(id_elev, id_materie, nota, NUME_ELEV) # nume_elev depinde DOAR de id_elev (nu de intreaga PK) # Solutie 2NF: Elevi(id_elev, nume) + Note(id_elev, id_materie, nota) # Incalcare 3NF: Elevi(id_elev, nume, id_clasa, DENUMIRE_CLASA) # denumire_clasa depinde tranzitiv: id_elev->id_clasa->denumire_clasa # Solutie 3NF: Elevi(id_elev, nume, id_clasa) + Clase(id_clasa, denumire)
1NF: valori atomice + fara grupuri repetitive de coloane 2NF: 1NF + fiecare atribut non-cheie depinde de INTREAGA cheie primara 3NF: 2NF + nicio dependenta tranzitiva intre atribute non-cheie