Sari la conținut
Atestia
Înapoi la teorie

Teorie

Modelul entitate-relație la atestatul de informatică — entități, relații 1:N și M:N, diagrama E-R

Cum construiești modelul entitate-relație cerut la Subiectul I: entitățile și atributele din enunț, notația

10

minute de citit

14

secțiuni

25

probleme rezolvate legate

Actualizat pe .

Pe această pagină
  1. Notația: #, *, °, Pk, Fk
  2. Pasul 1 — Entitățile și atributele, citite din enunț
  3. Tehnica 1 — Relația 1:N: cheia străină merge în partea „N”
  4. Tehnica 2 — Relația M:N: o entitate de legătură
  5. Tehnica 3 — Relația 1:1: cheie străină unică
  6. Tehnica 4 — Cheia compusă: când numărul singur nu identifică
  7. Tehnica 5 — Relația recursivă: entitatea legată de ea însăși
  8. Ce nu se exprimă prin chei
  9. Pasul 3 — Înregistrările de probă
  10. Atribute opționale și NULL
  11. Pasul 4 — Instrucțiunea SQL
  12. Greșeli care se repetă
  13. Unde exersezi mai departe
  14. Toate problemele din această categorie

La unele județe (Bucureşti, sesiunea 2020), Subiectul I de baze de date nu începe cu CREATE TABLE, ci cu un text despre o firmă — o pizzerie, un spital, o grădină botanică — și o cerință comună tuturor biletelor, în patru pași:

Pas Ce se cere Ce predai
1 entitățile și atributele lor semnificative lista entităților, cu notația # * °
2 relațiile dintre entități, într-o diagramă entitate-relație relațiile cu cardinalitatea lor (1:N, M:N, 1:1)
3 minimum două înregistrări fictive pentru fiecare entitate câte un tabel per entitate
4 instrucțiunea SQL pentru cerința biletului un SELECT, INSERT, UPDATE, DELETE sau ALTER TABLE

Primii trei pași valorează cel puțin cât al patrulea și sunt partea pe care nu o găsești explicată nicăieri pe scurt. Pagina e organizată pe tiparele de relație care apar în cele 25 de subiecte — sunt doar cinci. Odată ce le recunoști, orice text de bilet se modelează în câteva minute.

Notația: #, *, °, Pk, Fk

Rezolvările folosesc notația Oracle — cea în care e scris și SQL-ul de la pasul 4:

Simbol Înseamnă Exemplu
# identificator unic — devine cheia primară (Pk) # id_client
* atribut obligatoriu * nume
° atribut opțional — poate lipsi ° email
Fk cheie străină — coloana care trimite spre cheia primară a altei tabele id_client (Fk) în COMANDA
Uk valoare unică — nu se poate repeta în coloană la relațiile 1:1

Entitatea se scrie la singular și cu majuscule (CLIENT, nu Clienții), atributele cu litere mici.

CLIENT                  COMANDA
# id_client             # nr_comanda
* nume                  * data_comanda
* adresa                * nr_bucati
* telefon               * mod_plata
° email                   id_client (Fk)

Pasul 1 — Entitățile și atributele, citite din enunț

Regula de lucru: substantivele cu date proprii devin entități, adjectivele și cifrele devin atribute, verbele devin relații. „Fiecare client furnizează numele, adresa, numărul de telefon și este identificat printr-un ID” dă direct CLIENT: # id_client, * nume, * adresa, * telefon.

Trei decizii revin la aproape fiecare bilet:

  1. Un atribut stă într-un singur loc. La biroul de traduceri, un traducător cunoaște o singură limbă, deci limba unei traduceri rezultă din traducătorul ei. Pusă și în TRADUCERE, ar putea ajunge să contrazică datele traducătorului.
  2. Un rol nu e o entitate nouă. Managerul unui proiect e tot un angajat (are cod, nume, salariu), deci nu primește tabelă proprie — vezi relația recursivă, mai jos.
  3. Un identificator artificial e mai bun decât unul compus din date. „Nume + dată” identifică un concurs, dar o cheie din două coloane e greu de folosit ca cheie străină; id_concurs rezolvă.

Tehnica 1

Relația 1:N: cheia străină merge în partea „N”

E relația care apare la toate cele 25 de bilete. „Un traducător efectuează mai multe traduceri; la o traducere lucrează un singur traducător” = 1:N. În diagramă: linie simplă la capătul „1” (TRADUCATOR) și „picior de cioară” (trei liniuțe care se desfac) la capătul „N” (TRADUCERE).

Transformarea în tabele are o singură regulă: cheia primară din partea „1” intră, ca cheie străină, în tabela din partea „N”.

TRADUCATOR (1) ──efectuează──< TRADUCERE (N)

