În primul rând, o bază de date este o colecție de date. Aceste date sunt organizate în tabele așa cum se arată în exemplul person. În plus, există multe alte tipuri de obiecte în SGBD: vederi, funcții, proceduri, indici, drepturi și multe altele. Inițial ne concentrăm pe tabele și prezentăm patru dintre ele. Ele servesc drept fundație pentru ghidul nostru. Alte tipuri de obiecte vor fi date ulterior.
Încercăm să păstrăm totul cât mai simplu posibil. Cu toate acestea, acest set minimalist de patru tabele demonstrează o relație 1:n, precum și o relație n:m.
person
Tabelul person conține informații despre persoane fictive.
-- comment lines start with two consecutive minus signs '--'
CREATE TABLE person (
-- define columns (name / type / default value / nullable)
id DECIMAL NOT NULL,
firstname VARCHAR(50) NOT NULL,
lastname VARCHAR(50) NOT NULL,
date_of_birth DATE,
place_of_birth VARCHAR(50),
ssn CHAR(11),
weight DECIMAL DEFAULT 0 NOT NULL,
-- select one of the defined columns as the Primary Key and
-- guess a meaningfull name for the Primary Key constraint: 'person_pk' may be a good choice
CONSTRAINT person_pk PRIMARY KEY (id)
);
contact
Tabelul contact conține informații despre datele de contact ale unor persoane. S-ar putea lua în considerare stocarea acestor informații de contact în coloane suplimentare ale tabelului person: o coloană pentru e-mail, una pentru icq și așa mai departe. Suntem împotriva ei din anumite motive serioase:
- Valori lipsă: Mulți oameni nu au cele mai multe dintre aceste valori de contact, respectiv nu știm valorile. În continuare, tabelul va arăta ca o matrice rarefiată.
- Multiplicități: Alți oameni au mai multe adrese de e-mail sau mai multe numere de telefon. Să definim o mulțime de coloane email_1, email_2, … ? Care este limita superioară? SQL standard nu oferă ceva de genul „matrice de valori” pentru coloane (unele implementări o fac).
- Extensii viitoare: Într-o zi, vor exista unul sau mai multe tipuri de contact necunoscute astăzi. Atunci trebuie să modificăm tabelul.
Putem face față tuturor acestor situații într-un mod necomplicat, când datele de contact merg pe propriul tabel. Singurul lucru special este punerea persoanelor în legătură cu datele lor de contact. Această sarcină va fi gestionată de coloana person_id a lui contact din tabel. Are aceeași valoare ca și cheia primară a persoanei alocate.
Afirmația generală este că avem o unitate de informații (person) căreia îi aparțin potențial multiple unități de informații de același tip (contact). Numim această unitate o relație – în acest caz o relație 1:m (cunoscută și ca relație unu la mulți). Ori de câte ori întâlnim o astfel de situație, stocăm valorile, care pot apărea de mai multe ori, într-un tabel separat împreună cu id-ul primului tabel.
CREATE TABLE contact (
-- define columns (name / type / default value / nullable)
id DECIMAL NOT NULL,
person_id DECIMAL NOT NULL,
-- use a default value, if contact_type is omitted
contact_type VARCHAR(25) DEFAULT 'email' NOT NULL,
contact_value VARCHAR(50) NOT NULL,
-- select one of the defined columns as the Primary Key
CONSTRAINT contact_pk PRIMARY KEY (id),
-- define Foreign Key relation between column person_id and column id of table person
CONSTRAINT contact_fk FOREIGN KEY (person_id) REFERENCES person(id),
-- more constraint(s)
CONSTRAINT contact_check CHECK (contact_type IN ('fixed line', 'mobile', 'email', 'icq', 'skype'))
);
hobby
Oamenii urmăresc de obicei unul sau mai multe hobby-uri. În ceea ce privește multiplicitatea, avem aceleași probleme ca înainte cu contact. Deci avem nevoie de un tabel separat pentru hobby-uri.
CREATE TABLE hobby (
-- define columns (name / type / default value / nullable)
id DECIMAL NOT NULL,
hobbyname VARCHAR(100) NOT NULL,
remark VARCHAR(1000),
-- select one of the defined columns as the Primary Key
CONSTRAINT hobby_pk PRIMARY KEY (id),
-- forbid duplicate recording of a hobby
CONSTRAINT hobby_unique UNIQUE (hobbyname)
);
Poate ați observat că nu există nicio coloană pentru corespondentul person. De ce asta? În ceea ce privește hobby-urile, avem o problemă suplimentară: nu este doar faptul că o persoană urmărește mai multe hobby-uri. În același timp, mai multe persoane urmăresc același hobby.
Numim acest tip de împreunare o relație n:m. Poate fi proiectată prin crearea unui al treilea tabel între cele două tabele originale. Al treilea tabel conține ID-urile primului și celui de-al doilea tabel. Deci cineva poate decide care persoană urmărește ce hobby. În exemplul nostru, acest „tabel-din-mijloc” este person_hobby și va fi definit în continuare.
person_hobby
CREATE TABLE person_hobby (
-- define columns (name / type / default value / nullable)
id DECIMAL NOT NULL,
person_id DECIMAL NOT NULL,
hobby_id DECIMAL NOT NULL,
-- Also this table has its own Primary Key!
CONSTRAINT person_hobby_pk PRIMARY KEY (id),
-- define Foreign Key relation between column person_id and column id of table person
CONSTRAINT person_hobby_fk_1 FOREIGN KEY (person_id) REFERENCES person(id),
-- define Foreign Key relation between column hobby_id and column id of table hobby
CONSTRAINT person_hobby_fk_2 FOREIGN KEY (hobby_id) REFERENCES hobby(id)
);
Fiecare rând al tabelului conține un ID de la person și unul de la hobby. Aceasta este tehnica modului în care informațiile despre persoane și hobby-uri sunt unite.
Vizualizarea structurii
După executarea comenzilor de mai sus, baza de date ar trebui să conțină patru tabele (fără date). Tabelele și relația lor între ele pot fi vizualizate într-o așa-numită diagramă de relație între entități. În partea stângă există relația 1:n dintre person și contact, iar în partea dreaptă relația n:m dintre person și hobby cu al său „tabel-din-mijloc” person_hobby.
(Reprezentarea vizuală a bazei noastre de date din exemplu)
(Include texte din Wikibooks traduse și adaptate de Nicolae Sfetcu)
Lasă un răspuns