TRADUCERE: nr_ordine (Pk), nr_pagini, ..., id_traducator (Fk)

Invers nu se poate: în TRADUCATOR ar trebui o coloană traducere1, traducere2… fără limită.

Cuvintele din enunț care dau cardinalitatea: „un singur”, „exact un”, „aparține unei singure” → partea „1”; „mai multe”, „unul sau mai mulți”, „zero sau mai multe” → partea „N”.

Tehnica 2

Relația M:N: o entitate de legătură

„Un client cumpără mai multe produse, un produs e cumpărat de mai mulți clienți” = M:N. O relație M:N nu se poate pune direct în tabele: oricare parte ai alege pentru cheia străină, ar trebui să țină mai multe valori. Se rezolvă printr-o entitate de legătură, care o desface în două relații 1:N:

CLIENT (1) ──< COMANDA >── (1) PRODUS

COMANDA: nr_comanda (Pk), data, nr_bucati, id_client (Fk1), cod_produs (Fk2)

De multe ori entitatea de legătură există deja în enunț, cu nume propriu: COMANDA, OFERTA, PROGRAMARE, REPREZENTATIE. Când nu există, o inventezi: TEST_INTREBARE, LINIE_COMANDA.

Două variante de cheie primară, ambele corecte:

  • cheie proprie (nr_comanda) — când legătura e un eveniment care se poate repeta (același client comandă același produs de două ori);
  • cheie compusă din cele două chei străine (id_elev + id_proba, marcate Pk,Fk) — când perechea apare o singură dată (un elev are un singur rezultat la o probă).

Atenție la singular și plural: la pizzerie, „la fiecare comandă clientul specifică tipul produsului” — un produs pe comandă, deci COMANDA ajunge. La librăria digitală, o comandă are „una sau mai multe cărți”, deci COMANDA–CARTE e la rândul ei M:N și cere LINIE_COMANDA.

Tehnica 3

Relația 1:1: cheie străină unică

„Un apartament are cel mult un loc de parcare, un loc aparține cel mult unui apartament” = 1:1. Cheia străină se pune în oricare dintre tabele — de obicei în cea în care legătura e opțională — și primește în plus constrângerea de unicitate (Fk,Uk), altfel relația ar redeveni 1:N.

LOC_PARCARE: nr_loc (Pk), zona, id_apartament (Fk,Uk, opțional)

Avantajul se vede la interogare: un loc liber e un loc cu id_apartament gol, deci „câte locuri libere sunt în zona Est” devine un simplu WHERE id_apartament IS NULL. La spital, la fel: un salon cu un singur pat e ocupat dacă un pacient are numărul lui.

Exersează pe subiecte reale

Tehnica 4

Cheia compusă: când numărul singur nu identifică

Camera 101 există și la hotel, și la pensiune; camera 101 există în fiecare cămin. Numărul camerei nu identifică singur camera, deci cheia ei e compusă: unitatea + numărul. Cheia unității e simultan cheie străină și parte din cheia primară (Pk,Fk):

CAMERA: id_unitate (Pk,Fk), nr_camera (Pk), stare, id_tip (Fk)

Consecința pe care o uită toată lumea: tabelele care trimit spre CAMERA au nevoie de ambele coloane — STUDENT primește (nr_camin, nr_camera) ca cheie străină compusă.

Exersează pe subiecte reale

Tehnica 5

Relația recursivă: entitatea legată de ea însăși

„La un proiect lucrează mai mulți angajați, coordonați de un manager” — dar managerul e tot un ANGAJAT. Relația „coordonează” leagă ANGAJAT de ANGAJAT: 1:N, un șef are mai mulți subordonați. În diagramă e o buclă care pleacă din entitate și se întoarce în ea; în tabelă, o cheie străină care trimite spre cheia primară a aceleiași tabele:

ANGAJAT: cod_angajat (Pk), nume, ..., cod_sef (Fk -> cod_angajat, opțional)

cod_sef e opțional (°) — managerul de vârf nu are șef. La interogare, tabela se folosește de două ori, cu două aliasuri (a = angajatul, s = șeful): JOIN ANGAJAT s ON a.cod_sef = s.cod_angajat.

Exersează pe subiecte reale

Ce nu se exprimă prin chei

Unele reguli din enunț nu sunt relații. „O unitate are cel mult 100 de locuri” (suma locurilor din camere) sau „punctajul e între 0 și 10” sunt reguli de business. Cele pe o singură coloană se scriu ca CHECK (punctaj BETWEEN 0 AND 10); cele care adună rânduri se verifică în aplicație sau cu un trigger. Ajunge o propoziție în rezolvare — arată că ai citit enunțul până la capăt.

Exersează pe subiecte reale

Pasul 3 — Înregistrările de probă

Minimum două rânduri pe entitate — o singură înregistrare pe tabel pierde punctajul pasului. Înregistrările nu sunt decor, ci verifică modelul:

  • cheile străine trimit spre rânduri care există — comanda clientului 1230 cere un client 1230 în CLIENT;
  • datele acoperă cerința de la pasul 4. Dacă cerința numără comenzile clientului 1230, pune-i două comenzi și unui alt client una. Interogarea dă atunci un rezultat pe care îl poți verifica de mână și îl poți scrie în rezolvare („rezultatul e 2”);
  • atributele opționale apar o dată goale (—), ca să se vadă că sunt opționale.

Atribute opționale și NULL

Un atribut ° lipsă devine NULL în tabelă. Mai multe cerințe se sprijină exact pe asta: sportivii încă activi au an_retragere gol, locurile libere au id_apartament gol. Testul se scrie IS NULL, niciodată = NULL — comparația cu NULL nu e nici adevărată, nici falsă, deci nu întoarce niciun rând.

La UPDATE pe o coloană care poate fi goală, NULL || ', internet' dă tot NULL: cazul gol se tratează separat, cu CASE WHEN dotari IS NULL THEN ....

Pasul 4 — Instrucțiunea SQL

Instrucțiunea se scrie pe tabelele modelului tău, deci numele de coloane le alegi tu — trebuie doar să fie aceleași ca la pasul 1. Cerințele din cele 25 de bilete sunt scurte; se împart așa:

Cerința Instrucțiunea Tehnica, pe larg
„afișați…”, pe o singură entitate SELECT … WHERE … ORDER BY filtrarea, ordonarea
„câte…”, „valoarea totală…” COUNT(*), SUM funcțiile de agregare
„…pentru fiecare probă / concurs” JOIN + GROUP BY GROUP BY
condiția e pe altă entitate („albumele artistei Andra”) JOIN joncțiunea
„adăugați o traducere” INSERT INTO … (coloane) VALUES (…) inserarea
„ștergeți comenzile din 5 septembrie” DELETE … WHERE UPDATE și DELETE
„adăugați coloana email” ALTER TABLE CLIENTI ADD email VARCHAR2(25) —
SQL
-- conditia pe entitatea "parinte": JOIN, apoi WHERE pe coloana ei
SELECT al.titlu, al.an
FROM ALBUM al
JOIN ARTIST ar ON ar.id_artist = al.id_artist
WHERE ar.nume_scena = 'Andra'
ORDER BY al.an DESC;

Trei detalii de Oracle, pentru că subiectul cere notația Oracle:

  • datele se scriu cu TO_DATE('05.09.2019', 'DD.MM.YYYY'), nu ca text simplu — textul depinde de formatul implicit al serverului;
  • ALTER TABLE … ADD, fără cuvântul COLUMN (acela e MySQL și dă eroare în Oracle);
  • lipirea textelor se face cu ||: a.nume || ' ' || a.prenume.

Greșeli care se repetă

  • M:N desenată ca 1:N — „produsul comandat” pus ca atribut text în CLIENT; un client cu a doua comandă nu mai încape
  • 1:N desenată ca M:N — tabelă de legătură acolo unde enunțul spune „un singur traducător” sau „un angajat nu poate lucra la mai multe proiecte”
  • Cheia străină în partea „1” — traducere1, traducere2… în TRADUCATOR
  • Atributul legăturii pus pe o entitate — punctajul în ELEV, cantitatea în INGREDIENT
  • Tabelă separată pentru un rol (MANAGER) — dublează datele unui angajat
  • Cheie simplă pe un număr care se repetă — camera 101 la două unități
  • O singură înregistrare pe entitate — se cer minimum două
  • Chei străine care trimit spre rânduri inexistente în datele de probă
  • SUM(nr_bucati) când se cer comenzi — dă bucățile, nu comenzile; nicio eroare
  • = NULL în loc de IS NULL — zero rânduri, fără eroare
  • Inconsecvențele enunțului ascunse — atributul adăugat fără o propoziție de explicație

Mai departe

Unde exersezi mai departe

Modelarea se învață pe texte cât mai diferite: ia orice bilet de mai jos, acoperă rezolvarea și scrie pașii 1–3 înainte s-o deschizi. Diferențele dintre modelul tău și cel din rezolvare sunt, aproape mereu, una dintre cele cinci tehnici de pe pagina asta.

Pentru partea de SQL, paginile Interogări SQL pe două tabele și Baze de date şi SQL au fiecare tehnică pe larg, cu greșelile ei.

Toate problemele din această categorie

Fiecare are modelul complet — entități, relații, înregistrări — și instrucțiunea SQL, rulată pe date de probă.

25Arată toate problemele rezolvate25 baze de date