Uploaded by miricasilviuconstantin

baze de date curs introductiv

advertisement
Primii pași spre Full-stack
BAZE DE DATE
CURS INTRODUCTIV RAPID
Copyright 2022  Editura L&S SOFT
Toate drepturile asupra acestei lucrǎri aparţin editurii L&S SOFT.
Reproducerea integralǎ sau parţialǎ a textului din aceastǎ carte este
posibilǎ doar cu acordul în scris al editurii L&S SOFT.
ISBN: 978-606-95233-4-6
Materialul este aprobat MEN prin Ordinul nr. 1561/83.
ATENȚIE!
După confirmarea plății, fiecare carte poate fi descărcată de
maximum 5 ori şi este disponibilă spre descărcare 30 de zile.
Fiecare PDF este securizat în 28 de zone cu watermark invizibil
(id comandă, e-mail, nume) pentru a nu putea fi distribuit
pe alte căi virtuale.
Adresa: Aleea Aviației nr. 10, Voluntari, Ilfov
Telefon: 0727.731.947
E-mail: office@infobits.ro
www.infobits.ro
https://ebooks.infobits.ro
CUPRINS
Capitolul 1. Proiectarea bazelor de date
7
1.1. Noţiuni introductive
8
1.2. Normalizarea datelor
22
1.3. Implementarea modelului conceptual
29
1.4. Managementul de proiect
41
Teme de proiect
45
Capitolul 2. Limbajul MySQL
47
2.1. Ce este şi de ce învăţăm MySQL ?
48
2.2. Cum rulăm MySQL pe propriul calculator ?
49
2.3. Crearea unei baze de date
51
2.4. Tabele. Noţiuni elementare
53
2.5. Tipuri de date în MySQL
55
2.6. Operatori utilizaţi în MySQL
59
2.7. Funcţii MySQL
64
2.8. Afişarea coloanelor care rezultă în urma unui calcul
67
2.9. Valoarea NULL
68
2.10. Valori implicite
70
2.11. Cheie primară şi cheie unică
71
2.12. Autoincrementare
73
2.13. Sortarea datelor
74
2.14. Filtrarea datelor
75
6
Baze de date – curs introductiv
2.15. Actualizări într-un tabel
76
2.16. Funcţii agregate
79
2.17. Utilizarea subinterogărilor
80
2.18. Gruparea datelor
82
2.19. Uniuni de tabele
84
2.20. Elemente care privesc securitatea bazelor de date
87
Probleme Propuse
88
Capitolul 3. Limbajul PHP
92
3.1. Introducere
93
3.2. Formulare
95
3.3. Elementul TEXTAREA
99
3.4. Elementul SELECT
100
3.5. Constante. Variabile. Operatori
101
3.6. Instrucţiunile limbajului PHP
105
3.7. Funcţii în PHP
108
3.8. Funcţii “matematice”
111
3.9. Afişarea datelor - echo şi print
112
3.10. Funcţii pentru prelucrarea şirurilor de caractere
113
3.11. Masive în PHP
116
3.12. Variabile cookie
119
3.13. Utilizarea în comun a limbajelor PHP şi MySQL
121
3.14. Aplicaţii
128
3.15. Proiectarea paginilor web
138
Probleme propuse
140
Teme de proiect
142
Anexa 1. Instalarea pachetului EasyPHP
143
Indicaţii / Răspunsuri
154
CAPITOLUL
Proiectarea bazelor de date
În acest prim capitol veţi studia principiile generale ale proiectării
bazelor de date, vă veţi familiariza cu diversele anomalii care pot invalida
bazele de date, precum şi cu modalităţile de evitare ale acestora.
De asemenea, se va defini modelul conceptual al unei baze de date.
În ultima parte a capitolului, vor fi prezentate etapele realizării
unui proiect, avantajele lucrului în echipă şi veţi învăţa cum
să pregătiţi şi să susţineţi o prezentare în faţa publicului.

Ce este modelul conceptual şi care este rolul său ?


Ce este un ERD ?
Ce este o entitate şi cum se reprezintă ea într-un ERD ?


Ce este o instanţă ?
Ce sunt şi cum se stabilesc atributele unei entităţi ?
Cum se stabilesc relaţii între entităţi ?


Ce tipuri de relaţii pot exista între entităţi ?

Cum se reprezintă relaţiile în ERD ?


Normalizarea datelor
Cum se implementează modelul conceptual ?

Managementul de proiect
Cuvinte cheie: dată, informaţie, cunoştinţă, analiză, model
conceptual, entitate, instanţă, atribut, identificator unic, relaţie,
normalizare, mapare, integritate, proiect, echipă, prezentare
8
Baze de date – curs introductiv
1.1. Noţiuni introductive
1.1.1. Date. Informaţii. Cunoştinţe
Auzim adesea vorbindu-se despre “era informaţiilor” sau “societatea
informaţională” sau “tehnologia informaţiei”, însă de multe ori cuvântul "informaţie"
este folosit fără a-i înţelege clar sensul, diferenţa dintre date, informaţii sau
cunoştinţe.
În general, conţinutul gândirii umane operează cu următoarele concepte:

Date – constau în material brut, fapte, simboluri, numere, cuvinte, poze
fără un înţeles de sine stătător, neintegrate într-un context, fără relaţii cu
alte date sau obiecte. Ele se pot obţine în urma unor experimente,
sondaje, etc.

Informaţii – prin prelucrarea datelor şi găsirea relaţiilor dintre acestea
se obţin informaţii care au un înţeles şi sunt integrate într-un context.
Datele, organizate şi prezentate într-un mod sistematic pentru a
sublinia sensul acestora, devin informaţii. Pe scurt, informaţiile sunt
date prelucrate. Informaţiile se prezintă sub formă de rapoarte,
statistici, diagrame, etc.

Cunoştinţe – colecţii de date, informaţii, adevăruri şi principii învăţate,
acumulate de-a lungul timpului. Informaţiile despre un subiect, reţinute
şi înţelese, ce pot fi folosite în luarea de decizii, care pot forma judecăţi
şi opinii, devin cunoştinţe. Cu alte cuvinte, cunoştinţele apar în
momentul utilizării informaţiei.
1.1.2. Colectarea şi analizarea datelor. Modelul conceptual
Primul pas în realizarea unei aplicaţii de baze de date este analiza datelor şi
realizarea unei scheme conceptuale (model conceptual) ale acestora.
În această etapă sunt analizate natura şi modul de utilizare a datelor. Sunt
identificate datele care vor trebui memorate şi procesate, se împart în grupuri
logice şi se identifică relaţiile care există între aceste grupuri.
Analiza datelor este un proces uneori dificil, care necesită mult timp, însă
este o etapă obligatorie. Fără o analiză atentă a datelor şi a modului de utilizare a
acestora, vom realiza o bază de date care, putem constata în final, că nu
întruneşte cerinţele beneficiarului. Ideea de bază a analizei datelor şi a construirii
modelului conceptual este "să măsori de două ori şi să tai o singură dată".
Informaţiile necesare realizării modelului conceptual se obţin folosind
metode convenţionale precum intervievarea oamenilor din cadrul organizaţiei şi
studierea documentelor folosite.
Capitolul 1. Proiectarea bazelor de date
9
Odată obţinute aceste informaţii, ele trebuie reprezentate într-o formă
convenţională care să poată fi uşor înţeleasă de toată lumea. O astfel de
reprezentare este diagrama entităţi-relaţii, numită şi harta relaţiilor sau ERD-ul
(Entity Relationship Diagram). Aceste scheme sunt un instrument util care uşurează
comunicarea între specialiştii care proiectează bazele de date şi programatori, pe de
o parte şi beneficiari, pe de altă parte. Aceştia din urmă pot înţelege cu uşurinţă o
astfel de schemă, chiar dacă nu sunt cunoscători în domeniul IT.
În cele ce urmează, vom prezenta principalele elemente care intră în
componenţa unui ERD precum şi convenţiile de reprezentare a acestora.
1.1.3. Entităţi. Instanţe. Atribute. Identificator unic
O entitate este un lucru, obiect, persoană sau eveniment care are
semnificaţie pentru afacerea modelată, despre care trebuie să colectăm şi să
memorăm date. O entitate poate fi un lucru real, tangibil precum o clădire, o
persoană, poate fi o activitate precum o programare sau o operaţie sau poate fi o
noţiune abstractă.
O entitate este reprezentată în ERD printr-un dreptunghi cu colţurile
rotunjite. Numele entităţii este întotdeauna un substantiv la singular şi se scrie în
partea de sus a dreptunghiului cu majuscule, ca în Fig. 1.1:
PROFESOR
PACIENT
ELEV
Figura 1.1. Exemple de entităţi şi modul de reprezentare
O entitate este de fapt o clasă de obiecte şi pentru orice entitate există mai
multe instanţe ale sale. O instanţă a unei entităţi este un obiect, o persoană, un
eveniment particular din clasa de obiecte care formează entitatea. De exemplu,
elevul X din clasa a IX-a A de la Liceul de Informatică din localitatea Y este o
instanţă a entităţii ELEV.
După cum se vede, pentru a preciza o instanţă a unei entităţi, trebuie să
specificăm unele caracteristici ale acestui obiect, să-l descriem (să precizăm de
exemplu numele, clasa, şcoala, etc.). Aşadar, după ce am identificat entităţile
trebuie să descriem aceste entităţi în termeni reali, adică să le stabilim atributele.
Un atribut este orice detaliu care serveşte la identificarea, clasificarea,
cuantificarea, sau exprimarea stării unei instanţe a unei entităţi. Atributele sunt
informaţii specifice ce trebuie cunoscute şi memorate.
De exemplu, atributele entităţii ELEV sunt numele, prenumele, adresa,
numărul de telefon, adresa de e-mail, data naşterii, etc.
10
Baze de date – curs introductiv
În cadrul unui ERD, atributele se vor scrie imediat
sub numele entităţii, cu litere mici. Un atribut este un
substantiv la singular (vezi Fig. 1.2).
Figura 1.2. Exemplu
de entitate
ELEV
#
*
*
*
*
○
○
cnp
nume
prenume
data_nasterii
adresa
telefon
e-mail
Un atribut poate fi obligatoriu sau opţional. Dacă un atribut este
obligatoriu, pentru fiecare instanţă a entităţii respective trebuie să avem o valoare
pentru acel atribut: de exemplu, este obligatoriu să cunoaştem numele elevilor.
Pentru un atribut opţional putem avea instanţe pentru care nu cunoaştem valoarea
atributului respectiv. De exemplu, atributul ”e-mail” al entităţii ELEV este opţional,
un elev putând să nu aibă adresă de email. Un atribut obligatoriu este precedat în
ERD de un asterisc ”*”, iar un atribut opţional va fi precedat de un cerculeţ ”o”.
Atributele care definesc în mod unic instanţele unei entităţi se numesc
identificatori unici (UID). UID-ul unei entităţi poate fi compus dintr-un singur atribut,
precum codul numeric personal ce poate fi un identificator unic pentru entitatea ELEV.
În alte situaţii, identificatorul unic este compus dintr-o combinaţie de două sau mai
multe atribute. De exemplu, combinaţia dintre titlu, numele autorului şi data apariţiei
poate forma unicul identificator al entităţii CARTE. Oare combinaţia titlu şi nume autor
nu era suficientă? Răspunsul este NU, deoarece pot exista mai multe volume scrise de
Mihai Eminescu având toate titlul ”Poezii”, dar apărute la date diferite.
Atributele care fac parte din identificatorul unic al
unei entităţi vor fi precedate de semnul diez ”#” (vezi
Fig. 1.2 şi Fig. 1.3).
Figura 1.3. Alt exemplu
de entitate
CARTE
#
#
#
*
*
titlu
autor
data_aparitiei
format
numar_pagini
Observaţie ! Atributele din UID sunt întotdeauna obligatorii, însă semnul ”#” este
suficient, nu mai trebuie pus şi un semn asterisc în faţa acestor atribute.
Valorile unor atribute se pot modifica foarte des, ca de exemplu atributul
vârstă. Spunem, în acest caz, că avem de a face cu un atribut volatil. Dacă
valoarea unui atribut însă se modifică foarte rar sau deloc (de exemplu data
naşterii) acesta este un atribut non-volatil. Evident este de preferat să folosim
atribute non-volatile atunci când acest lucru este posibil.
Capitolul 1. Proiectarea bazelor de date
11
Identificaţi entităţile pentru următoarele scenarii. Identificaţi apoi pentru
fiecare entitate atributele sale, stabiliţi opţionalitatea acestora şi precizaţi unicul
identificator al fiecărei entităţi.
Indicaţie. Subliniaţi substantivele care au semnificaţie pentru afacerea descrisă.
Un substantiv va fi subliniat doar la prima sa apariţie. Dintre aceste substantive veţi
alege apoi entităţile.
1. Pentru a se abona la diverse reviste, persoanele doritoare trebuie să
furnizeze numele, adresa şi un număr de telefon. Fiecare revistă este identificată
prin titlu, numărul volumului şi data apariţiei. Abonaţii semnează pentru abonare un
contract pe o anumită perioadă de timp specificată prin data de început a
abonamentului şi data finală. Bineînţeles că o persoană se poate abona la mai
multe reviste în acelaşi timp.
2. Despre angajaţii unei firme se cunoaşte numele, titlul, numărul de telefon
de la birou. Angajaţii pot fi implicaţi într-o serie de proiecte ce se desfăşoară în
cadrul firmei. Despre fiecare proiect se cunoaşte numele, data la care a demarat
proiectul şi se poate cunoaşte o dată la care se va finaliza proiectul. La fiecare
proiect lucrează un singur angajat, însă un angajat poate fi implicat în mai multe
proiecte. Fiecare angajat are un manager, cu excepţia directorului. Managerii pot fi
şi ei implicaţi în proiecte.
1.1.4. Relaţii între entităţi
În lumea reală, obiectele nu există izolat. Percepem obiectele din lumea
reală doar în conexiune cu alte obiecte, de exemplu vom spune 'pământul se
învârte în jurul soarelui', 'el este medic', etc.
Aşadar, după ce aţi identificat care sunt entităţile şi atributele acestor entităţi,
este timpul să punem în evidenţă relaţiile care există între aceste entităţi, modul în
care acestea comunică între ele. O relaţie este o asociere, legătură sau conexiune
existentă între entităţi şi care are o semnificaţie pentru afacerea modelată.
Orice relaţie este bidirecţională, legând două entităţi sau o entitate cu ea însăşi.
De exemplu, elevii studiază mai multe materii, o materie e studiată de către elevi.
Orice relaţie este caracterizată de următoarele elemente:
-
numele relaţiei;
-
opţionalitatea relaţiei;
-
gradul (cardinalitatea) relaţiei.
12
Baze de date – curs introductiv
Să luăm ca exemplu relaţia existentă între entităţile JUCĂTOR şi ECHIPĂ.
Vom spune:
Un JUCĂTOR joacă într-o ECHIPĂ.
Numele relaţiei este: joacă.
Pentru a stabili opţionalitatea relaţiei trebuie să răspundem la următoarele
întrebări: un jucător trebuie să joace într-o echipă? Se poate ca un jucător să nu
joace în nicio echipă?
Dacă acceptăm faptul că toţi jucătorii trebuie să joace într-o echipă, relaţia
este obligatorie sau mandatorie şi vom spune că:
Un JUCĂTOR trebuie să joace într-o ECHIPĂ.
Dacă însă acceptăm că există jucători care nu joacă în nicio echipă (de
exemplu, li s-a terminat contractul şi în momentul de faţă nu mai joacă la nicio
echipă), atunci relaţia este opţională. În acest caz, vom spune că:
Un JUCĂTOR poate juca la o ECHIPĂ.
Cardinalitatea relaţiei este dată de numărul de instanţe ale entităţii din
partea dreaptă a relaţiei care pot intra în relaţie cu o instanţă a entităţii din partea
stângă a relaţiei. Adică va trebui să răspundem la întrebări de genul: la câte echipe
poate juca un jucător? Răspunsurile posibile sunt unul şi numai unul sau unul
sau mai mulţi. Vom spune:
Un JUCĂTOR trebuie/poate să joace la o ECHIPĂ şi numai una.
sau
Un JUCĂTOR trebuie/poate să joace la una sau mai multe ECHIPE.
Cea mai realistă variantă a relaţiei dintre JUCĂTOR şi ECHIPĂ este aşadar:
Un JUCĂTOR poate să joace la o ECHIPĂ şi numai una.
Am precizat însă mai înainte că orice relaţie este bidirecţională. Relaţia
dintre ECHIPĂ şi JUCĂTOR o putem enunţa astfel:
La o ECHIPĂ trebuie să joace unul sau mai mulţi JUCĂTORI.
1.1.4.1. Convenţii de reprezentare a relaţiilor
În cadrul diagramei entităţi-relaţii, o relaţie va fi reprezentată printr-o linie ce
uneşte cele două entităţi. Deoarece o relaţie este bidirecţională, linia ce uneşte cele
două entităţi este compusă din două segmente distincte, câte unul pentru fiecare
entitate. Tipul segmentului ce pleacă de la o entitate ne va indica opţionalitatea
relaţiei dintre această entitate şi entitatea aflată în cealaltă parte a relaţiei. Dacă
acest segment este continuu este vorba de o relaţie obligatorie, o linie întreruptă
indică o relaţie opţională.
Capitolul 1. Proiectarea bazelor de date
13
De exemplu, în Fig. 1.4 segmentul ce pleacă de la entitatea JUCĂTOR, fiind
întrerupt, înseamnă că un jucător poate juca la o echipă, adică relaţia este
opţională. Segmentul ce pleacă dinspre entitatea ECHIPĂ este continuu, deci la o
echipă trebuie să joace jucători.
Figura 1.4. Reprezentarea relaţiilor
Modul în care o linie se termină spre o entitate este important. Dacă se
termină printr-o linie simplă, înseamnă că o instanţă şi numai una a acestei entităţi
este în relaţie cu o instanţă a celeilalte entităţi. În exemplul anterior, linia de la
JUCATOR la ECHIPA se termină în partea dinspre ECHIPA cu o linie simplă, deci
un jucător joacă la o echipă şi numai una.
Dacă linia se termină cu trei linii (picior de cioară), înseamnă că mai multe
instanţe ale entităţii pot corespunde unei instanţe a celeilalte entităţi. În exemplul
anterior, linia de la ECHIPĂ la JUCĂTOR se termină cu piciorul de cioară,
înseamnă că unei instanţe a entităţii ECHIPĂ îi corespund mai multe instanţe ale
entităţii JUCĂTOR, adică o echipă are unul sau mai mulţi jucători.
Caracteristica relaţiei
Valoare
Mod de reprezentare
Numele relaţiei
un verb
se scrie deasupra relaţiei
linie continuă
Opţionalitatea
relaţie obligatorie
(TREBUIE)
relaţie opţională
(POATE)
una şi numai una
Cardinalitatea
linie întreruptă
linie simplă
picior de cioară
una sau mai multe
Tabelul 1.1. Moduri de reprezentare a unei relaţii
1.1.4.2. Tipuri de relaţii
Variantele de relaţii ce pot exista între două entităţi sunt prezentate mai jos:
-
relaţii one-to-one – acest tip de relaţie este destul de rar întâlnit –
uneori, astfel de relaţii pot fi modelate transformând una dintre entităţi
în atribut al celeilalte entităţi.
-
relaţii one-to-many – sunt cele mai întâlnite tipuri de relaţii, însă şi aici,
cazurile c) şi d) prezentate în Fig. 1.6, sunt mai puţin uzuale;
14
Baze de date – curs introductiv
Figura 1.5. Exemple de relaţii one-to-one
Figura 1.6. Exemple de relaţii one-to-many
-
relaţii many-to-many – aceste tipuri de relaţii apar în prima fază a
proiectării bazei de date, însă ele trebuie să fie ulterior eliminate. Fig. 1.7
prezintă câteva exemple de astfel de relaţii.
Figura 1.7. Exemple de relaţii many-to-many
Capitolul 1. Proiectarea bazelor de date
15
1.1.5. Rezolvarea relaţiilor many-to-many
După cum am precizat anterior, relaţiile many-to-many pot apărea într-o
primă fază a proiectării bazei de date, însă ele nu au voie să apară în schema finală.
Să considerăm relaţia dintre entităţile STUDENT şi CURS (vezi Fig. 1.8). Se
ştie că orice curs se termină în general cu un examen. Unde vom memora nota
studentului la fiecare examen?
Figura 1.8. Exemplu de relaţie many-to-many
Dacă încercăm să introducem atributul nota la entitatea STUDENT, nu vom
şti cărei materii îi corespunde acea notă, întrucât unei instanţe a entităţii STUDENT
îi corespund mai multe instanţe ale entităţii CURS. Invers, dacă încercăm să
memorăm nota în cadrul entităţii CURS, nu vom şti cărui student îi aparţine acea
notă.
Rezolvarea unei relaţii many-to-many constă introducerea unei noi entităţi
numită entitate de intersecţie, pe care o legăm de entităţile originale prin câte o
relaţie one-to-many.
Paşii în rezolvarea unei relaţii many-to-many sunt următorii:

se găseşte entitatea de intersecţie - pentru exemplul nostru, vom introduce
entitatea INSCRIERE:
Figura 1.9. Rezolvarea relaţiilor many-to-many, pasul 1
16

Baze de date – curs introductiv
crearea noilor relaţii:
o
opţionalitatea: relaţiile care pleacă din entitatea de intersecţie sunt
întotdeauna obligatorii în această parte. În partea dinspre entităţile
originale, relaţiile vor păstra opţionalitatea relaţiilor iniţiale.
o
cardinalitatea: ambele relaţii sunt de tip one-to-many, iar partea cu
many va fi întotdeauna înspre entitatea de intersecţie.
o
numele noilor relaţii:
Figura 1.10. Rezolvarea relaţiilor many-to-many, pasul 2

adăugarea de atribute în cadrul entităţii de intersecţie, dacă acestea există.
În exemplul nostru ne poate interesa, să spunem, data la care s-a înscris un
student la un curs, data la care a finalizat cursul, precum şi nota obţinută la
sfârşitul cursului.
Figura 1.11. Rezolvarea relaţiilor many-to-many, pasul 3
Capitolul 1. Proiectarea bazelor de date

17
stabilirea identificatorului unic pentru entitatea de intersecţie: dacă entitatea
de intersecţie nu are un identificator unic propriu, atunci acesta se poate
forma din identificatorii unici ai entităţilor iniţiale, la care putem adăuga
atribute ale entităţii de intersecţie.
În exemplul nostru, identificatorul unic al entităţii de intersecţie este format
din id-ul studentului, id-ul cursului şi data înscrierii la curs.
Faptul că identificatorul unic al unei entităţi preia identificatorul unic din altă
entitate cu care este legată este reprezentat grafic prin bararea relaţiei
respective, înspre entitatea care preia UID-ul celeilalte entităţi:
Figura 1.12. Rezolvarea relaţiilor many-to-many, pasul 4
1. O bază de date va memora orarul unei universităţi. Fiecare curs este parte a
unui modul, iar fiecărui curs îi este asociat exact un profesor. La fiecare curs
participă mai mulţi studenţi.
Fiecare poziţie din orar corespunde unei zile a săptămânii şi unei anumite
ore. Fiecare poziţie din orar durează exact o oră, dar uneori un curs poate dura mai
multe ore consecutive, însă nici un curs nu poate apărea în zile diferite sau la ore
diferite neconsecutive ale aceleiaşi zile.
Fiecare profesor şi fiecare student pot avea mai multe ore de curs la care
participă în decursul unei săptămâni.
18
Baze de date – curs introductiv
Care dintre următoarele variante NU este o soluţie posibilă a acestei probleme ?
a) Se stabileşte o relaţie one-to-many între CURS şi POZITIE_ORAR;
b) Se stabileşte o relaţie many-to-many între CURS şi POZITIE_ORAR;
c) Pentru fiecare curs vom avea un atribut start care reţine ora de începere
a cursului şi un atribut durată care memorează numărul de poziţii
consecutive din orar "ocupate" de acel curs;
d) Pentru fiecare curs vom avea două atribute primul şi ultimul care
memorează prima şi respectiv ultima poziţie din orar ocupată de acel
curs.
2. Fie următoarea hartă a relaţiilor:
Figura 1.13. Relaţia propusă pentru problema 2
Cum se citeşte corect relaţia dintre CLIENT şi MAŞINA?
a) Fiecare CLIENT poate să închirieze o MAŞINĂ şi numai una.
b) Fiecare CLIENT trebuie să închirieze o MAŞINĂ şi numai una.
c) Fiecare CLIENT poate să închirieze una sau mai multe MAŞINI.
d) Fiecare CLIENT trebuie să închirieze una sau mai multe MAŞINI.
3. Numele unei entitǎţi este de obicei:
a) un verb;
b) un substantiv ;
c) un adverb;
d) orice cuvânt.
4. Care dintre următoarele variante NU poate reprezenta un atribut al entităţii
PANTOF?
a) culoare;
b) mărime;
c) model;
d) clasa.
5. Care dintre următoarele fraze pot fi citite din schema de mai jos?
Figura 1.14. Relaţia propusă pentru problema 5
Capitolul 1. Proiectarea bazelor de date
a)
b)
c)
d)
19
Un student poate să urmeze mai multe cursuri.
Un curs poate fi urmat de mai mulţi studenţi.
Un student trebuie să urmeze un singur curs.
Un curs trebuie să fie urmat de un student.
6. Ce semnificaţie are piciorul de cioară (
) în cadrul unui ERD?
a) relaţia este obligatorie;
b) relaţia este opţională;
c) pot exista una sau mai multe instanţe ale entităţii lângă care apare
semnul în relaţie cu o instanţă a celeilalte entităţi;
d) niciuna din variantele anterioare.
1. Completaţi în tabelul următor, în prima coloană, câte un exemplu de entitate a
cărui atribut este specificat în coloana a doua:
Entitate
Atribut
culoare
nr_calorii
volum
Tabelul 1.2.
2. Citiţi, în ambele sensuri, următoarele relaţii. Din ce atribute este compus UID-ul
fiecărei entităţi?
Figura 1.15. Relaţiile propuse pentru problema 2
20
Baze de date – curs introductiv
3. Rezolvaţi următoarele relaţii many-to-many:
Figura 1.16. Relaţiile propuse pentru problema 3
4. Daţi două exemple de relaţii one-to-many.
(vezi baremele de notare şi de corectare de la pag. 380)
1. Reluaţi aplicaţiile de la pagina 11 şi stabiliţi relaţiile dintre entităţile de la fiecare
exerciţiu. Rezolvaţi apoi eventualele relaţii many-to-many. Verificaţi să nu existe
relaţii redundante în schemele obţinute.
Pentru scenariile de la punctele 2-5, determinaţi entităţile, atributele acestora şi
relaţiile dintre entităţi. Desenaţi harta relaţiilor pentru fiecare exerciţiu în parte.
2. O firmă produce mai multe tipuri de maşini, un model fiind caracterizat printr-un
nume, mărimea motorului şi un sufix care indică gradul de lux al acesteia (de
exemplu XL, GL). Fiecare model este construit din mai multe părţi, fiecare parte
putând fi folosită pentru construirea mai multor modele de maşini. Fiecare parte are
o descriere şi un cod. Fiecare model de maşină este produs de exact o fabrică a
firmei, fabrică ce se poate găsi în una din ţările UE.
O fabrică poate produce mai multe modele de maşini şi mai multe tipuri de părţi
componente. De asemenea, fiecare tip de parte componentă poate fi produsă de o
singură fabrică a firmei.
Capitolul 1. Proiectarea bazelor de date
21
3. O universitate are în componenţa sa mai multe facultăţi, fiecare facultate având
mai multe departamente. Fiecare departament oferă studenţilor mai multe cursuri.
Un profesor poate lucra la un singur departament al unei singure facultăţi. Fiecare
curs are mai multe secţiuni, iar o secţiune poate să facă parte din mai multe
cursuri. Un profesor poate preda mai multe secţiuni, din acelaşi curs sau din
cursuri diferite, dar o secţiune poate fi predată de mai mulţi profesori.
4. La o facultate este nevoie să se memoreze date despre studenţi, cursuri şi
secţiunile fiecărui curs. Fiecare student are un nume, un număr de identificare,
adresa de acasă, adresa temporară, pentru cei care nu fac facultatea în localitatea
lor. Un student poate opta să urmeze un curs întreg sau doar anumite secţiuni ale
unui curs. De asemenea, el poate urma mai multe cursuri şi/sau secţiuni de curs
simultan. Un curs poate avea mai multe secţiuni, dar o secţiune poate fi parte a
mai multor cursuri.
5. Angajaţii unei firme sunt redistribuiţi la diferitele departamente din cadrul firmei.
Dorim ca în baza de date să memorăm, pentru fiecare angajat, departamentul la
care lucrează acum, dar şi departamentul la care a lucrat prima dată, la angajarea
în firmă.
22
Baze de date – curs introductiv
1.2. Normalizarea datelor
1.2.1. Ce este normalizarea?
Normalizarea este o tehnică de proiectare a bazelor de date prin care se
elimină (sau se evită) anumite anomalii şi inconsistenţe ale datelor. O bază de date
bine proiectată nu permite ca datele să fie redundante, adică aceeaşi informaţie să
se găsească în locuri diferite sau să se memoreze în baza de date informaţii
care se pot deduce pe baza altor informaţii memorate în baza de date. Anomaliile
care pot să apară la o bază de date nenormalizată sunt următoarele:
-
anomalii la actualizarea datelor – închipuiţi-vă că la secretariatul şcolii
voastre sunt memorate într-o tabelă informaţiile despre toţi elevii şcolii:
nume, adresă, telefon, etc. De asemenea, la biblioteca şcolii există fişele
voastre tot într-o tabelă. Aceste fişe conţin numele, prenumele, adresa,
telefonul, data înscrierii la bibliotecă, etc. Acum câteva zile v-aţi schimbat
domiciliul. Noua adresă trebuie modificată atât la secretariat cât şi în fişa
de la bibliotecă şi în toate locurile în care această informaţie apare. Dacă
modificarea nu se produce în unul dintre aceste locuri (fie că aţi uitat să
anunţaţi, fie din alte motive), datele devin inconsistente.
Alt scenariu: la o bibliotecă se înregistrează într-o tabelă următoarele
date despre cărţi: ISBN, titlu, autor, preţ, subiect, editură şi adresa
editurii. La un moment dat, o editură îşi schimbă adresa. Bibliotecara va
trebui să modifice adresa editurii respective în înregistrările corespunzătoare tuturor cărţilor din bibliotecă apărute la respectiva editură. Dacă
această modificare nu se face cu succes, unele dintre înregistrări
rămânând cu vechea adresă, apare din nou o inconsistenţă a datelor.
-
anomalii de inserare – în exemplul anterior, nu vom putea memora
adresa unei edituri, lucru inacceptabil dacă dorim să avem informaţii şi
despre edituri a căror cărţi nu le avem în bibliotecă, eventual de la care
dorim să facem comenzi.
-
anomalii de ştergere – să presupunem că într-o tabelă memorăm
următoarele informaţii: codul studentului, codul cursului şi codul
profesorului. La un moment dat, niciun student nu mai doreşte să
participe la un anume curs. Ştergând toate înregistrările
corespunzătoare cursului, nu vom mai putea şti niciodată cine preda acel
curs.
Conceptul de normalizare a bazelor de date a fost pentru prima dată introdus de
către Edgar Frank Codd. Formele normale oferă indicaţii pe baza cărora puteţi decide
dacă un anumit ERD este bine proiectat, neexpus anomaliilor şi inconsistenţelor. În
principiu, normalizarea implică descompunerea unei entităţi în două sau mai multe
entităţi, prin compunerea cărora se pot obţine exact aceleaşi informaţii.
Capitolul 1. Proiectarea bazelor de date
23
Formele normale se aplică fiecărei entităţi în parte. O bază de date (sau un
ERD) se găseşte într-o anumită formă normală doar dacă toate entităţile se găsesc
în acea formă normală.
Edgar Codd a definit primele trei forme normale 1NF, 2NF şi 3NF. Ulterior,
s-au mai definit formele normale 4NF, 5NF şi 6NF care însă sunt rar folosite în
proiectarea bazelor de date.
1.2.2. Prima formă normală (1NF)
O entitate se găseşte în prima formă normală dacă şi numai dacă:
- nu există atribute cu valori multiple;
- nu există atribute sau grupuri de atribute care se repetă.
Cu alte cuvinte, toate atributele trebuie să fie atomice, adică să conţină o
singură informaţie.
Dacă un atribut are valori multiple, sau un grup de atribute se repetă, atunci
trebuie să creaţi o entitate suplimentară pe care să o legaţi de entitatea originală
printr-o relaţie de 1:m. În noua entitate vor fi introduse atributele sau grupurile de
atribute care se repetă.
Să considerăm entitatea din Fig. 1.17, referitoare la notele elevilor unei
clase. Câteva observaţii referitoare la această entitate: câte discipline studiazǎ un
elev? Câte perechi (disciplina, nota) va trebui să aibă entitatea ELEV? Să spunem
că ştim exact numărul maxim de discipline pe care le poate studia un elev. Ce se
întâmplă dacă în anul şcolar viitor acest număr de discipline va fi mai mare? În
plus, la o materie un elev poate avea mai multe note. Câte note? Cum memorăm
aceste note? Le punem în câmpul corespunzător disciplinei cu virgulă între ele?
Cum rezolvăm această problemă? Vom crea o nouă entitate în care vom
introduce disciplina şi nota la disciplina respectivă (vezi Fig. 1.18).
În acest fel, fiecărui elev îi pot corespunde oricâte note, iar la o disciplină
poate avea oricâte note, singura restricţie conform acestui model fiind că un elev
nu va putea primi în aceeaşi zi, la aceeaşi materie, mai multe note.
Să considerăm un alt exemplu. Pentru managementul unui proiect este
important să ştim pentru fiecare membru al echipei care sunt abilităţile de care dispune,
pentru a cunoaşte modul în care să atribuim sarcinile în cadrul grupului. Într-o primă
etapă, am proiectat o entitate ANGAJAT, care are un atribut abilităţi, ca în Fig. 1.19.
Însă se ştie că fiecare angajat are mai multe abilităţi pe care dorim să le
memorăm. Aşadar, atributul abilităţi nu respectă prima formă normală. În
consecinţă, vom crea o nouă entitate ABILITATE în care vom memora toate
abilităţile fiecărui angajat (vezi Fig. 1.20).
24
Baze de date – curs introductiv
Figura 1.17
Figura 1.18
Figura 1.19
Figura 1.20
1.2.3. A doua formă normală (2NF)
O entitate se găseşte în a doua formă normală dacă şi numai dacă se
găseşte în prima formă normală şi în plus, orice atribut care nu face parte din UID
(Unique IDentifier) va depinde de întregul UID, nu doar de o parte a acestuia.
De exemplu, dacă memorăm angajaţii unui departament într-o entitate ca mai jos:
Figura 1.21. Exemplu de entitate
Se observă că data_nasterii şi adresa sunt două atribute care depind
doar de id-ul angajatului, nu de întregul UID care este combinaţia dintre atributele
id_dep şi id_angajat. Această situaţie se rezolvă prin crearea unei noi entităţi
ANGAJAT, pe care o legăm de entitatea DEPARTAMENT printr-o relaţie 1:m.
Capitolul 1. Proiectarea bazelor de date
25
Figura 1.22. Relaţia între cele două entităţi
O situaţie mai specială este în cazul relaţiilor barate, când trebuie ţinut
seama că UID-ul unei entităţi este compus din atribute din entitatea respectivă,
plus un atribut sau mai multe provenite din relaţia barată. Să considerăm următorul
exemplu:
Figura 1.23. Exemplu de relaţie barată
Se observă că UID-ul entităţii APARTAMENT este compus din combinaţia a
trei atribute: numărul apartamentului, numărul blocului şi strada. Deci, toate
atributele din entitatea APARTAMENT care nu fac parte din UID, trebuie să depindă
de întregul UID. Dar se ştie că atributul cod_postal depinde doar de strada şi de
numărul blocului, nu şi de numărul apartamentului. Acest lucru ne spune că
atributul nu este memorat la locul potrivit. Deoarece depinde doar de combinaţia
(strada, nr_bloc), înseamnă că de fapt depinde de UID-ul entităţii bloc.
Aşadar, vom muta atributul cod_postal în entitatea BLOC.
Figura 1.24. Rezultatul modificării efectuate
Observaţie ! Dacă o entitate se găseşte în prima formă normală şi UID-ul său
este format dintr-un singur atribut, atunci ea se găseşte automat în a doua
formă normală.
26
Baze de date – curs introductiv
1.2.4. A treia formă normală (3NF)
O entitate se găseşte în a treia formă normală dacă şi numai dacă se
găseşte în a doua formă normală şi în plus niciun atribut care nu este parte a
UID-ului nu depinde de un alt atribut non-UID. Cu alte cuvinte, nu se acceptă
dependenţe tranzitive, adică un atribut să depindă de UID în mod indirect.
Luăm ca exemplu entitatea CARTE din Fig. 1.25. Atributul biografie_autor nu
depinde de ISBN ci de atributul autor. Nerezolvarea acestei situaţii duce la
memorarea de date redundante, deoarece biografia unui autor va fi memorată
pentru fiecare carte scrisă de autorul respectiv.
Rezolvarea acestei situaţii constǎ în crearea unei noi entităţi, să-i zicem
AUTOR, pe care o legăm de entitatea CARTE printr-o relaţie 1:m (vezi Fig. 1.26).
Figura 1.25. Entitate
Iniţială
Figura 1.26. Introducerea unei noi entităţi
Atenţie! Acest model este corect doar dacă se acceptă că o carte are un singur autor.
Lăsăm ca temă rezolvarea situaţiei în care o carte poate avea mai mulţi autori. În
această situaţie, apare o relaţie many-to-many pe care trebuie să o rezolvaţi.
1. Care dintre următoarele enunţuri NU este un exemplu de redundanţă?
a) O relaţie între două entităţi care poate fi dedusă din altă relaţie.
b) O valoare dintr-o bază de date care poate fi obţinută direct pe baza altei valori.
c) Două atribute din baza de date care au aceeaşi valoare.
d) O valoare din baza de date care poate fi obţinută efectuând diferite
calcule asupra altor valori.
e) Niciuna dintre variantele anterioare.
Capitolul 1. Proiectarea bazelor de date
27
2. Care dintre următoarele cerinţe NU sunt necesare pentru ca o entitate să se
găsească în a treia formă normală?
a) Trebuie să se găsească în a doua formă normală.
b) Fiecare atribut care nu face parte din UID trebuie să depindă de întregul UID.
c) Nu trebuie să existe dependenţe tranzitive.
d) Niciuna dintre variantele anterioare.
3. Care este cea mai avansată formă normală în care
se găseşte entitatea alăturată?
a) 1NF;
c) 3NF;
b) 2NF;
d) ERD-ul nu este normalizat.
Figura 1.27.
Entitatea propusă
4. În ce formă normală se găseşte fiecare dintre următoarele entităţi?
a)
b)
c)
5. Un magazin vinde o gamă variată de pantofi de diferite mărimi şi modele. Un
model este identificat printr-un cod. Fiecare model are o descriere şi aceeaşi
descriere se poate aplica mai multor modele. Atributul vanzare_saptamanala
va memora numărul de pantofi de un anumit model şi o anumită mărime vânduţi
săptămâna anterioară (de exemplu, 25 de perechi, model 17, mărimea 39). Atributul
valoare_lunara_model reprezintă valoarea totală a pantofilor vânduţi pentru
fiecare model în parte, indiferent de model. Desenaţi un ERD în forma normală
3NF, conţinând toate aceste informaţii.
6. Se dă următoarea schemă a unei baze de date existente într-o videotecă.
Presupunând că videoteca dispune de un singur exemplar din fiecare film video,
stabiliţi în ce formă normală se găseşte acest ERD. Dacă el nu se găseşte în forma
normală 3NF, faceţi modificările necesare pentru aducerea sa la forma normală 3NF.
Figura 1.28.
Schema propusă
28
Baze de date – curs introductiv
7. Plecând de la următoarea entitate, desenaţi un ERD în forma normală 3NF:
Figura 1.29. Entitatea propusă pentru problema 7
8. Desenaţi ERD-ul pentru următorul scenariu şi aduceţi-l în forma normală 3NF:
într-o clădire se găsesc mai multe birouri. Fiecare birou este identificat unic
printr-un număr. În fiecare birou se găseşte un singur telefon. Un telefon poate fi de
două tipuri: telefon interior (cu care nu se pot face apeluri în afara clădirii) şi telefon
exterior, cu care se pot face apeluri atât în interiorul clădirii cât şi cu exteriorul.
Fiecare telefon are un număr unic. Într-un birou pot lucra mai mulţi angajaţi, pentru
fiecare cunoscându-se numele, prenumele, adresa, e-mail-ul, data naşterii şi data
angajării. Se ştie că un angajat poate lucra într-un singur birou.
9. Modificaţi ERD-ul de la problema anterioară în ipoteza că într-un birou pot exista
mai multe telefoane, folosite în comun de către toţi angajaţii care lucrează în acel
birou.
10. Aduceţi modificările necesare entităţii alăturate astfel încât să obţineţi un ERD
în forma normală 3NF. Entitatea reţine informaţii despre angajaţii unei agenţii de
plasare a forţei de muncă, care oferă personal cu normă întreagă sau cu program
redus, pentru diferite hoteluri din întreaga ţară. Se
memorează numărul de ore lucrate de fiecare angajat
în diferite hoteluri. Se ştie că numărul de contract este
întotdeauna dependent de codul hotelului dar nu şi
invers.
Figura 1.30. Entitatea propusă
pentru problema 10
Capitolul 1. Proiectarea bazelor de date
29
1.3. Implementarea modelului conceptual
1.3.1. Modele de baze de date
Bazele de date au fost concepute pentru stocarea volumelor mari de informaţii
relativ omogene între care se pot stabili anumite relaţii. O bază de date este deci o
colecţie structurată de date aflate în interdependenţă, date care pot fi consultate
pentru a răspunde diferitelor interogări. Înregistrările returnate ca răspuns la o
interogare devin informaţii care pot fi utilizate în luarea unor decizii ulterioare.
Sistemul complex de programe care permite descrierea, organizarea,
memorarea, regăsirea, administrarea şi securizarea informaţiilor dintr-o bază de
date se numeşte sistemul de gestiune a bazelor de date (SGBD). Memorarea
datelor conţinute de bazele de date se face pe suporturile de memorie internă sau
externă folosite de calculatoare. SGBD este un software special asociat bazelor de
date care asigură interfaţa între o bază de date şi utilizatorii ei, rezolvând toate
cererile de acces la datele memorate.
Pentru orice bază de date poate fi compusă o descriere a datelor şi
obiectelor memorate, precum şi relaţiile existente între aceste obiecte. O astfel de
descriere se numeşte schema bazei de date.
Există mai multe modele de baze de date, acestea diferenţiindu-se în funcţie
de modul de organizare a schemei bazei de date.
Un model de bază de date nu este doar un mod de structurare a datelor, el
defineşte de asemenea un set de operaţii care pot fi realizate cu datele respective.
Cele mai cunoscute modele de baze de date sunt următoarele:


Modelul tabelar – toate datele sunt memorate sub forma unui singur
tabel, un tablou bidimensional de date.
Modelul ierarhic – datele sunt organizate sub forma unor structuri
arborescente, există deci o rădăcină cu mai mulţi dependenţi, care la rândul
lor pot avea alţi dependenţi. IMS (Information Management System) produs
de IBM este un exemplu de SGBD bazat pe acest tip de model.

Modelul reţea este un model performant, dar complicat. O bază de date
de tip reţea reprezintă o colecţie de noduri şi legături, fiecare nod putând
fi legat de oricare altul. Legăturile trebuie stabilite având tot timpul în
minte interogările posibile şi acţiunile viitoare probabile.

Modelul relaţional reprezintă cel mai utilizat model de stocare a datelor,
în care datele sunt organizate sub formă de tabele între care există
diverse legături.
30
Baze de date – curs introductiv

Modelul obiectual, destinat să suporte modele de obiecte complexe
(organizare de tip heap cu referinţe între componente) este oarecum
asemănător reţelei, iar prin faptul că pentru accesare directă, stochează
o hartă a ierarhiilor şi relaţiilor claselor de obiecte, are ascendent şi în
modelul ierarhic. Modelul obiectual se pretează pentru înmagazinarea
informaţiilor complexe: atribute descriptive asociate datelor multimedia,
documentelor, desenelor, arhivelor, etc.

Modelele hibride sunt mixturi ale modelelor prezentate anterior, din care
cel mai semnificativ este modelul relaţional-obiectual, obţinut prin
extensii ale modelului de organizare tabelar şi izvorât din tendinţa spre
universalitate a bazei de date (entităţi complexe şi de naturi diferite,
evoluând în condiţii eterogene).
1.3.2. Baze de date relaţionale
Bazele de date relaţionale au fost dezvoltate având în vedere în primul rând
utilizatorii finali. Acest model are la bază teoria matematică a relaţiilor, ceea ce a
făcut posibilă tratarea algoritmică a proiectării bazelor de date şi problema
normalizării datelor.
Modelul relaţional este un model simplu, bazat pe algebra relaţională, care a
făcut posibilă dezvoltarea limbajelor relaţionale sub forma unui software specializat
ce asistă procesul de implementare a bazelor de date. Astfel de limbaje sunt
SQL-ul (Structured Query Language) şi QBE (Query By Example).
În momentul de faţă, există multe sisteme performante de gestiune a bazelor
de date relaţionale precum Oracle, DB2, MySQL, Informix, etc.
În cazul bazelor de date relaţionale mari şi foarte mari, s-au impus SGBD-uri
precum Oracle, DB2 şi Informix. Acestea au la bază tehnologia client-server.
Transformarea modelului conceptual, a ERD-ului, în modelul fizic, adică în
baza de date propriu-zisă, se numeşte mapare. Acest proces implică transformarea
fiecărui element al ERD-ului.
Prima etapă a acestui proces constă în crearea tabelelor bazei de date. Astfel:

fiecărei entităţi îi va corespunde câte un tabel. Spre deosebire de
entitate, un tabel va avea numele un substantiv la plural. De exemplu,
entitatea ANGAJAT se va transforma în tabela ANGAJAŢI, entitatea
ELEV, în tabela ELEVI, etc.

Fiecare atribut al unei entităţi va deveni o coloană a tabelei. Fiecare
coloană va memora date de acelaşi tip.

Fiecare instanţă a unei entităţi se va transforma într-un rând (sau
înregistrare) al tabelului corespunzător.

Unicul identificator al entităţii devine cheia primară a tabelei. Coloana
sau combinaţia de coloane care identifică în mod unic toate liniile unui
tabel se numeşte cheie primară.
Capitolul 1. Proiectarea bazelor de date
31
Deci, orice tabelă are linii şi coloane şi conţine datele organizate conform
anumitor structuri. În limbajul bazelor de date, coloanele se numesc câmpuri.
Fiecare coloană reprezintă un câmp cu o denumire unică, de un anumit tip (şir de
caractere, numeric, dată calendaristică, etc.), având o dimensiune prestabilită.
Rândurile tabelei se numesc înregistrări.
Vom vedea pe parcursul următorului paragraf cum mapăm relaţiile dintre
entităţi.
numele entităţii la plural  numele tabelei
atributul  coloana
instanţa  linia
Figura 1.31. Maparea entităţilor
Informaţiile despre o tabelă a bazei de date vor fi prezentate folosind
diagramele de tabelă care sunt nişte tabele de forma celui din Tabelul 1.3, în care
vom nota numele coloanelor pe care le va avea tabela bazei de date, notăm dacă
o coloană face parte din cheia primară, caz în care vom scrie un pk (primary key)
în coloana a treia, sau dacă face parte din cheia străină, caz în care vom scrie în
coloana a doua un fk (foreign key), iar în ultima coloană vom nota dacă atributul
este opţional sau obligatoriu. Pentru aceasta vom folosi aceleaşi simboluri ca şi în
cazul ERD-ului. Asupra cheilor străine vom reveni în paragraful următor.
În tabelul 1.3 vedeţi diagrama tabelei CĂRŢI corespunzǎtoare entitǎţii CARTE:
Numele coloanei
Tip cheie
Opţionalitatea
titlu
Pk
*
autor
Pk
*
data_apariţiei
*
format
*
nr_pagini
*
Tabelul 1.3. Exemplu de diagramă de tabel
Se observă că deocamdată nu avem nicio cheie străină, deoarece cheia străină
provine din relaţiile în care entitatea este implicată. Cum deocamdată această
entitate nu are nici o relaţie cu nicio altă entitate, nu vom avea nicio cheie străină.
32
Baze de date – curs introductiv
Completaţi diagramele de tabelă pentru entităţile de mai jos:
Figura 1.32. Entităţi propuse ca exerciţiu
1.3.3. Maparea relaţiilor
1.3.3.1. Maparea relaţiilor one-to-many
Să începem cu un exemplu. Vom considera ERD-ul din Fig. 1.33:
Figura 1.33. Exemplu de ERD
Să ne reamintim cum se citeşte relaţia dintre cele două entităţi:
Fiecare JUCĂTOR poate juca într-o ECHIPĂ şi numai una.
La fiecare ECHIPĂ trebuie sǎ joace unul sau mai mulţi JUCĂTORI.
Observăm că nu putem memora toţi jucătorii care joacă la o echipă în cadrul
tabelei ECHIPA, deoarece ar trebui să introducem o coloană cu valori multiple.
Invers însă, putem cu uşurinţă să memorăm, pentru fiecare jucător, echipa la care
joacă, deoarece acesta nu poate juca decât la o singură echipă.
Capitolul 1. Proiectarea bazelor de date
33
Oare cum putem memora echipa la care joacă un jucător? Răspunsul este
destul de simplu. Vom memora pentru fiecare jucător codul echipei la care joacă.
Adică diagrama de tabel corespunzătoare entităţii JUCĂTOR va fi următoarea:
Numele coloanei
Nr_legitimatie
Nume
Prenume
Data_nasterii
Adresa
Telefon
Email
cod_echipa
Tip cheie
Pk
Fk
Opţionalitatea
*
*
*
*
*
o
o
o
Tabelul 1.4. Diagrama de tabel corespunzătoare entităţii JUCĂTOR
De pe tabela anterioară puteţi deduce încă un element important al mapării
relaţiilor: dacă relaţia pe partea many este opţională atunci şi coloanele cheii străine
vor fi opţionale. Ce înseamnă acest lucru? Cum un jucător poate la un moment dat
să nu joace la nici o echipă, câmpul cod_echipă va rămâne necompletat în dreptul
lui (va avea valoarea NULL). Dacă însă relaţia este obligatorie pe partea many,
atunci coloanele ce fac parte din cheia străină vor fi obligatorii.
În general, la maparea unei relaţii de tip one-to-many vom introduce, în
tabela corespunzătoare entităţii de pe partea many a relaţiei, cheia primară a
entităţii de pe partea one a relaţiei. Câmpurile astfel introduse se vor numi chei
străine (în engleză, foreign key).
Aşadar:
-
cheia străină a unei tabele este cheia primară din tabela referinţă;
-
cheia străină este întotdeauna introdusă în tabela corespunzătoare
entităţii din partea many a relaţiei.
1.3.3.2. Maparea relaţiilor one-to-one
Dându-se două entităţi A şi B legate între ele printr-o relaţie one-to-one, este
evident că putem include cheia primară a lui A în cadrul tabelei B, dar putem
proceda la fel de bine şi invers, incluzând cheia primară a tabelei B în cadrul
tabelei A, deoarece fiecărei instanţe a entităţii A îi corespunde cel mult o instanţă a
entităţii B, dar şi invers, oricărei instanţe a entităţii B îi corespunde cel mult o
instanţă a entităţii A.
Pentru relaţia din Fig. 1.34, de exemplu, putem memora - pentru fiecare
persoană, seria de paşaport, dar şi invers - pentru fiecare paşaport, putem memora
cnp-ul deţinătorului.
34
Baze de date – curs introductiv
Decizia depinde de specificul afacerii modelate. Dacă, de exemplu, ne
interesează în primul rând persoanele şi abia apoi datele de pe paşapoarte, atunci
vom adopta probabil prima variantă, a memorării seriei de paşaport în cadrul
tabelei PERSOANE, iar dacă însă baza de date este destinată evidenţei
paşapoartelor, atunci probabil vom adopta varianta a doua.
Figura 1.34. Exemplu de ERD
Uneori este convenabil să memorăm cheia străină în ambele părţi ale
relaţiei, în exemplul nostru, pentru fiecare paşaport să memorăm cnp-ul persoanei
care îl deţine, dar şi pentru fiecare persoană să memorăm seria de paşaport.
1.3.4. Maparea relaţiilor barate
Relaţiile barate se transformǎ în urma mapǎrii în cheie străină în tabela
aflată în partea many a relaţiei, la fel ca la maparea oricărei relaţii one-to-many.
Bara de pe relaţie exprimă faptul că acele coloane ce fac parte din cheia străină
vor deveni parte a cheii primare a tabelei din partea many a relaţiei barate.
Pentru exemplul din Fig. 1.35, cheia primară a tabelei ATRIBUTE va fi
formată din coloanele denumire_atribut şi denumire_entitate, aceasta din
urmă fiind de fapt cheie străină în tabela ATRIBUTE:
Figura 1.35. Maparea relaţiilor barate
Vom avea diagramele de tabel:
Numele coloanei
denumire
Tip cheie
Pk
Opţionalitatea
*
Tabelul 1.5. Diagrama de tabel ENTITĂŢI
Capitolul 1. Proiectarea bazelor de date
Numele coloanei
denumire_atribut
denumire_entitate
opţionalitate
Tip cheie
Pk
Pk, Fk
35
Opţionalitatea
*
*
*
Tabelul 1.6. Diagrama de tabel ATRIBUTE
Să considerăm acum un exemplu în care există mai multe relaţii barate,
în cascadă:
Figura 1.36. Relaţii barate în cascadă
Vom avea tabelele de mai jos:
Numele coloanei
idA
C1
Tip cheie
Pk
Opţionalitatea
*
*
Tabelul 1.7. Diagrama de tabel pentru entitatea A
Numele coloanei
idB
C2
idA
Tip cheie
Pk
Pk, Fk
Opţionalitatea
*
*
*
Tabelul 1.8. Diagrama de tabel pentru entitatea B
Numele coloanei
idC
C3
idA
idB
Tip cheie
Pk
Pk, Fk
Pk, Fk
Opţionalitatea
*
*
*
*
Tabelul 1.9. Diagrama de tabel pentru entitatea C
Numele coloanei
idD
C4
idA
Tip cheie
Pk
Fk
Opţionalitatea
*
*
*
Tabelul 1.10. Diagrama de tabel pentru entitatea D
36
Baze de date – curs introductiv
1. Reluaţi exerciţiile propuse pe parcursul paragrafelor anterioare şi realizaţi
maparea ERD-urilor obţinute.
2. Realizaţi maparea următoarei hărţi a relaţiilor.
Figura 1.37. Harta relaţiilor propusă ca aplicaţie
1.3.5. Operaţii specifice prelucrării bazelor de date
Orice sistem de gestiune a bazelor de date (SGBD) trebuie să asigure
următoarele funcţii:

definirea structurii bazei de date;

încărcarea datelor în baza de date (adăugarea de noi înregistrări la
baza de date);

accesul la date pentru:
o
interogare (afişarea datelor, sortarea lor, calcule statistice, etc.);
o
ştergere;
o
modificare;
Capitolul 1. Proiectarea bazelor de date



37
întreţinerea bazei de date:
o
refacerea bazei de date prin existenţa unor copii de siguranţă;
o
repararea în caz de incident;
o
colectarea şi refolosirea spaţiilor goale;
posibilitatea de reorganizare a bazei de date prin:
o
restructurarea datelor;
o
modificarea accesului la date;
securitatea datelor.
O parte din aceste operaţii pot fi realizate cu ajutorul limbajului SQL, altele
cu ajutorul unor programe specializate, care sunt puse la dispoziţia administratorului bazei de date de către sistemul de gestiune al bazelor de date.
1.3.6. Reguli de integritate
Detalierea caracteristicilor pe care trebuie să le prezinte un SGBD pentru a fi
considerat relaţional a fost realizată de către E. F. Codd în 1985 sub forma a 13
reguli. Una dintre aceste reguli precizează că restricţiile de integritate trebuie să
poată fi definite în limbajul utilizat de SGBD pentru definirea datelor.
Regulile de integritate garantează că datele introduse în baza de date sunt
corecte şi valide. Aceasta înseamnă că dacă există orice regulă sau restricţie
asupra unei entităţi, atunci datele introduse în baza de date respectă aceste
restricţii.
Tipurile de reguli de integritate sunt următoarele:

Integritatea entităţilor – indică faptul că nici o coloană ce face parte
din cheia primară nu poate avea valoarea NULL. În plus, pentru fiecare
înregistrare, cheia primară trebuie să fie unică.

Integritatea de domeniu – acest tip de reguli permite ca într-o
anumită coloană să se introducă doar valori dintr-un anumit domeniu.
De exemplu, putem impune ca salariul unui angajat să fie cuprins între
4500 şi 5000 RON.

Integritatea referenţială – este o protecţie care asigură ca fiecare
valoare a cheii străine să corespundă unei valori a cheii primare din
tabela referită. De exemplu, referindu-ne la tabelele JUCĂTORI şi
ECHIPE, corespunzătoare ERD-ului din Fig. 1.33, cod este cheie
primară în tabela ECHIPE, iar în tabela JUCĂTORI, cod devine cheie
străină. Astfel, valoarea câmpului cod din cadrul tabelei JUCĂTORI
corespunzătoare unui anumit jucător trebuie să se regăsească printre
valorile câmpului cod din tabela ECHIPE, altfel ar însemna că jucătorul
respectiv joacă la o echipă inexistentă (vezi Fig. 1.38).
38
Baze de date – curs introductiv
Figura 1.38. Exemplu de încălcare a integrităţii referenţiale
Situaţii de încălcare a integrităţii referenţiale pot apărea:

la adăugarea unei noi înregistrări în baza de date, se poate încerca
introducerea unor valori invalide pentru câmpurile cheii străine;

la actualizarea bazei de date;

la ştergerea unei înregistrări. De exemplu, se şterge înregistrarea
corespunzătoare unei anumite echipe (echipa se desfiinţează).
Înregistrările jucătorilor care au jucat la acea echipă vor încălca
integritatea referenţială, deoarece se vor referi la o echipă care nu mai
există. Soluţiile posibile sunt ca la ştergerea unei echipe, toţi jucătorii
care au activat la acea echipă să fie şi ei şterşi din baza de date
(ştergere în cascadă), sau valoarea câmpului cod_echipă pentru
acei jucători să fie setată la NULL, ceea ce înseamnă că acei jucători
nu activează la nicio echipă.
1.3.7. Programe de validare şi de acţiune
În realizarea modelului conceptual al unei baze de date se ţine cont de
modul în care funcţionează afacerea modelată, datele care trebuie să fie memorate,
relaţiile dintre acestea, etc. Modul de utilizare a diferitelor date, modul în care
acestea sunt relaţionate pot diferi de la o afacere la alta.
Regulile afacerii unei organizaţii se referă în esenţă la procesele şi fluxurile
tuturor datelor şi activităţilor zilnice din cadrul organizaţiei.
Cum funcţionează organizaţia?
Care sunt activităţile sale?
Capitolul 1. Proiectarea bazelor de date
39
Regulile afacerii acoperă următoarele aspecte ale unei organizaţii:

Orice tip de politici organizaţionale de orice tip şi de la orice nivel al
organizaţiei.

Orice tip de formule de calcul (ca, de exemplu, modul de calcul al
ratelor pentru diverse împrumuturi, modul de calcul al salariilor, etc.).

Orice tip de reguli impuse de lege sau reguli interne ale organizaţiei.
Regulile simple ale afacerii pot fi implementate în modelul bazei de date prin
intermediul relaţiilor dintre entităţi. Acest tip de reguli se numesc reguli structurale.
Alte reguli ale afacerii pot fi implementate folosind regulile de integritate despre
care am discutat în paragraful anterior. Există totuşi reguli pentru implementarea
cărora va trebui să scriem programe speciale folosind limbaje specializate specifice
SGBD-ului utilizat. Acest tip de reguli se numesc reguli procedurale.
1. Când mapaţi un ERD, care dintre următoarele afirmaţii NU este adevărată?
a) Fiecare entitate este mapată într-o tabelă.
b) Fiecare atribut este mapat într-o coloană a tabelei corespunzătoare.
c) Fiecare entitate în parte este mapată într-o linie din tabelul corespunzător.
d) Fiecare relaţie one-to-many se transformă într-o cheie străină.
2. Într-o tabelă, o instanţă a unei entităţi este mapată ca:
a) o relaţie many-to-many;
b) o linie din tabel;
c) o coloană din tabel;
d) un atribut;
e) un index.
3. Două entităţi A şi B se găsesc într-o relaţie one-to-one care este opţională la
ambele capete. Care dintre următoarele variante este o soluţie corectă de mapare ?
a) Combinarea celor două entităţi A şi B într-o singură relaţie.
b) Crearea a două tabele separate şi includerea unei chei străine atât în
tabela A cât şi în tabela B.
c) Combinarea celor două entităţi A şi B într-o singură tabelă.
d) Utilizarea unei chei primare care să fie o combinaţie a cheilor primare din A şi B.
4. Referitor la ERD-ul din Fig. 1.39, care dintre afirmaţiile de mai jos corespund
unei variante corecte de mapare?
a) Se preia cheia primară din tabela PERSOANE şi se adaugă ca şi cheie
străină la tabela MASINI.
40
Baze de date – curs introductiv
Figura 1.39. ERD propus pentru problema 4
b) Se preia cheia primară din tabela MASINI şi se adaugă ca şi cheie străină
la tabela PERSOANE.
c) Se creează o singură tabelă cu informaţiile din ambele entităţi.
d) Se preiau cheile primare din ambele tabele şi se introduc într-o nouă
tabelă numită PROPRIETARI.
e) Oricare dintre variantele de mai sus este corectă.
5. O bază de date conţine următoarele tabele:
Tabela DEPARTAMENTE
DepNo Departament
1
IT
2
Electric
3
Geografie
4
Istorie
5
Business
Tabela ANGAJATI
IdAngajat NumeAngajat
1
Ionescu
2
Georgescu
3
Vasilescu
4
Marinescu
5
Andreescu
Tabela ANGAJARI
IdAngajat DepNo
1
1
3
2
4
1
3
3
1
2
2
5
Desenaţi ERD-ul din care s-au obţinut prin mapare aceste tabele.
(vezi baremele de notare şi de corectare de la pag. 380)
Capitolul 1. Proiectarea bazelor de date
41
1.4. Managementul de proiect
1.4.1. Ce este un proiect ?
Un proiect este o secvenţă de acţiuni intercorelate, care se derulează într-o
perioadă de timp clar definită şi delimitată, orientate către îndeplinirea unor
obiective cu caracter unic şi precis.
Putem defini managementul de proiect ca fiind efortul planificării,
organizării şi mobilizării resurselor pentru un scop dat. Managementul de proiect
este de fapt un instrument, un set de metode şi tehnici care ne ajută să atingem cu
eficacitate scopurile şi obiectivele propuse.
1.4.2. Etape în realizarea unui proiect
Orice proiect trece printr-o serie întreagă de etape. Ceea ce este important
de reţinut este faptul că orice proiect este un proces iterativ, în sensul că orice
etapă poate fi repetată de mai multe ori, în funcţie de necesităţile de redefinire a
anumitor cerinţe.
Etapele principale pe care le parcurgem pentru realizarea unui proiect sunt
următoarele:


Definirea proiectului
o
Validarea proiectului – în această etapă vor fi analizate toate documentele
prezente în propunerea de proiect. Această analiză va duce fie la
confirmarea şi acceptarea proiectului, fie va duce la respingerea, sau
eventual regândirea acestuia, în cazul în care propunerea de proiect nu a
fost bine realizată, şi resursele au fost subestimate.
o
Definirea proiectului – constă în enunţarea problemei, stabilirea scopului
proiectului, stabilirea unei liste a posibilelor soluţii etc. Orice proiect propus
poate avea elemente pe care cel care l-a propus nu a considerat necesar
să le detalieze, însă echipa de proiect poate avea nevoie de informaţii
suplimentare pentru a înţelege corect enunţul proiectului.
Organizarea proiectului
o
Stabilirea obiectivelor
o
Stabilirea grupului ţintă - când încercaţi să stabiliţi care este grupul ţintă
al unui proiect trebuie să răspundeţi la următoarele întrebări: Cine trebuie
să ştie despre proiect? Cine va folosi acest proiect? Asupra cui vor avea
impact rezultatele proiectului? Cine finanţează acest proiect? Cine aprobă
acest proiect? Cine livrează proiectul? Cine va trebui să fie instruit?
42
Baze de date – curs introductiv
o
Stabilirea cerinţelor proiectului – este un proces iterativ care poate
implica negocierea. Fiind conducătorul proiectului, ştiţi ce este posibil şi ce
nu în ceea ce priveşte scopul proiectului, timpul alocat, costurile, cerinţele
de calitate etc. Un proiect care nu îndeplineşte cerinţele utilizatorului este
din start un eşec.
o
Stabilirea infrastructurii proiectului – infrastructura se referă la
elemente precum instrumente de comunicare în cadrul echipei (telefoane
mobile, PDA, laptop, etc.), spaţiu de lucru pentru membrii echipei (birou),
echipamente de birou, laboratoare, etc.
o
Stabilirea sistemului de calitate a proiectului
o
Formarea echipei de proiect

Planificarea proiectului – planul proiectului prezintă desfăşurarea normală,
ideală a unui proiect. Acesta oferă reperele necesare evaluării situaţiei
proiectului. Fără existenţa unui plan dinainte stabilit, exercitarea controlului
este practic imposibilă.

Elaborarea proiectului – în această etapă se stabilesc detaliile tehnice şi de
design, se revizuiesc schemele tehnice, se revizuiesc criteriile de cost şi
performanţă. Această etapă vizează conturarea unui model al aplicaţiei. Se
proiectează bazele de date, se realizează interfeţele aplicaţiei (rapoarte,
ecrane, meniuri etc), se proiectează prelucrările automate, etc.

Dezvoltarea proiectului

Implementarea proiectului – constă în instalarea produsului şi testarea sa,
instruirea viitorilor utilizatori. Se testează produsul în condiţii reale, şi se
înlătură eventualele erori depistate în funcţionare. Tot în această fază
personalul implicat în proiect este redus. Se încep activităţile de publicitate.

Finalizarea proiectului – se elaborează rapoartele finale, se eliberează
personalul angajat în derularea proiectului.
1.4.3. Principiile lucrului în echipă
Colaborarea înseamnă mai ales implicarea oamenilor în crearea propriilor
soluţii la problemele cu care se confruntă. În cadrul unui proces colaborativ,
oamenii au ocazia să afle punctul de vedere şi perspectiva celorlalţi şi să
gândească împreună soluţii la problemele comune.
Colaborarea este o artă ! Sunteţi uneori puşi în situaţia de a vorbi şi
colabora cu persoane pe care nu le cunoaşteţi, cu care nu sunteţi de acord sau pe
care nu le agreaţi.
Mărimea echipei de proiect este un factor important care poate influenţa
modul de conducere al acesteia. Într-o echipă prea mare pot apărea probleme de
comunicare, dificultăţi în luarea deciziilor. În general, se acceptă că o echipă pentru
a putea fi eficientă nu trebuie să depăşească un număr de 10 persoane.
Capitolul 1. Proiectarea bazelor de date
43
În cazul proiectelor cu număr mare de persoane implicate, participanţii la
proiect trebuie organizaţi în mai multe echipe satelit intercorelate, coordonate de o
echipă principală al cărei rol principal este să asigure o comunicare facilă şi
eficientă între toate echipele satelit.
Fiecare membru al unei echipe de proiect trebuie să cunoască ceea ce se
aşteaptă de la el. Trebuie stabilite de la început rezultatele aşteptate de la fiecare
membru al echipei în parte, acţiunile ce trebuie executate pentru obţinerea
rezultatului, relaţiile de subordonare în cadrul echipei, metodele de măsurare a
performanţei fiecărui membru al echipei.
Liderul echipei are în primul rând rolul de a stabili, menţine şi proteja un
proces colaborativ care permite tuturor să participe neîngrădit la munca grupului.
1.4.4. Pregătirea şi susţinerea unei prezentări
În momentul finalizării unui proiect va trebui să prezentaţi rezultatul muncii
voastre în faţa clientului. Susţinerea unei prezentări în public este pentru oricine o
sursă de stres. Mulţi oameni ar prefera să evite complet această problemă, dar de
multe ori este imposibil de evitat. Indiferent că lucrăm singuri sau în echipă, vom
putea fi puşi în situaţia de a face o prezentare publică.
Adevărul este că susţinerea unei prezentări publice nu trebuie să fie un
motiv de stres. Atât timp cât aveţi în minte câteva principii de bază, vorbitul în
public va deveni o experienţă plăcută pentru voi.
Iată câteva principii de care trebuie să ţineţi seama pentru a depăşi
dificultăţile legate de vorbitul în public:

Vorbitul în public NU este un motiv real de stres.
Mulţi oameni erau la început îngroziţi de ideea de a vorbi în public. Le
tremurau genunchii, vocea, gândurile o luau razna. Totuşi, ei au învăţat
să elimine definitiv teama de a vorbi în public.

Nu îţi propune să fi genial sau perfect, chiar dacă aşa ţi se pare că ar
trebui. Ţi se poate întâmpla să greşeşti, ţi se poate întâmpla să uiţi
porţiuni întregi din ceea ce vroiai să spui, poţi să nu glumeşti deloc şi
totuşi prezentarea ta să aibă succes.
Totul depinde de cum defineşti tu şi auditorul tău succesul. Auditorul tău
nu aşteaptă de la tine să fi perfect. Cu cât încerci mai tare să fi perfect cu
atât mai mult vei adânci anxietatea pe care o ai şi efectul va fi contrar
celui scontat. Ceea ce este important atunci când faci o prezentare în
faţa unui public este să oferi ceva auditorului. Atâta timp cât auditorul
rămâne cu ceva de pe urma prezentării, ei o vor considera un succes.

Nu încerca să transmiţi prea multe informaţii într-o prezentare. Nu
trebuie să transmiţi “tone” de informaţii şi detalii, oferă publicului doar
ceea ce el doreşte cu adevărat. Studiile arată că oamenii îşi amintesc
doar foarte puţine elemente din ceea ce vorbitorii prezintă.
44
Baze de date – curs introductiv

Nu încerca să mulţumeşti pe toată lumea, acesta este un punct de
vedere nerealist.

Nu încerca să imiţi alţi prezentatori, e un lucru foarte dificil. Încearcă să fi
tu însuţi, e mult mai uşor.

Nu încerca să controlezi comportamentul auditorului. Dacă oamenii sunt
agitaţi, nu încerca să le controlezi comportamentul. Dacă cineva
vorbeşte cu vecinul, citeşte ziarul sau chiar a adormit în timpul
prezentării tale, ignoră-l!

Nu te scuza. Auditorul nu are de unde să ştie că ai uitat să spui ceva.
Vorbeşte cu încredere, fi convins de ceea ce spui.

Organizează logic conţinutul prezentării. Orice prezentare va avea o
introducere, conţinutul propriu-zis şi o concluzie.

Utilizează materiale audio-vizuale ajutătoare, dacă acestea sunt
necesare. O prezentare în PowerPoint, bine realizată, poate fi de un real
folos.
o
Asigură-te din timp că întregul echipament (calculator,
video-proiector, etc) funcţionează.
o
Nu bombarda auditorul cu efecte sonore sau cu animaţii exagerate şi
utilizează în mod echilibrat culorile.
o
Include în prezentarea electronică doar cele mai importante idei.
o
Nu încărca slide-urile cu prea multe texte. În general, se admit 7-10
cuvinte pe linie şi maximum 10 linii de text pe un slide.
o
Preferă un grafic în locul textelor, dar nu exagera cu mai mult de
două grafice pe un slide.

Păstrează contactul vizual cu auditorul. Încearcă în acest fel să faci
fiecare persoană din public să se simtă implicată.

Fă scurte pauze. Nu alerga prin prezentare, dă-ţi răgazul să respiri. Dă
timp audienţei să reflecte la ceea ce ai spus.

Adaugă puţin umor prezentării tale, dacă acest lucru este posibil.
Păstrează treaz interesul auditorului pe parcursul întregii prezentări.

Nu ţine mâinile în buzunar în timpul prezentării !

Adoptă o ţinută adecvată în ziua prezentării. Atrage atenţia auditorului
asupra a ceea ce spui, nu a mesajelor de pe tricou sau asupra bijuteriilor
pe care le porţi !
În acest moment v-aţi însuşit elementele de bază ale modelării bazelor de
date. Aţi văzut diverse situaţii ce pot apărea pe parcursul creării modelului
conceptual şi cum să rezolvaţi anumite situaţii problemă.
Capitolul 1. Proiectarea bazelor de date
45
În acest subcapitol aţi aflat cum se organizează un proiect, care sunt etapele
de realizare ale lui şi cum să organizaţi munca într-o echipă. De asemenea, ştiţi
cum să pregătiţi şi să faceţi o prezentare în faţa unui public. Este momentul să
aplicaţi toate aceste cunoştinţe!
Ideal ar fi să formaţi o echipă din 2 - 4 persoane, alegeţi-vă o temă de
proiect, fie din temele propuse în această secţiune, fie una propusă chiar de voi.
Realizaţi modelul conceptual al afacerii modelate. Atenţie! Repartizaţi sarcinile în
mod echitabil în cadrul echipei de proiect.
Pregătiţi o prezentare a proiectului realizat, materialele vizuale (postere,
pliante, prezentarea PowerPoint), care să vă ajute la susţinerea prezentării.
Puteţi chiar organiza împreună cu cadrul didactic, un concurs la nivelul
clasei sau al şcolii / academiei, la care să invitaţi şi alte persoane.
Nu uitaţi să documentaţi fiecare presupunere pe care aţi făcut-o în realizarea
proiectului!
Tema 1: „Campionatul Naţional de Fotbal”. O bază de date memorează informaţii
despre jucătorii şi cluburile din cele patru divizii din campionatul naţional de fotbal.
Fiecare club de fotbal are un nume unic în întregul campionat. Un club de fotbal
poate avea mai multe echipe în campionat. Pentru fiecare echipă se cunoaşte
căpitanul său, care este unul dintre jucători.
Jucătorii au asociat un identificator unic, un nume, nu neapărat unic şi sunt
angajaţi la diferitele echipe. În baza de date se păstrează şi detalii privind nivelul
abilităţilor (notă cuprinsă între 1 şi 10) fiecărui jucător pentru fiecare dintre poziţii de
joc (portar, apărător, mijlocaş, etc). De exemplu, jucătorul Ionescu poate avea
nivelul 10 pe postul de portar, 7 pentru poziţia de apărător, etc.
Este important ca în baza de date să se memoreze un istoric al tuturor
jucătorilor, la ce echipe au jucat, în ce perioadă, etc.
Se va memora şi un istoric al golurilor marcate de fiecare jucător de-a lungul
carierei. Pentru fiecare gol se va şti data, meciul în care a fost marcat, minutul, etc.
Tema 2: „Firmă de închirieri de maşini”. Trebuie să proiectaţi baza de date a
unei firme care oferă spre închiriere maşini de diferite tipuri. Trebuie să păstraţi
informaţii despre maşinile firmei, firmele cu care firma are contracte de colaborare
(de exemplu, garaje), maşinile închiriate, veniturile firmei şi bineînţeles date despre
clienţii firmei.
Maşinile sunt descrise prin date precum: producătorul, modelul, anul de
fabricaţie, mărimea motorului, tipul de combustibil, numărul de pasageri, numărul
de înmatriculare, preţul de cumpărare, data cumpărării, preţul de închiriere şi detalii
privind asigurarea maşinii.
46
Baze de date – curs introductiv
Toate reparaţiile importante asupra maşinilor firmei sunt făcute de firme cu
care colaborează. Unele firme solicită plata serviciilor de service imediat după ce
reparaţia a fost făcută, altele acceptă plata în rate a serviciilor. Trebuie ţinută
evidenţa clară a fiecărei maşini, a celor închiriate, a celor aflate în reparaţii, etc.
Se păstrează de asemenea evidenţa tuturor veniturilor şi cheltuielilor firmei:
cumpărarea de noi maşini, închirierea de maşini, cheltuieli de reparaţii, vânzarea
unor maşini mai vechi din parcul auto (firma preferă să nu păstreze în parcul auto o
maşină mai mult de un an), taxe de asigurare a maşinilor etc.
Firma deţine un portofoliu de clienţi destul de stabil. Pentru clienţii privilegiaţi
oferă reduceri la închirierea de maşini. Aceşti clienţi au de asemenea posibilitatea
de a rezerva o maşină din timp. O maşină poate fi închiriată pentru o perioadă de
timp de la o zi la un an. Plata pentru închirierea unei maşini se poate face cash sau
cu credit card. Se acceptă orice tip de card.
Datele importante despre clienţi precum numele, adresa, numărul de telefon,
seria permisului de conducere, etc. vor fi şi ele memorate în baza de date.
Tema 3: „Firmă IT”. Trebuie să proiectaţi baza de date a unei companii de
dimensiune medie din domeniul IT. Firma livrează diferite produse clienţilor săi, de la
simple aplicaţii create la cerere, până la instalări de echipamente hardware şi
software particularizat. Firma are ca angajaţi diverşi experţi, consultanţi şi personal
auxiliar. Întregul personal este angajat pe termen nelimitat, nu există angajaţi
temporari sau colaboratori. Compania este împărţită în mai multe departamente,
fiecare departament fiind condus de către un angajat din cadrul departamentului
respectiv. Pentru un proiect care trebuie dezvoltat în cadrul firmei, se formează o
echipă de persoane selectate din mai multe departamente. Managerul de proiect
este pe deplin şi exclusiv responsabil de conducerea proiectului, independent de
ierarhia de conducere din cadrul firmei.
Tema 4: „Spital”. Un spital este format din mai multe secţii, precum Pediatrie,
Oncologie, Dermatologie etc. În fiecare secţie sunt internaţi mai mulţi pacienţi, pe
baza recomandării medicului de familie şi a confirmării făcute de către un specialist
al spitalului. La internare, sunt înregistrate datele personale ale pacienţilor. O fişă
separată ţine evidenţa investigaţiilor făcute pacientului pe toată perioada internării,
rezultatele acestor investigaţii, tratamentul aplicat pacientului şi rezultatele obţinute
în urma tratamentelor efectuate. Un pacient este repartizat unui anumit medic care
coordonează toate investigaţiile şi tratamentele aplicate pacientului, însă acesta
poate solicita şi altor colegi să examineze pacientul său. Medicii sunt specialişti în
diverse ramuri ale medicinii, şi pot avea în supraveghere mai mulţi pacienţi, nu
neapărat toţi din aceeaşi secţie.
Tema 5: „Editură”. O editură editează cărţi ştiinţifice din diferite domenii. Cărţile
sunt scrise de autori specializaţi într-un anumit domeniu. Firma are angajaţi mai
mulţi editori care nu sunt neapărat specialişti în diferitele domenii, fiecare editor
fiind responsabil pentru mai multe publicaţii. O carte acoperă unul din domeniile în
care este specialist autorul, fiecare autor lucrează cu un editor, dar poate avea
spre publicare o altă carte de care este responsabil un alt editor.
CAPITOLUL
Limbajul MySQL
În acest capitol veţi învăţa MySQL, limbaj de programare specializat
pentru gestiunea bazelor de date relaţionale pe Internet. Cu ajutorul
platformei EasyPHP, veţi putea lucra uşor pe calculatorul dvs.
Ce este şi de ce învăţăm MySQL ?


Cum rulăm MySQL pe propriul calculator ?
Cum creăm o bază de date ?

Tabele – noţiuni elementare

Tipuri de date, operatori şi funcţii


Afişarea c oloanelor care rezultă în urma unui calcul


Valoarea NULL. Valori implicite
Ce sunt cheile primare şi cheile unice ?



Autoincrementare
Cum sortăm şi cum filtrăm datele ?
Cum actualizăm datele dintr-un tabel ?

Funcţii agregate

Utilizarea subinterogărilor

Cum putem grupa datele ?

Ce sunt uniunile de tabele ?
Cuvinte cheie: tipuri de date, operatori, funcţii, valoare implicită,
cheie primară, cheie unică, autoincrementare, sortare, filtrare,
actualizare, funcţii agregate, subinterogări, grupare, uniune
48
Baze de date – curs introductiv
2.1. Ce este şi de ce învăţăm MySQL ?
În ultimii ani, utilizarea bazelor de date pe Internet a luat o amploare
deosebită. Există o mulţime de aplicaţii, extrem de utile (care le utilizează), cum ar fi:
-
Aplicaţii de contorizare, aplicaţii prin care cei care au creat un site au
posibilitatea să-şi contorizeze numărul de vizitatori ai site-ului respectiv sau,
mai mult, contorizarea se poate extinde la nivel de pagină afişată. Pentru a
evita cu un vizitator, care a deschis de mai multe ori pagina respectivă, să
nu fie contorizat de mai multe ori, se va reţine adresa IP a acestuia.
-
Comerţ electronic, aplicaţii prin care anumite firme îşi promovează şi vând
produsele de care dispun. În acest caz, bazele date vor reţine, pe de o
parte, informaţii despre produse, iar pe de altă parte, comenzile clienţilor.
Avantajele comerţului electronic sunt uriaşe pentru că nu implică cheltuieli
pentru spaţiile de desfacere (magazine) şi, teoretic, oferta se adresează
clienţilor din toată lumea.
-
Votul electronic, aplicaţii prin care se poate afla părerea vizitatorilor
site-ului respectiv referitoare la tema supusă votului. Şi aici este important ca
un vizitator să nu voteze de mai multe ori, motiv pentru care baza de date
reţine adresa IP a vizitatorului.
-
Aplicaţii de comunicare - aplicaţii prin care diverşi vizitatori ai site-ului
respectiv dezbat o anumită problemă, supusă discuţiei. În astfel de cazuri,
bazele de date vor reţine informaţii despre cei care scriu (de multe ori,
aceştia, mai întâi, trebuie să se înscrie în baza de date a site-ului) şi
mesajele acestora.
Există o mulţime de alte aplicaţii ale bazelor de date: site-urile diverselor
ziare, posturi de televiziune, bazele de date create şi exploatate de motoarele de
căutare, etc. Şirul acestora este practic infinit. Iată motivul pentru care ne vom iniţia
în crearea şi exploatarea bazelor de date pe Internet.
1
Ce este SQL ? În practica creării şi utilizării bazelor de date relaţionale s-a impus
necesitatea existenţei unui limbaj standard care permite efectuarea acestor
operaţii. Astfel, a apărut SQL - Structured Query Language. Limbajul este
supervizat de comisia de standardizare ANSI (American National Standards
Institute), motiv pentru care se mai numeşte şi ANSI SQL. SQL nu este un limbaj
de firmă, el este implementat de o mulţime de SGBD-uri, de această dată
consacrate, cum ar fi: Microsoft Access, Oracle, Microsoft SQL Server
şi, bineînţeles, MySQL.
Ce este MySQL ? MySQL este un limbaj specializat pentru gestiunea bazelor de
date relaţionale pe Internet. Aşa cum s-a mai spus, are la bază limbajul SQL.
MySQL gestionează baze de date care se găsesc pe server, iar comenzile pot fi
date cu ajutorul limbajului PHP, dar şi cu alte limbaje, ca de exemplu Java.
1
Revedeţi “Capitolul 1. Proiectarea bazelor de date” deoarece stă la baza tuturor noţiunilor
prezentate aici!
Capitolul 2. Limbajul MySQL

49
Prin utilizarea pachetului EasyPHP putem să instalăm MySQL pe calculatorul
nostru. Vedeţi Anexa 1! Exact în acest mod vom proceda pentru studiul
limbajului MySQL, adică vom crea baze de date pe calculatorul nostru.
2.2. Cum rulăm MySQL pe propriul calculator ?
Dacă ați instalat pachetul EasyPHP, urmând paşii prezentaţi în Anexa 1, ați
observat faptul că avem la dispoziție modulul phpMyAdmin, care ne permite să
creăm și să manipulam baze de date, având o interfață intutivă. De aici putem să





creăm, edităm și să ștergem baze de date și tabele;
executăm comenzi SQL;
importăm / exportăm date din\în fișiere csv;
asigurăm mentenanța serverului de date;
efectuăm căutări în bazele de date, ș.a.m.d
Pentru mai multe informații, accesați pagina oficială a proiectului:
https://phpmyadmin.net
Pe calculatorul nostru putem accesa pagina phpmyadmin din Dashboard, care
poate fi accesat la adresa locală:
http://127.0.0.1:10000/
Se va deschide apoi următoarea fereastră:
Pentru a scrie comenzi SQL, alegem din meniu comanda asociată care va
deschide un editor online unde putem lucra:
50
Baze de date – curs introductiv
Scriem comenzile potrivite apoi apăsăm butonul Execută.
Important. Dacă obțineți erori la crearea tabelelor în paginile ce vor urma,
executați întregul cod sql (copy/paste în editorul SQL) ce se găsește la
adresa de mai jos:
https://raw.githubusercontent.com/phpmyadmin/phpmyadmin/master/
sql/create_tables.sql
(implicit nu este creată o bază de date specifică pentru phpmyadmin)
Să vedem în continuare cum putem crea
prima noastră bază de date!
Capitolul 2. Limbajul MySQL
51
2.3. Crearea unei baze de date

În MySQL, pentru a crea o bază de date se dă comanda:
CREATE DATABASE nume_baza;
În urma acestei comenzi, teoretic, se creează baza de date cu numele
indicat de noi (prima_db în acest prim exemplu):
În fapt, se creează un folder cu numele bazei de date în subfolder-ul data al
folder-ului MySQL, în cazul nostru:
C:\Program Files\EasyPHP-Webserver-14.1b2\binaries\dbserver\data
52
Baze de date – curs introductiv
Dacă există deja o bază de date cu acest nume, se refuză crearea uneia noi:

În cazul în care, după deschiderea aplicaţiei sau în timpul sesiunii de lucru,
se doreşte lucrul cu o anumită bază de date, se dă comada de mai jos:
USE nume_baza;

Pentru ştergerea unei baze de date se utilizează comanda:
DROP DATABASE nume_baza

Uneori, din anumite motive, dorim o listă a bazelor de date existente.
În acest caz, se utilizează comanda de mai jos:
SHOW DATABASES
Interfața grafică a modulului phpmyadmin ne permite bineînțeles să lucrăm și
vizual, precum observați probabil deja – există opțiunea creării unei baze de date
noi direct din lista care se regăsește în partea stângă:
Vom prefera însă în acest curs să ne axăm mai mult pe partea de programare,
deci utilizăm mai des comenzi SQL din motive pur pedagogice.
Capitolul 2. Limbajul MySQL
53
2.4. Tabele. Noţiuni elementare
Într-un tabel coloanele sunt identificabile prin nume, iar rândurile, prin
valorile pe care le memorează. Toate datele dintr-o coloană au acelaşi tip. Un
tabel are un număr specificat de coloane, dar are un număr nespecificat de
rânduri. Uneori, când ne referim la un rând, folosim şi termenul de înregistrare,
iar atunci când ne referim la data din rând, situată într-o anumită coloană, folosim
1
şi termenul de câmp .

O instrucţiune prin care se poate crea un tabel este prezentată mai jos, unde
2
ceea ce este trecut între paranteze drepte este considerat facultativ :
CREATE TABLE nume_tabel
( nume_coloana1 tip_data
nume_coloana2 tip_data
...
nume_coloanan tip_data
);
[specificatori],
[specificatori],
[specificatori]
Specificatorii se referă la cheia primară, valori distincte, valori implicite,
autoincrementare, dacă printre valorile reţinute se poate găsi sau nu valoarea
NULL. Toate acestea sunt tratate separat.
Exemplul 2.1. Se creează un tabel cu 3 coloane: prima conţine codul materialului
şi poate reţine cel mult 5 caractere, a doua conţine denumirea materialului şi poate
reţine până la 20 de caractere, iar ultima reţine cantitatea din fiecare material (în
bucăţi) şi poate reţine un număr natural cu maximum 3 cifre:
CREATE TABLE materiale
(cod char(5),
denumire char(20),
cantitate_buc INT(3)
);

Pentru introducerea rândurilor în tabel se utilizează comanda de mai jos,
unde se introduc, pe rând, toate câmpurile unei linii, în ordinea în care au
fost declarate coloanele:
INSERT INTO nume_tabel VALUES (data1, data2...datan);
Exemplul 2.2. Se inserează în tabel două linii:
INSERT IMTO materiale VALUES(‘001’, ‘panouri’,78);
INSERT IMTO materiale VALUES(‘007’, ‘placi’,0);
Noţiunea de tabel este prezentată pe scurt. O prezentare amănunţită se găseşte în
capitolul anterior, “Proiectarea bazelor de date”.
1
Specificatorii vor fi trataţi separat. Tabelul astfel creat nu conţine nicio înregistrare. Pentru
adăugarea înregistrărilor utilizăm altă instrucţiune MySQL.
2
54
Baze de date – curs introductiv
În practica utilizării bazelor de date, instrucţiunea anterioară este considerată ca
generatoare de erori, prin faptul că se poate greşi ordinea de introducere a datelor,
iar efectul este acela că tabelul va conţine date eronate. Din acest motiv, se
preferă forma de mai jos a instrucţiunii, deşi este necesar să scriem mai mult…

Se inserează în tabel valori pentru coloanele indicate în ordinea în care au
fost declarate coloanele:
INSERT INTO nume_tabel (nume_coloana1,... nume_coloanak)
VALUES (data1,...datak);

Pentru a afişa întreg tabelul se utilizează comanda:
SELECT * FROM nume_tabel
Exemplul 2.3. Pentru tabelul creat anterior se dă comanda:
SELECT * FROM materiale
Figura 2.3. Exemplu de tabel
Există posibilitatea să afişăm numai anumite coloane ale tabelului, în
ordinea pe care o dorim, dacă folosim instrucţiunea de mai jos:
SELECT nume_coloana1,... nume_coloanak FROM nume_tabel

Să observăm faptul că, atunci când afişăm un tabel, în capul său se trece
numele coloanelor din tabel. Dacă dorim ca în capul de tabel să figureze alt
nume pentru o coloană, atunci, în instrucţiunea de mai sus, în loc de a scrie
numai numele coloanei, vom scrie numele coloanei urmat de cuvântul cheie
AS şi de numele care dorim să fie afişat în capul de tabel. Astfel, utilizăm
alias-uri pentru numele coloanelor.
Exemplul 2.4. Pentru tabelul de mai sus vom scrie:
SELECT cod AS codul, denumire AS nume, cantitate_buc AS cantitate
FROM materiale;

Putem vizualiza numele tabelelor existente în baza de date prin utilizarea
instrucţiunii următoare:
SHOW TABLES [FROM nume_baza]

În caz că am uitat care sunt coloanele dintr-un anumit tabel al bazei de date
şi tipul acestora, putem utiliza instrucţiunea:
SHOW COLUMNS FROM nume_tabel
Capitolul 2. Limbajul MySQL
55
2.5. Tipuri de date în MySQL
Aşa cum am văzut, coloanele au un anumit tip. Până în prezent, am utilizat
câteva tipuri fără a oferi o prezentare unitară a acestora. Este momentul s-o facem
acum.
În linii mari, tipurile de date din MySQL se împart în:
a) tipuri care reţin şiruri de caractere;
b) tipuri numerice;
c) tipuri care reţin data, ora.
În continuare, vom prezenta detaliat pe fiecare în parte.
2.5.1. Tipuri de date care reţin şiruri de caractere
Câteva tipuri care reţin şiruri de caractere sunt prezentate mai jos:
Tip
Descriere
CHAR[(n)]
VARCHAR
TINYTEXT
TEXT
MEDIUMTEXT
LONGTEXT
ENUM
SET
Un câmp de acest tip reţine un şir de caractere de lungime
n (fixă). În caz că n nu este precizat, reţine un caracter.
Ocupă n octeţi.
Un câmp de acest tip reţine şiruri de cel mult 255 de
caractere. Un octet reţine lungimea efectivă a şirului.
Ocupă n+1 octeţi.
La fel ca mai sus.
Un câmp de acest tip reţine şiruri de cel mult 65535 de
caractere. Doi octeţi reţin lungimea efectivă a şirului. Ocupă
n+2 octeţi, unde n este numărul de caractere al şirului.
Un câmp de acest tip reţine şiruri de cel mult 16.777.215
caractere. Trei octeţi reţin lungimea efectivă a şirului.
Ocupă n+3 octeţi.
Un câmp de acest tip reţine şiruri de cel mult
4.294.967.295 de caractere. Patru octeţi reţin lungimea
efectivă a şirului. Ocupă n+4 octeţi.
Baza va reţine un vector de şiruri de caractere. Un câmp de
acest tip poate reţine un singur şir de caractere din
vector. De altfel, coloana reţine indicele din şir. Vedeţi
exemplul 2.5!
Baza va reţine un vector de şiruri de caractere.. Un câmp
de acest tip poate reţine unul sau mai multe şiruri de
caractere din vector. De altfel, se reţine vectorul
caracteristic al şirurilor. Vedeţi exemplul 2.6!
Tabelul 2.1. Tipuri de date care reţin şiruri de caractere
56
Baze de date – curs introductiv
Exemplul 2.5. Se creează tabelul ”tstA” care are două coloane: prima reţine un
şir de cel mult 65.535 de caractere şi a doua, un şir din mulţimea şirurilor ”luni”,
”marti”, ”miercuri”. În tabel se inserează 3 linii şi, la sfârşit, tabelul este afişat.
Să observăm că în cazul coloanelor de tip SET,
dacă se încearcă memorarea unui şir inexistent
în definiţia coloanei (în exemplu, şirul ”joi”),
atunci acea coloană va reţine şirul vid.
Figura 2.4.
Tabelul “tstA”
CREATE TABLE tstA
( v1 TEXT,
v2 ENUM (‘luni’,‘marti’,‘miercuri’)
);
INSERT INTO tstA VALUES (‘un sir’,’miercuri’);
INSERT INTO tstA VALUES (‘un sir’,’joi’);
INSERT INTO tstA VALUES (‘alt sir’,’luni’);
SELECT * FROM tstA;
Exemplul 2.6. Se creează tabelul ”tstB” care conţine două coloane c1, de
lungime fixă de 3 caractere şi c2 de tip SET. Un element al coloanei poate reţine o
submulţime a mulţimii {”dimineata”, ”pranz”, ”seara”}.
Pentru a vedea cum se introduce submulţimea,
analizaţi cele trei instrucţiuni INSERT. În figura
alăturată puteţi observa tabelul rezultat în urma
introducerii datelor.
Observaţi faptul că, la ultima inserare, se
încearcă introducerea unui şir, ”noaptea”, care
nu este prezent în definiţia tipului coloanei. Nu se
semnalează eroare, dar şirul nu este introdus.
Figura 2.5. Tabelul “tstB”
CREATE TABLE tstB
(c1 char(3),
c2 SET (‘dimineata’, ‘pranz’, ‘seara’)
);
INSERT
INSERT
INSERT
INSERT
INTO
INTO
INTO
INTO
tstB
tstB
tstB
tstB
VALUES
VALUES
VALUES
VALUES
SELECT c1,c2 FROM tstB;
(‘abc’,‘dimineata,seara’);
(‘abc’,‘seara,pranz’);
(‘abc’,‘seara’);
(‘abc’,‘seara,noaptea’);
Capitolul 2. Limbajul MySQL
57
2.5.2. Tipuri de date numerice
Tipurile numerice se împart la rândul lor în tipuri întregi şi tipuri reale.
O parte dintre tipurile întregi se găsesc în tabelul de mai jos:
Tip
TINYINT
SMALLINT
MEDIUMINT
INT
BIGINT
Descriere
Un câmp de acest tip ocupă 1 octet. Reţine numere întregi
cuprinse în intervalul [-128,127], iar dacă este urmat de
UNSIGNED reţine numere naturale cuprinse în intervalul [0,255].
Un câmp de acest tip ocupă 2 octeţi. Reţine numere întregi
cuprinse în intervalul [-32768,32767], iar dacă este urmat de
UNSIGNED, reţine numere naturale cuprinse în intervalul
[0,65535].
Un câmp de acest tip ocupă 3 octeti. Reţine numere întregi
cuprinse în intervalul [-8.388.608, 8.388.607], iar dacă
este urmat de UNSIGNED, reţine numere naturale cuprinse în
intervalul [0, 16.777.215].
Un câmp de acest tip ocupă 4 octet.i Reţine numere întregi
cuprinse în intervalul [-2.147.483.648, 2.147.483.647], iar
dacă este urmat de UNSIGNED, reţine numere naturale cuprinse
în intervalul [0, 4294967295].
Un câmp de acest tip ocupă 8 octet.i Reţine numere întregi
cuprinse în intervalul [-9.223.372.036.854.775.808,
9.223.372.036.854.775.807], iar dacă este urmat de
UNSIGNED, reţine numere naturale cuprinse în intervalul [0,
18.446.744.073.709.551.615].
Tabelul 2.2. Tipuri de date numerice întregi
Observaţie ! Uneori veţi folosi declaraţii de tip de genul int(4). Aceasta
înseamnă că în coloană se rezervă automat o lăţime de 4 caractere pentru
afişarea numerelor. De exemplu, dacă numărul reţinut este 1, atunci el este afişat
ca bbb1, unde prin b am notat blank-ul. Aceasta nu afectează valorile care pot fi
memorate. De exemplu, dacă dorim să memorăm numărul 12345, acesta va fi
memorat şi se va afişa 12345. Dar, astfel este afectată lăţimea întregii coloane.
Tipurile reale se găsesc în tabelul de mai jos:
Tip
FLOAT
DOUBLE
Descriere
Ocupă 4 octeţi.
Ocupă 8 octeţi.
58
Baze de date – curs introductiv
DECIMAL(n,d)
Numărul este stocat ca şir de caractere. Parametrul n
reprezintă numărul de cifre nenule aflate înaintea virgulei,
plus, dacă este cazul, 1, pentru semnul -, iar d reprezintă
numărul de zecimale. Dacă numărul introdus are înaintea
virgulei un număr de cifre +1 (pentru semn) mai mare decât
n, acesta este trunchiat, iar dacă numărul de zecimale este
mai mare ca d, atunci se reţin exact d zecimale. În acest din
urmă caz, numărul se rotunjeşte la exact d zecimale.
Tabelul 2.3. Tipuri de date numerice reale
Exemplul 2.7. O coloană are tipul decimal(2,3):
Se introduce
1.1
23.4567
1
-5
-15
Se memorează şi afişează
1.100
23.457
1.000
-5.000
-9.999
Tabelul 2.4. Cum se memorează şi se afişează diverse valori cu zecimale
2.5.3. Tipuri de date care reţin anul, data şi ora
În tabelul următor aveţi tipurile care reţin anul, data şi ora:
Tip
YEAR
TIME
DATE
DATETIME
Descriere
Un câmp de acest tip reţine ani. O dată se introduce ca şir
de caractere. De exemplu, pentru anul 2001 se poate
introduce ‘2001’ sau ‘1’, iar pentru anul 1989 se poate
introduce ‘1989’ sau ‘89’.
Un câmp de acest tip reţine ora din zi - se introduce ca şir
de caractere sub forma ‘hh:mm:ss’.
Un câmp de acest tip reţine data. Aceasta se introduce sub
forma ‘yyyy-mm-dd’. De exemplu, ‘1999-11-24’.
Un câmp de acest tip reţine date de forma dată şi oră. O
dată se introduce ca şir de forma:
‘yyyy-mm-dd hh:mm:ss’
Tabelul 2.5. Tipuri de date care reţin anul, data şi ora
Capitolul 2. Limbajul MySQL
59
2.6. Operatori utilizaţi în MySQL
Începem prin a prezenta principalii operatori în ordinea crescătoare a
priorităţii lor. Utilitatea operatorilor va fi evidenţiată în paragrafele următoare,
deocamdată doar îi prezentăm:
1. ||, OR, XOR
2. &&, AND
3. BETWEEN, CASE WHEN, THEN, ELSE
4. ==,>=,<=,<,>,!=,<>,IS,IS,LIKE,IN
5.|
6. &
7. <<, >>
8. -,+ (operatori binari)
9. *, /, DIV, %, MOD
10. ^
11. -,+ (operatori unari)
12. !, NOT
Pentru a putea testa un operator puteţi utiliza instrucţiunea
SELECT. De exemplu, dacă daţi comanda SELECT 1+1;, rezultatul se
1
vede în imaginea alăturată .
Observaţie foarte importantă ! În MySQL există o valoare specială, numită Null.
Semnificaţia ei este valoare necunoscută. Modul în care este posibil ca un câmp
să reţină respectiva valoare va fi prezentat ulterior. Deocamdată reţineţi faptul că,
dacă Null este un operand, atunci rezultatul oricărei operaţii care se efectuează
cu Null este Null. Evident, dacă operandul este Null, atunci el este
necunoscut, iar operaţia va avea rezultat necunoscut, indiferent de celălalt operand
sau de tipul operaţiei.
Exemplul 2.8. 1+NullNull sau Null=NullNull.
Operatorii se împart, aşa cum suntem deja obişnuiţi din alte limbaje de programare,
în mai multe grupe. Acestea sunt prezentate în continuare.
2.6.1. Operatori aritmetici
Operatorii aritmetici acţionează asupra tipurilor numerice şi returnează o
valoare de tip numeric. Pot fi analizaţi în Tabelul 2.6.
În cele ce urmează, pentru a evidenţia rezultatul unei operaţii, vom utiliza caracterul ““.
Spre exemplu, 1+1  2.
1
60
Baze de date – curs introductiv
Operator
Operaţie
+
adunare
-
scădere
*
/
înmulţire
împărţire
DIV
împărţire întreagă
MOD sau %
restul împărţirii întregi
-, +
Minus şi plus, operatori unari
Rezultat
2+3
 1;
2 - 3  -1;
3.5*26
5 / 2  2.5;
5 DIV 2=2;
-5 DIV 2 =-2
5 MOD 21
-5 MOD 2 -1
5 % 2 1;
-5 % 2  -1
--11
Tabelul 2.6. Operatori aritmetici
2.6.2. Operatori de comparare
Pot fi comparate două valori numerice sau două şiruri. Şirurile se compară
lexicografic (ordinea din dicţionar) şi nu se face distincţie între literele mari şi cele
mici. Rezultatul este 1 pentru adevărat şi 0 pentru fals.
Operaţie
Operator
<
<=
>
>=
=
<> sau !=
mai mic.
mai mic sau egal
mai mare
mai mare sau egal
egalitate
diferit
Rezultat
2 < 1  0;
1 <2  0;
‘ab’<b  1;
2 <=2  1;
3>2 1
‘b’>’ab’ 1
7>=7  1;
7 XOR 8  0;
7=71
‘un’=’UN’1
1<>21;
1!=21;
1<>10’
1!=10;
Tabelul 2.7. Operatori de comparare
Observaţie ! Se pot compara şi date de tipul TIME, DATE, etc. În fapt, o astfel de
comparare este lexicografică. Vedeţi exemplul 2.9!
Capitolul 2. Limbajul MySQL
61
Exemplul 2.9. Analizaţi operaţiile de comparare de mai jos:
‘1:12:3’<‘2:00:00’1, ‘1999-12-29’= ‘1999-12-29’1.
‘1:12:3’<‘13:00:00’0 - compararea s-a facut lexicografic, motiv pentru
care rezultatul este eronat.
‘01:12:3’<‘13:00:00’1 pentru ca rezultatul să fie corect, chiar dacă
compararea este lexicografică, trebuie ca orele, minutele, secundele să fie cu
acelaşi număr de cifre. De fapt, atunci când se memorează în baza de date o astfel
de valoare, operaţia este făcută automat. Acesta este motivul pentru care
comparările efectuate cu date memorate în baza de date sunt corecte.
2.6.3. Operatori logici
În MySQL se consideră 2 valori logice: false, reprezentat de 0 şi true
reprezentat de 1 şi de orice valoare diferită de 0. Operatorii logici acţionează
asupra valorilor logice şi returnează 1, pentru adevărat şi 0, pentru fals.
Operator
Operaţie
|| sau OR
sau logic, dacă ambii operanzi sunt 0,
rezultatul este 0, altfel rezultatul este 1.
&& sau
AND
şi, dacă ambii operanzi sunt diferiţi de
0, rezultatul este 1, altfel rezultatul este
0.
NOT
negare, dacă operandul este 0,
rezultatul este 1, altfel rezultatul este 0.
XOR
sau exclusiv, dacă un operand este 0 şi
altul diferit de 0, rezultatul este 1, altfel,
rezultatul este 0.
Rezultat
2 || 1  1;
0 || 1  1;
0 || 0  0;
2 && 1  1;
2 && 0  0;
0 && 0  0;
NOT 30;
NOT 1=0;
NOT 0=1;
7 XOR 0  1;
7 XOR 8  0;
0 XOR 0  0;
Tabelul 2.8. Operatori logici
2.6.4. Operatori logici pe biţi
Se aplică tipurilor întregi şi acţionează asupra tuturor biţilor aflaţi pe poziţii
corespondente.
Operator
|
&
Operaţie
sau pe biţi, dacă ambii biţi sunt 0,
rezultatul este 0, altfel rezultatul este 1.
şi pe biţi, dacă ambii biţi sunt 1,
rezultatul este 1, altfel rezultatul este 0.
Rezultat
2 | 1  3
2 & 1  0
62
Baze de date – curs introductiv
^
~
sau exclusiv pe biţi, dacă biţii sunt
diferiţi, rezultatul este 1, altfel rezultatul
este 0.
negare, un bit 0 devine 1, un bit 1
devine 0.
10^39
(1010
^00111001)
~0...011...10
Tabelul 2.9. Operatori logici pe biţi
2.6.5. Operatori de deplasare
Se aplică tipurilor întregi şi acţionează asupra tuturor biţilor aflaţi pe poziţii
corespondente.
Operator
<<
>>
Operaţie
deplasare stânga, deplasare către stânga
a biţilor operandului din stânga cu k poziţii,
unde k este operandul din dreapta. Poziţiile
rămase libere se completează cu 0.
deplasare dreapta, deplasare către
dreapta a biţilor operandului din stânga cu k
poziţii, unde k este operandul din dreapta.
Rezultat
1<<24
(1 trece în 100)
4>>21
(100 trece în 1)
Tabelul 2.10. Operatori de deplasare
2.6.6. Alţi operatori
Operatorii IS NULL, IS NOT NULL testează dacă o valoare este sau nu NULL
(sunt singurii operatori prin care se testează acest lucru)!
Exemplul 2.10. Analizaţi operaţiile următoare: 1 IS NULL  0;, NULL IS
NULL  1;, 1 IS NOT NULL  1;, NULL IS NOT NULL  0;.
Operatorii IN, NOT IN testează apartenenţa unei valori la o mulţime. Valoarea
poate fi de formă numerică sau de un tip care reţine un şir de caractere. Importanţa
mare pe care o au aceşti operatori va rezulta studiind paragrafele următoare.
Exemplul 2.11. Analizaţi operaţiile următoare: 1 IN(1,2,3,4)  1;,
5 IN(1,2,3,4)  0;, ‘1sir’ IN (‘1sir’,’2sir’,’3sir’)  1;,
‘4sir’ IN (‘1sir’,’2sir’,’3sir’)  0;.
Operatorul LIKE, NOT testează dacă un şir de caractere îndeplineşte anumite
condiţii: dacă este prefixat sau nu de un anumit subşir, dacă este postfixat sau nu
de acesta sau dacă subşirul se găseşte în interior. Pentru substituirea unui număr
neprecizat de caractere necunoscute se utilizează caracterul ”%”, iar pentru un
singur caracter neprecizat se utilizează caracterul ”_”.
Capitolul 2. Limbajul MySQL
63
Exemplul 2.12. Analizaţi operaţiile următoare:
‘popescu’ LIKE ‘pop%’1; (‘popescu’ este prefixat de subşirul ‘pop’),
‘ponescu’ LIKE ‘pop%’0; (‘ponescu’ nu este prefixat de subşirul ‘pop’),
‘ionescu’ LIKE ‘%escu’1 (‘ionescu’ este postfixat de subşirul ‘escu’).
Operatorul BETWEEN min AND max testează dacă o valoare se găseşte între o
valoare minimă şi una maximă. În caz afirmativ returnează 1, altfel, 0. Se poate
aplica şi pentru date care reţin şiruri de caractere (ordinea lexicografică), dar şi
pentru datele de timp.
Exemplul 2.13. Analizaţi operaţiile următoare: 1 BETWEEN 0 AND 4 1;,
‘mama’ BETWEEN ‘min’ AND ‘lin’ 1;, 2 BETWEEN 2 AND 2 1;,
1 BETWEEN 2 AND 4 0;, ‘1999-10-31’ BETWEEN ‘1989-12-10’ AND
‘2000-01-01’1.
Operatorul CASE WHEN THEN ELSE. Poate fi aplicat în două forme:
Forma 1. Se evaluează v şi dacă produce valoarea vi se returnează valoarea
vali, iar dacă nicio condiţie vi nu este îndeplinită, se returnează valoarea valn+1:
CASE v
WHEN v1 THEN val1
[WHEN v2 THEN val2]
...
[WHEN vn THEN valn]
[ELSE valn+1]
END
Exemplul 2.14. Se afişează ‘doi’:
CASE 2
WHEN 1 THEN ‘unu’
WHEN 2 THEN ‘doi’
WHEN 3 THEN ‘trei’
ELSE ‘alta valoare’
END;
Forma 2. În această formă, dacă este îndeplinită condiţia i, se returnează
valoarea vi,. Dacă niciuna din condiţiile vi nu este îndeplinită, se returnează
valoarea vn+1:
CASE
WHEN conditie1 THEN v1
[WHEN conditie2 THEN v2]
...
[WHEN conditien THEN vn]
ELSE vn+1
END
64
Baze de date – curs introductiv
Exemplul 2.14. Se afişează ‘adevarat’:
CASE
WHEN 1<2 THEN ‘adevarat’
ELSE “nu se poate’
END;
2.7. Funcţii MySQL
În MySQL există o serie de funcţii predefinite. Întrucât astfel de funcţii au fost
prezentate pentru limbajul studiat (Pascal sau C/C++), în acest paragraf vor fi
tratate pe scurt. Pot fi testate prin utilizarea instrucţiunii SELECT.
2.7.1. Câteva funcţii matematice
Funcţie
ABS(x)
Descriere
Modul de x.
CEIL(x)
Cel mai mic întreg mai mare sau
egal cu x.
FLOOR(X)
Cel mai mare întreg mai mic sau
egal cu x.
EXP(x)
LOG(b,x)
ex
Logaritm în baza b din x.
PI()

POW(x,y)
xy
ROUND(x)
Cel mai apropiat întreg de x.
SIN(x)
COS(x)
Sinus de x.
Cosinus de x.
SIGN(x)
Semnul lui x: -1, dacă x<0, 0, dacă
x=0, 1 dacă x>0.
SQRT(x)
Radical din x.
Rezultat
ABS(-2)  2;
CEIL(1.7) 2;
CEIL(2)2;
CEIL(-1.7)-1;
FLOOR(-1.7) -2
FLOOR(2)  2;
FLOOR(1.7) 1;
EXP(1) 2.7182...
LOG(2,4) 2;
PI()3.141593
POW(2,3)8
ROUND(2.3)2;
ROUND(2.7)3;
ROUND(-2.8)-3;
SIN(PI()/2)1;
COS(0) 1
SIGN(2)  1;
SIGN(0)  0;
SIGN(-2)  -1;
SQRT(4)  2;
Tabelul 2.11. Funcţii matematice
Capitolul 2. Limbajul MySQL
65
2.7.2. Câteva funcţii care lucrează asupra şirurilor de caractere
Funcţie
Descriere
LENGTH(x)
Lungimea şirului x.
CONCAT(x1
,x2,..)
Concatenează şirurile x1,x2,….
INSTR(x,y)
SUBSTRING(x,
p,l)
RTRIM(x)
LTRIM(x)
TRIM(x)
UPPER(x)
LOWER(x)
FIND_IN SET
(x,’s1,s2,
..sn’)
FORMAT(x,d)
STRCMP(x,y)
Caută dacă y este subşir pentru
x. În caz afirmativ, returnează
indicele de început (indicii încep
cu 1), altfel returnează 0.
Returnează subşirul din x care
începe în poziţia p şi are
lungimea l.
Returnează şirul fără blank-urile
din dreapta.
Returnează şirul fără blank-urile
din stânga.
Returnează şirul fără blank-urile
din stânga şi din dreapta.
Returnează şirul scris cu litere
mari.
Returnează şirul scris cu litere
mici.
Returnează indicele apariţiei
şirului x în şirul de şiruri
‘s1,s2,...,sn’. Dacă x nu
este găsit, returnează 0.
Converteşte numărul real x la
un şir cu d zecimale. Pentru
ultima zecimală se face, dacă
este cazul, rotunjirea.
Compară lexicografic şirurile x
şi y. Dacă x<y returnează -1,
dacă x=y returnează 1, iar dacă
x>y, returnează 1.
Rezultat
LENGTH(‘abc’)  3;
CONCAT(‘ab’,’c’)
 ‘abc’
INSTR(‘abc’,’b’)2
INSTR(‘abc’,’d’)0
SUBSTRING(‘abc’,2,1)
’b’
RTRIM(‘un
LTRIM(‘
‘)’un’
un’) ’un’
TRIM(‘ un ‘)’un’
UPPER(‘Un’) ’UN’
LOWER(‘Un’) ’un’
FIND_IN_SET
(‘b’,’a,b,c’)  2
FORMAT(1.789,2)
1.79
STRCMP(‘ma’,’mama’)
-1
Tabelul 2.12. Funcţii care lucrează asupra şirurilor de caractere
2.7.3. Câteva funcţii care lucrează asupra datei şi orei
Funcţie
NOW()
Descriere
Returnează data şi ora sub forma
yyyy-mm-dd hh:mm:ss.
Rezultat
66
Baze de date – curs introductiv
Dacă x este de tipul DATA,
afişează anul extras din x.
YEAR(x)
DAY(X)
Ca mai sus, extrage ziua.
MONTH(x)
Ca mai sus, extrage luna.
TIME(x)
Ca mai sus, extrage ora.
HOUR(x)
Ca mai sus, extrage ora ca
număr între 0 şi 23.
MINUTE
Ca mai sus, extrage minutul.
DATEDIFF
(x,y)
DATE_ADD
(data,INTERV
AL,nr, x)
DATE_SUB
(data,INTERV
AL,nr, x)
x şi y sunt de tip DATETIME sau
DATE. Calculează diferenţa în zile
dintre x şi y.
Calculează data care se obţine
dacă la valoarea data se adună
nr, unde x specifică ce este nr:
YEAR - ani, DAY - zile,
MONTH - luni.
La fel ca mai sus, numai că se
obţine data diferenţă.
YEAR(NOW())
returnează anul curent.
DAY(NOW())returnează
ziua curentă.
MONTH(NOW())
returnează luna curentă.
TIME(NOW())
returnează ora curentă.
HOUR(NOW())
returnează ora curentă
ca număr între 0 şi 23.
MINUTE(NOW())
returnează minutul
curent
DATEDIFF(NOW(),
’1989-12-21’)
DATE_ADD(NOW(),
INTERVAL, 10 DAY)
Se obţine data care va fi
peste 10 zile.
DATE_SUB(NOW(),
INTERVAL, 10 DAY)
Se obţine data care a
fost acum 10 zile.
Tabelul 2.13. Funcţii care lucrează asupra datei şi orei
2.7.4. Două funcţii speciale
Funcţia IF are forma de mai jos, unde expresie1 este de un tip întreg. Dacă
expresie1 este nenulă, atunci se returnează expresie2, altfel se returnează
expresie3. Atenţie: dacă expresie1 este de tip real, se rotunjeşte la cel mai
apropiat întreg. Dacă, de exemplu, acesta este 0.41, atunci se rotunjeşte la 0, prin
urmare, rezultatul va fi altul...
IF(expresie1,expresie2,expresie3)
Exemplul 2.15. Analizaţi exemplele următoare: IF (1>2, ‘adevarat’,
’fals’)  ‘adevarat’, IF (0.45, ‘nu’,’da’) ’da’;.
Funcţia IFNULL are forma de mai jos. Dacă expresie1 nu este NULL, returnează
expresie1,, altfel returnează expresie2.
IFNULL(expresie1, expresie2)
Capitolul 2. Limbajul MySQL
67
Exemplul 2.16. Analizaţi exemplele următoare: IFNULL (0,‘este null’) 
0, IFNULL (NULL,‘este NULL’) ’este NULL’.
2.8. Afişarea coloanelor care rezultă în urma unui calcul
O regulă elementară în crearea şi utilizarea bazelor de date spune că
acestea vor reţine numai date care nu rezultă în urma unui calcul.
Nerespectarea ei conduce la baze de date care ocupă mult spaţiu. Acum vom
învăţa să afişăm datele care rezultă în urma unui calcul.
Exemplul 2.17. Priviţi tabelul din Fig. 2.6, numit ”prod”, care reţine produsele
existente într-un depozit. Pentru fiecare produs se cunoaşte cantitatea (”cant”) şi
preţul unitar (”pret_unitar”), preţul unui exemplar din produsul respectiv. Să
presupunem că dorim ca, pe lângă informaţiile afişate, să aflăm valoarea totală
pentru fiecare produs în parte. Valoarea se obţine ca produs între cantitate şi preţul
unitar.
Figura 2.6. Tabelul “prod”
Pentru aceasta, atunci când afişăm tabelul, vom crea o nouă coloană sub forma:
expresie AS nume_coloana, unde expresie calculează valorile din coloana
respectivă, iar ”nume_coloana” va fi numele ei. Iată cum se afişează noul tabel,
prezentat mai jos:
Figura 2.7.
Tabelul rezultat
SELECT den, cant, pret_unitar,
cant*pret_unitar AS valoare FROM prod;
Exemplul 2.18. Se dă tabelul alăturat, numit ”persoane”.
Se cere să se separe numele de prenume şi să se
afişeze datele ca mai jos:
Figura 2.9.
Tabelul dorit
Figura 2.8. Tabelul
“persoane”
68
Baze de date – curs introductiv
Rezolvare. Se utilizează funcţii care operează asupra şirurilor de caractere:
SELECT SUBSTRING(nume,1,INSTR(nume,’ ‘)-1)
AS prenume
SUBSTRING(nume, 1+INSTR(nume,’ ‘),LENGTH(nume)) AS nume
FROM persoane;
Exemplul 2.19. Se consideră tabelul din Fig. 2.10, numit ”pers”, care cuprinde
numele şi data naşterii pentru două persoane:
Figura 2.10. Tabelul
“pers”
Se cere să se afişeze numele şi vârsta
fiecărei persoane.
Figura 2.11.
Tabelul dorit
Rezolvare. Se utilizează funcţii care operează asupra câmpurilor de tip DATE şi
DATETIME.
SELECT nume, YEAR(NOW())-YEAR(data_n) AS varsta FROM pers;
Exemplul 2.20. Se consideră un tabel, numit ”numar”,
alcătuit dintr-o singură coloană, c de tip INT. Se cere să
se listeze acea coloană şi o alta, numită ”paritate”,
care să conţină două valori: ‘par’ dacă numărul din c
este par şi ‘impar’, în caz contrar (vezi figura alăturată).
SELECT c, IF(C MOD 2, ‘impar’,’par’) AS
paritate FROM numar;
Figura 2.12.
Tabelul rezultat
2.9. Valoarea NULL
În MySQL, aşa cum s-a arătat, există o valoare specială, numită NULL.
Semnificaţia ei este “nicio valoare“.
Atunci când definim o coloană se poate trece specificatorul NULL. Oricum,
se asumă implicit, NULL. De altfel, acest lucru poate fi testat. Creaţi un tabel, de
exemplu, cu o coloană de un anumit tip, fără a specifica NULL sau NOT NULL şi
apoi daţi comanda SHOW COLUMNS FROM nume_tabel; şi analizaţi tabelul
afişat! Exerciţiu!
Capitolul 2. Limbajul MySQL
69
a) Atunci când o coloană are trecut specificatorul NULL sau nu s-a trecut nimic şi
la introducerea unui rând, pentru coloana respectivă, nu este trecută o valoare
pentru acel câmp, acolo se va memora valoarea specială NULL.
b) Atunci când o coloană are trecut specificatorul NOT NULL şi la introducerea
unui rând, în coloana respectivă, nu este trecută o valoare, acolo se va memora:
-
0, dacă coloana este de tip numeric;
-
şirul vid, dacă coloana este de un tip care permite reţinerea de şiruri;
-
indicele 0 din şir, dacă coloana este de tip ENUM şi aceasta are ca efect
afişarea primului şir al enumerării;
-
mulţimea vidă, dacă coloana este de tip SET.
Analizaţi exemplele următoare şi verificaţi, de fiecare dată, tabelul afişat.
Exemplul 2.21. Rulaţi secvenţa de mai jos şi se va afişa
tabelul alăturat:
CREATE TABLE testnull
(c1 INT NULL,
c2 INT NOT NULL);
INSERT INTO testnull (c2) VALUES (10);
INSERT INTO testnull (c1) VALUES (7);
Figura 2.13.
Tabelul rezultat
SELECT * FROM testnull;
Exemplul 2.22. Se creează tabelul alăturat, în care
coloanele reţin şiruri de caractere:
CREATE TABLE testnull1
(c1 TEXT NULL,
c2 TEXT NOT NULL);
INSERT INTO testnull1(c1) VALUES (‘Un sir’);
INSERT INTO testnull1(c2) VALUES (‘Alt sir’);
Figura 2.14.
Tabelul rezultat
SELECT * FROM testnull1;
Exemplul 2.23. Se creează tabelul din figura alăturată, în
care coloanele reţin date de tip ENUM:
CREATE TABLE testnull2
( c1 ENUM(‘sir1’,’sir2’,’sir3’) NULL,
c2 ENUM(‘sir1’,’sir2’,’sir3’) NOT NULL);
INSERT INTO testnull2(c1) VALUES (‘sir2’);
INSERT INTO testnull2(c2) VALUES (‘sir1’);
SELECT * FROM testnull2;
Figura 2.15.
Tabelul rezultat
70
Baze de date – curs introductiv
Exemplul 2.24. Se creează tabelul alăturat, în care
coloanele reţin date de tip SET.
CREATE TABLE testnull3
( c1 SET(‘sir1’,’sir2’,’sir3’) NULL,
c2 SET(‘sir1’,’sir2’,’sir3’) NOT NULL);
INSERT INTO testnull2(c1) VALUES (‘sir1,sir2’);
INSERT INTO testnull2(c2) VALUES (‘sir3’);
Figura 2.16.
Tabelul rezultat
SELECT * FROM testnull3;
Aşa cum am arătat, semnificaţia lui NULL este “nicio valoare”. De asemenea, am
învăţat că o operaţie în care un operand este NULL, va avea rezultatul NULL. Acest
fapt este util, pentru că, în caz contrar s-ar putea ajunge la rezultate false.
Exemplul 2.25. Tabelul alăturat
“elev“ prezintă numele, nota la
engleză şi nota la franceză
pentru doi elevi. Unul dintre ei,
nu are notă la franceză (NULL).
Figura 2.17. Tabelul “elev”
Se cere să se calculeze mediile celor doi
elevi. Scriem interogarea:
SELECT nume,
(engleza+franceza)/2 AS media;
Figura 2.18. Rezultatul interogării
Să observăm că pentru elevul căruia nu i se cunoaşte nota la franceză, nu i
se cunoaşte nici media. Logic vorbind, aşa este corect. Dacă nu se cunoaşte o
notă, nu se cunoaşte nici media deoarece n-ar fi normal ca pentru acest elev să se
afişeze media 10...
2.10. Valori implicite
În practică, nu întotdeauna se cunosc datele în totalitate. În astfel de cazuri,
atunci când pentru un anumit rând nu se cunoaşte un câmp, fie acesta va reţine
NULL, fie va reţine o valoare implicită, convenabil aleasă. De exemplu, dacă la un
examen de admitere un elev nu se prezintă la o probă, se poate lua decizia ca, la
acea probă, elevul să primească nota 1.
Pentru ca un câmp, în absenţa datelor să aibă o valoare implicită, se
foloseşte specificatorul DEFAULT:
DEFAULT valoare_implicita

Facem observaţia că pot lua valori implicite câmpurile cu lungime fixă.
De exemplu, un câmp declarat CHAR(20) poate lua o valoare implicită, dar
unul declarat TEXT nu poate lua o astfel de valoare.
Capitolul 2. Limbajul MySQL
71
Exemplul 2.26. În tabelul următor, se reţin numele şi oraşul de domiciliu pentru
mai multe persoane:
Figura 2.19.
Tabelul propus
Dacă oraşul de domiciliu nu este cunoscut, se preferă, în locul valorii NULL, să fie
afişat şirul ‘necunoscut’:
CREATE TABLE pers_oras
(nume CHAR (25),
domiciliu CHAR(30) DEFAULT ‘necunoscut’);
INSERT into pers_oras (nume) VALUES (‘Gulagea Constantin’);
INSERT into pers_oras VALUES (‘Ionescu Mihai’, ‘Galati’ );
SELECT * FROM pers_oras;
2.11. Cheie primară şi cheie unică
A) Cheia primară este constituită dintr-un câmp (sau mai multe câmpuri) şi trebuie
să îndeplinească simultan condiţiile:
a) Valorile reţinute de coloana care alcătuieşte cheia primară trebuie să fie
distincte. În cazul în care cheia este alcătuită din mai multe coloane, pentru a
avea două chei distincte, este necesar ca acestea să fie diferite pentru cel
puţin o coloană dintre ele. Tentativa de a înscrie în tabel o înregistrare care are
cheia primară identică cu alta, existentă în tabel, este sancţionată cu eroare.
b) Câmpul (câmpurile) care alcătuieşte (alcătuiesc) cheia primară trebuie să
aibă o lungime fixă. De exemplu, nu poate fi cheie primară un câmp de tip TEXT.
Raţiunea existenţei cheii primare este dată de accesul foarte rapid la
înregistrarea de cheie dată. Trebuie ştiut că înregistrările unui tabel se reţin în
ordinea introducerii lor. Atunci când, de exemplu, un câmp este declarat cheie
primară, se construieşte un tabel auxiliar, invizibil pentru utilizator, în care pentru
fiecare valoare din câmpul cheie primară se reţine poziţia rândului care are acea
cheie. În acel tabel, cheile sunt în ordine crescătoare (dacă este vorba de şiruri de
caractere, acestea se reţin în ordine lexicografică, ca mai jos). Pornind de la cheie,
în tabelul “invizibil” se identifică rapid rândul cu acea cheie. În acest caz, se
foloseşte căutarea binară, algoritm studiat la informatică (revedeţi) şi, după cum
ştiţi, o astfel de căutare se face în O(log(n)). Din acel rând se află poziţia
înregistrării cu acea cheie din tabelul iniţial. De aici, accesul la înregistrare este
imediat. Căutarea clasică se efectuează în O(n).
72
Baze de date – curs introductiv
Exemplul 2.27. Presupunem că tabelul principal are drept cheie primară câmpul
"Nume":
Tabel principal
Nume
Ion
Maria
Ana
Cristian
Mihai
Vârstă
15
17
21
12
18
Înălţime (cm)
173
159
159
171
182
Tabel “invizibil”
Nume
Ana
Cristian
Ion
Maria
Mihai
Poziţie
3
4
1
2
5
Pentru a preciza că o anumită coloană este cheie primară se foloseşte, atunci când
se descrie coloana, specificatorul PRIMARY KEY.
Exemplul 2.28. Se creează un tabel în care prima coloană este cheie primară:
CREATE TABLE ex_cheie_primara_un_camp
(c1 INT PRIMARY KEY,
c2 TEXT
);
Dacă cheia primară este alcătuită din mai multe câmpuri, după descrierea
coloanelor, se utilizează specificatorul PRIMARY KEY sub forma:
PRIMARY KEY(nume_col1, nume_col2,...)
Exemplul 2.29. În tabelul următor cu trei coloane, coloanele c1 şi c2 alcătuiesc
cheia primară:
CREATE TABLE cheie_primara_doua_campuri
(c1 INT,
c2 CHAR(10),
c3 TEXT,
PRIMARY KEY(c1,c2)
);
B) Cheie unică - se poate cere ca o coloană (sau mai multe) să conţină numai
valori distincte. Pentru aceasta se va utiliza specificatorul UNIQUE KEY. În acest
caz, dacă în coloana respectivă se va încerca o inserare cu o valoare care există
deja, se va semnala eroare.
Observaţie ! Şi în acest caz, nu este permis să solicităm valori distincte pentru o
coloană de un tip de lungime variabilă (cum ar fi, de exemplu, tipul TEXT).
Exemplul 2.30. Se creează un tabel în care în ambele coloane vor fi numai valori
distincte:
CREATE TABLE distincte
( c1 INT UNIQUE KEY,
c2 char(10) UNIQUE KEY
);
Capitolul 2. Limbajul MySQL
73
2.12. Autoincrementare
Cu siguranţă, aţi văzut o mulţime de tabele în care rândurile sunt
numerotate. Mai jos, aveţi un astfel de tabel, cu numele unor persoane:
Figura 2.20. Tabelul cu
număr de ordine
Este incomod, ca la introducerea fiecărui rând să se specifice numărul de
ordine pentru rândul respectiv. Din acest motiv, s-a pus la dispoziţia clienţilor un
mecanism prin care incrementarea se face automat.
Pentru ca o coloană să reţină numerele de ordine al rândurilor respective,
este necesar ca, la definirea ei, să se utilizeze specificatorul AUTO_INCREMENT.
Pentru a putea utiliza acest specificator, este necesar să fie îndeplinite condiţiile:
a) coloana să fie de un tip întreg;
b) coloana să reţină numai valori distincte - pentru a determina aceasta,
coloana trebuie să fie declarată ca fiind cheie primară sau cu cheie unică.
Exemplul 2.31. Iată cum am creat tabelul din Fig. 2.20, numit ”auto”:
CREATE TABLE auto
(nr_ord INT UNIQUE KEY AUTO_INCREMENT,
nume CHAR(20)
);
INSERT INTO auto (nume) VALUES(‘Marius Oprean’);
INSERT INTO auto (nume) VALUES(‘Mihai Minca’);
Există şi posibilitatea să se introducă valori dorite în coloana declarată cu
autoincrementare. În acest caz, la următoarele introduceri, valorile implicite vor fi
obţinute pornind de la valoarea introdusă.
Exemplul 2.32. Analizaţi tabelul alăturat,
obţinut din cel anterior, la care s-au mai făcut
inserările de mai jos:
Figura 2.21. Tabel
modificat
INSERT INTO auto VALUES(7,‘Doru Cran’);
INSERT INTO auto (nume) VALUES(‘Dan Bitu’);
74
Baze de date – curs introductiv
2.13. Sortarea datelor
Uneori este necesar ca datele să fie afişate sortate
după valorile unei coloane sau după valorile mai
multor coloane. Dacă acestea sunt de tip şir de
caractere, ele pot fi sortate în ordine lexicografică.
Alăturat aveţi un tabel, numit “sortare”, pe care
vom exersa modul de afişare a datelor sortate după
anumite criterii.
Figura 2.22. Tabel “sortare”
Exemplul 2.33. Datele sunt afişate sortate crescător,
după valorile existente în coloana ”nume”. Să
observăm că sortarea crescătoare este cea implicită,
pentru a o obţine nu este necesar să o specificăm:
SELECT * FROM sortare ORDER BY nume;
Figura 2.23. Tabelul sortat crescător
Exemplul 2.34. Pentru a sorta datele descrescător,
se foloseşte specificatorul DESC. Mai jos, am sortat
datele descrescător după valorile câmpului
”data_n” (data naşterii):
SELECT * FROM sortare ORDER BY
data_n DESC;
Figura 2.24. Tabelul sortat
descrescător după data naşterii
Există posibilitatea să sortăm datele (crescător sau descrescător) după valorile
existente în mai multe coloane. Practic, mai întâi se sortează datele după prima
coloană specificată, apoi, păstrând această ordine, după a doua coloană, ş.a.m.d.
Exemplul 2.35. Datele sunt sortate crescător
după valorile existente în coloana ”nume”, apoi,
păstrând această ordine, descrescător după
valorile din coloana ”data_n”.
SELECT * FROM sortare ORDER BY nume,
data_n DESC;
Figura 2.25. Tabelul sortat crescător
după ambele coloane
Observaţie ! Avem două persoane cu numele ”Mihai”. Mai întâi este afişată
persoana născută în 1980, apoi cea născută în 1975 (sortate descrescător după
câmpul ”data_n”).
Capitolul 2. Limbajul MySQL
75
Exemplul 2.36. Există posibilitatea să afişăm
numai un număr dorit de rânduri. Pentru aceasta
se foloseşte clauza LIMIT, ca mai jos:
SELECT * FROM sortare ORDER BY nume
LIMIT 3;
Figura 2.26. Afişarea unor rânduri din tabel
2.14. Filtrarea datelor
Uneori nu suntem interesaţi să fie afişate toate liniile tabelului, ci numai
unele, care îndeplinesc anumite condiţii. O astfel de operaţie se numeşte
filtrare. Pentru a realiza operaţia de filtrare se ataşează instrucţiunii SELECT, la
sfârşit, clauza WHERE condiţie. În acest fel, sunt selectate numai liniile pentru
care condiţia din clauza WHERE este îndeplinită. În cazul în care datele se cer
sortate, clauza ORDER BY se va trece după WHERE.
Exemplul 2.37. Se consideră un tabel precum cel de mai jos, în care se prezintă
situaţia şcolară a elevilor unei clase:
CREATE TABLE elevi
( nume TEXT,
matematica INT, engleza INT, informatica INT);
Figura 2.27. Tabelul “elevi”
1. Afişaţi numele elevilor care au la matematică note
mai mari sau egale cu 8.
SELECT nume FROM elevi
WHERE matematica>=8;
Figura 2.28.
Exemplu de filtrare
2. La fel ca mai sus, numai că se cere ca numele
elevilor să fie afişate în ordine alfabetică.
SELECT nume FROM elevi
WHERE matematica>=8
ORDER BY nume;
Figura 2.29.
Exemplu de filtrare
76
Baze de date – curs introductiv
3. Se cere să se afişeze numele elevilor care au promovat la fiecare materie şi
media generală pe care aceştia o au.
SELECT nume, (matematica+engleza+informatica)/3 AS media
FROM elevi
WHERE matematica>4 AND engleza>4 AND informatica>4;
Figura 2.30.
Exemplu de filtrare
Observaţie ! Filtrarea datelor este un caz considerat particular al unui concept cu
mult mai general, interogarea! De obicei, interogăm o bază de date cu ajutorul
instrucţiunii SELECT.
2.15. Actualizări într-un tabel
În general, prin actualizarea unui tabel înţelegem modificarea datelor
reţinute de acesta şi/sau modificarea structurii sau numelui tabelului.
A) Prin actualizarea datelor dintr-un tabel înţelegem operaţii precum inserarea
unor linii, modificarea valorilor unor câmpuri şi ştergerea unor rânduri.
A1) Pentru inserare, putem utiliza instrucţiunile de mai jos:
1. INSERT INTO nume_tabel [(nume_col1, nume_col2..)
VALUES(expresie1, expresie2...)
Această instrucţiune a fost deja prezentată, nu vom mai reveni asupra ei.
2. INSERT INTO [DISTINCT} nume_tabel [(nume_col1, nume_col2..)
SELECT ....
Într-un tabel se pot insera linii dintr-un alt tabel. Pentru aceasta se foloseşte
instrucţiunea de mai sus (vezi Exemplul 2.38, pct. 1). Dacă se doreşte inserarea
numai a liniilor distincte din tabelul sursă, utilizaţi specificatorul DISTINCT.
A2) Pentru a modifica valorile reţinute de un câmp sau mai multe, se utilizează
instrucţiunea de mai jos (vezi Exemplul 2.38, pct. 2):
UPDATE nume_tabel
SET coloana1=expresie1,
...
coloanak=expresiek
[WHERE conditie];
Capitolul 2. Limbajul MySQL
77
În urma executării acestei comenzi, pentru fiecare rând din tabel care
îndeplineşte condiţia din WHERE, se actualizează coloanele indicate de SET cu
expresiile corespunzătoare.
Observaţie ! În absenţa clauzei WHERE sunt afectate toate rândurile din tabel.
A3) Ştergerea unui rând sau a mai multor rânduri se face cu instrucţiunea de mai
jos (vezi Exemplul 2.38, pct. 3 şi pct. 4):
DELETE FROM nume_tabel
[WHERE conditie]
Observaţie ! În absenţa clauzei WHERE sunt şterse toate rândurile din tabel.
B) Modificări ale numelui tabelului sau a structurii acestuia.
B1) Pentru a modifica numele unui tabel se utilizează instrucţiunea:
RENAME TABLE nume_vechi TO nume_nou
B2) Pentru ştergerea unei coloane, chiar dacă conţine date, se utilizează
instrucţiunea:
ALTER TABLE nume_tabel
DROP COLUMN nume_coloana
B3) Pentru adăugarea unei coloane cu un tip de date, se utilizează instrucţiunea:
ALTER TABLE nume_tabel
ADD nume_col tip;
Exemplul 2.38. Fie tabelele de mai jos, ambele cu aceleaşi coloane, de acelaşi tip:
Figura 2.31. Tabelul “prs”
Figura 2.32. Tabelul “prs1”
1. Se cere să se insereze în tabelul ”prs”, acele
persoane din ”prs1” care sunt din ”Craiova”.
Alăturat, vedeţi tabelul ”prs” actualizat.
INSERT INTO prs (nume, oras)
SELECT nume, oras FROM prs1 WHERE
oras=’craiova’;
Figura 2.33.
Tabelul “prs” actualizat
78
Baze de date – curs introductiv
2. S-a observat că Ioana şi Florin sunt de fapt
din braila. Corectaţi datele din tabel! Alăturat aveţi
afişat tabelul cu datele actualizate.
UPDATE prs
SET oras=’braila’
WHERE nume IN (‘ioana’, ‘florin’);
Figura 2.34. Tabelul actualizat
3. Ştergeţi din tabelul ”prs” înregistrarea în care
numele este Mirela (vezi figura alăturată):
DELETE FROM prs
WHERE nume=’Mirela’;
Figura 2.35.
4. Creaţi un nou tabel ”prs2”, cu aceeaşi structură
ca şi ”prs”, care să conţină numai persoanele din
”prs” care sunt din Braila şi Ploiesti.
CREATE TABLE prs2 AS
SELECT nume, oras FROM prs
WHERE nume IN (‘braila’, ‘ploiesti’);
Figura 2.36. Tabelul nou “prs2”
Exemplul 2.39. În tabelul alăturat, ”prs”, există
mai multe înregistrări identice. Se cere să se
elimine duplicatele.
a) Creăm un alt tabel, de manevră, numit ”mand”,
care conţine aceleaşi înregistrări cu ”prs”, doar că
au fost eliminate duplicatele:
CREATE mand AS
SELECT distinct nume, oras FROM prs;
b) Ştergem tabelul ”prs”: DROP TABLE prs;
Figura 2.37. Tabelul “prs”
c) Redenumim tabelul ”mand” ca ”prs” şi-l afişăm
pe ”prs”:
RENAME TABLE mans TO PRD;
SELECT * FROM prs;
Figura 2.38.
Tabelul rezultat
Observaţie! Mare atenţie când efectuaţi astfel de operaţii. În cazurile reale, în care
tabelele au mii de rânduri, se pot produce pierderi de date. Din acest motiv, înainte
de a actualiza un tabel, este bine să-i creaţi o copie de siguranţă pe care, după ce
aţi rezolvat problema, s-o ştergeţi.
Capitolul 2. Limbajul MySQL
79
2.16. Funcţii agregate
Toate calculele făcute până în prezent au avut ca operanzi doar câmpurile
unui aceluiaşi rând. Întrebarea este: se pot efectua calcule cu valorile reţinute de o
coloană? Răspunsul este afirmativ. Pentru astfel de calcule se utilizează
aşa-numitele “funcţii agregate”. În cele ce urmează, prezentăm aceste funcţii, iar
pentru exemplificare utilizăm tabelul ”elevi”, tabel pe care l-am creat în paragraful
2.14. Funcţiile agregate sunt prezentate în tabelul de mai jos:
Nume funcţie
COUNT()
MIN()
MAX()
SUM()
AVG()
Ce realizează
Sub forma COUNT(*), afişează numărul de linii ale tabelului.
Sub forma COUNT(nume_coloana), numără valorile, din
coloana de nume dat, care nu sunt NULL.
Sub forma MIN(nume_coloana), calculează cea mai mică
valoare din coloană. Valorile NULL sunt ignorate.
Sub forma MAX(nume_coloana), calculează cea mai mare
valoare din coloană. Valorile NULL sunt ignorate.
Sub forma SUM(nume_coloana), calculează suma valorilor
dintr-o coloană. Valorile NULL sunt ignorate.
Sub forma AVG(nume_coloana), calculează media aritmetică
a valorilor dintr-o coloană. Valorile NULL sunt ignorate.
Tabelul 2.14. Funcţii agregate
Exemplul 2.40. Câţi elevi sunt în tabel?
SELECT COUNT(*)
AS numar_elevi FROM elevi;
Figura 2.39.
Exemplul 2.41. Care este numărul de note la
engleză? Se afişează 4, pentru că un elev nu are
notă la această disciplină (NULL).
SELECT COUNT(engleza) AS
numar_note_engleza FROM elevi;
Figura 2.40.
Exemplul 2.42. Care este media notelor la informatică?
SELECT AVG(informatica) AS
media_note_informatica FROM elevi;
Figura 2.41.
Exemplul 2.43. Câţi elevi au nota 10 la engleză?
SELECT COUNT(engleza) AS elevi_de_zece FROM
elevi
WHERE engleza=10;
Figura 2.42.
80
Baze de date – curs introductiv
Exemplul 2.44. Câţi elevi au media generală peste 8?
SELECT COUNT(nume) AS elevi_peste_8
WHERE (matematica+engleza+informatica)/3>8;
Figura 2.43. Rezultat
2.17. Utilizarea subinterogărilor
Aşa cum am arătat, filtrările sunt cazuri particulare de interogări. În general,
orice rezultat care este obţinut cu ajutorul unei instrucţiuni SELECT este o
interogare. La modul general, o interogare poate returna:
A) o coloană, eventual cu un singur rând;
B) mai multe coloane - în acest caz se poate spune că interogarea
returnează un tabel.
Problema care se pune în continuare este următoarea: pot fi utilizate datele
returnate de o interogare pentru a efectua o nouă interogare? Răspunsul este, în
general afirmativ şi este valabil începând cu versiunea MySQL incorporată în
versiunea EasyPHP 1.8. În aceste cazuri, prima interogare care se efectuează
este interogarea subordonată. Rezultatul ei este utilizat pentru a efectua o nouă
interogare. Vom considera, pe rând, cazurile în care interogarea subordonată
returnează o valoare, o coloană şi un tabel (mai multe coloane). Toate exemplele
care urmează vor avea ca bază de plecare tabelul elevi, utilizat şi în paragrafele
anterioare.
A) Interogarea subordonată returnează o coloană cu un singur rând
Exemplul 2.45. Se cere să se determine numele elevilor care au cea mai mare
notă la matematică.
Figura 2.44.
Rezultatul dorit
Practic, ar trebui să vedem care este cea mai mare notă la matematică, o primă
interogare, problemă pe care o rezolvăm utilizând funcţia agregată MAX(), apoi
într-o nouă interogare, aflăm numele elevilor care au această notă. În acest caz,
interogarea subordonată returnează o valoare, cea maximă.
SELECT nume, matematica FROM elevi
WHERE matematica=(SELECT MAX(matematica) FROM elevi);
Mai întâi, se execută interogarea subordonată, apoi cea care o subordonează. În
acest caz, interogarea subordonată calculează nota maximă obţinută la
matematică (să observăm că aceasta nu este în mod obligatoriu 10), iar cealaltă
interogare returnează numele elevilor cu această notă.
Capitolul 2. Limbajul MySQL
81
Exemplul 2.46. Se cer numele elevilor care au cea mai mare medie la obiectele
matematică şi informatică. Vom proceda în acelaşi mod. În primul rând, selectăm
media maximă la obiectele amintite, apoi numele elevilor cu această medie.
SELECT nume, (matematica+informatica)/2 AS media FROM elevi
WHERE (matematica+informatica)/2=
(SELECT MAX((matematica+informatica)/2) FROM elevi);
Figura 2.45.
Rezultatul obţinut
Exemplul 2.47. Se cer numele elevilor şi media generală, unde media generală a
lor este strict mai mare decât media elevilor din tabel. Se cere, de asemenea, ca
elevii să fie ordonaţi în ordinea crescătoare a mediilor.
Interogarea subordonată calculează media generală a elevilor, iar prima interogare
afişează elevii care au media generală peste aceasta.
SELECT nume, (matematica+informatica+engleza)/3 AS media FROM elevi
where (matematica+engleza+informatica)/3>
(SELECT AVG((matematica+engleza+informatica)/3) FROM elevi)
ORDER BY media DESC;
Figura 2.46.
Rezultatul obţinut
Exemplul 2.48. Care este numele elevilor care au aceeaşi notă la matematică ca
şi elevul Popescu Marius? În acest caz, interogarea subordonată returnează
nota la matematică a elevului Popescu Marius, iar interogarea care o
subordonează returnează numele elevilor care au această notă:
SELECT nume FROM elevi WHERE matematica=
(SELECT matematica FROM elevi
WHERE nume=’Popescu Marius’);
Figura 2.47.
Rezultatul obţinut
B) Interogarea subordonată returnează un tabel
În acest caz, tabelul returnat de interogarea subordonată trebuie să aibă un
nume. Acesta se dă cu ajutorul clauzei AS. De asemenea, interogarea care
subordonează adresează câmpurile tabelului, pornind de la numele său, urmat de
‘.’ şi de numele coloanei.
Exemplul 2.49. Care este media generală la matematică şi la informatică a elevilor
care au cel puţin 8 la una dintre discipline?
82
Baze de date – curs introductiv
Tabelul returnat de interogarea subordonată conţine notele la matematică şi
la informatică ale elevilor care au cel puţin 8 la una dintre aceste discipline. Acest
tabel se numeşte virtual. Interogarea principală calculează mediile la matematică şi
informatică ale acestor elevi.
SELECT AVG(virtual.matematica) AS medie_mate,
AVG(virtual.informatica) AS medie_info FROM
(SELECT matematica, informatica FROM elevi
WHERE matematica>=8 OR informatica>=8) AS virtual;
Figura 2.48.
Rezultatul obţinut
2.18. Gruparea datelor
Datele dintr-un tabel pot fi grupate în funcţie de valorile dintr-o anumită
coloană. De exemplu, datele din tabelul din Fig. 2.49 pot fi grupate după valorile
din coloana ”data”. Astfel, un grup este alcătuit din rândurile de tabel
corespunzătoare datei ‘2006-03-15‘, altul, corespunzătoare datei ‘2006-03-16‘,
..., altul corespunzător unei date necunoscute (NULL). Prelucrările datelor din
fiecare grup se fac cu ajutorul funcţiilor agregate, aşa cum suntem deja obişnuiţi.
Pentru a grupa datele din tabel după valorile unei coloane se utilizează clauza
GROUP BY nume_coloana, adăugată după numele tabelului. Exemplele care
urmează vă vor lămuri!
Exemplul 2.50. Se consideră tabelul
“vanzari” cu structura de mai jos
care conţine data vânzării, numele
produsului vândut şi valoarea
vânzării din produsul respectiv:
CREATE TABLE vanzari
( data
DATE,
produs CHAR(15),
valoare INT);
Figura 2.49.
Tabelul “vanzari”
Întrebări:
1. Care este numărul de vânzări din fiecare zi? Grupăm datele după dată şi
numărăm vânzările pentru fiecare grup.
Capitolul 2. Limbajul MySQL
83
SELECT data, COUNT(*) AS numar_vanzari FROM vanzari
GROUP BY data;
Figura 2.50. Numărul de
vânzări din fiecare zi
2. Care este suma vânzărilor zilnice? Grupăm datele după dată şi însumăm
vânzările pentru fiecare dată în parte:
SELECT data, SUM(valoare) AS
suma_vanzari FROM vanzari
GROUP BY data;
Figura 2.51. Suma
vânzărilor zilnice
3. Care este numărul de vânzări şi suma vânzărilor în fiecare zi (se va afişa un
singur tabel)?
SELECT data, COUNT(*) AS nr_vanzari, SUM(valoare) AS suma_incasata
FROM vanzari GROUP BY data;
Figura 2.52. Numărul de
vânzări şi suma încasată
din fiecare zi
4. Care este data în care am am vânzări în valoare maximă, câte vânzări au fost
şi care este suma încasată?
Ar trebui să obţinem un tabel care să conţină data şi suma vânzărilor zilnice, apoi,
din aceasta să selectăm vănzarea maximă şi, apoi, data la care s-a efectuat
vânzarea zilnică. În MySQL, în varianta de care dispunem, nu este permisă mai
mult de o interogare cu subordonata sa. Din acest motiv, vom crea un tabel de
manevră (“manevra“) care conţine data şi suma vânzărilor zilnice (ca la punctul 2).
Apoi din acesta, utilizând o interogare cu subinterogare, vom extrage datele cerute.
În final, vom şterge tabelul “manevra“.
CREATE TABLE manevra AS
SELECT data, SUM(valoare) AS vanzare
FROM vanzari GROUP BY data;
Pentru probă, afişăm tabelul manevra.
SELECT * FROM manevra;
Figura 2.53. Tabelul “manevra”
84
Baze de date – curs introductiv
Pornind de la “manevra”, obţinem datele cerute.
SELECT data, vanzare FROM manevra
WHERE vanzare=
(SELECT MAX(vanzare) FROM manevra);
Ştergem tabelul ”manevra”:
Figura 2.54. Rezultatul final
DROP TABLE manevra;
2.19. Uniuni de tabele
Un punct de maximă importanţă şi eficienţă în utilizarea bazelor de date este
dat de uniunea de tabele. Uniunea este alcătuită din două sau mai multe tabele
între care există o legătură. De cele mai multe ori, legătura este dată de valorile
existente în câte o coloană a fiecărui tabel din uniune. Pentru tabelele care
alcătuiesc uniunea se pot utiliza alias-uri de nume, sub forma nume_tabel AS
alias_nume, introduse în clauza FROM. Alias-urile pot fi utilizate în orice parte a
instrucţiunii select. În aceste cazuri, adresarea unei coloane a tabelului se face
sub forma: alias_nume.nume_col.
Avantajele utilizării alias-urilor sunt:
- se pot asigura nume scurte pentru tabele, gen A, B,..., etc.
- în cazul auto-uniunilor, caz care este prezentat în actualul paragraf, un
singur tabel poate avea alias-uri diferite, fapt care permite anumite
interogări speciale ca şi cum am avea mai multe tabele: A, B, etc. În astfel
de cazuri, atunci când ne referim la o coloană, pentru a nu se crea
confuzie, trebuie precizat tabelul, cum ar fi de exemplu: A.nume_col,
B.nume_col, etc.
1) O primă formă de realizare a unei uniuni este utilizarea instrucţiunii SELECT în
care la clauza FROM se trec, pe rând, toate tabelele care o alcătuiesc, iar legătura
este precizată cu ajutorul clauzei WHERE. Vezi exemplele 2.51, pct. 1.a), 4, 5.
2) Atunci când uniunea este alcătuită din două tabele, se poate preciza o
legătură de tip INNER sub forma de mai jos. În astfel de cazuri, se afişează datele
din tabel1 şi din tabel2, pentru care este îndeplinită condiţia din ON. O astfel de
uniune se mai numeşte şi uniune interioară. Vezi exemplul 2.51, pct. 1.b)!
nume_tabel1 [AS...]INNER JOIN nume_tabel2 [AS...]
ON conditia de uniune
3) Atunci când uniunea este alcătuită din două tabele, se poate preciza o
legătură de tip LEFT OUTER sub forma de mai jos. În astfel de cazuri, se afişează
toate datele din tabel1, iar datele din tabel2 se afişează numai dacă este
Capitolul 2. Limbajul MySQL
85
îndeplinită condiţia din ON, altfel, în locul lor se afişează valoarea implicită (NULL,
de cele mai multe ori). O astfel de uniune se mai numeşte şi uniune exterioară
stânga. Vezi exemplul 2.51, pct. 2.
nume_tabel1 [AS...]LEFT JOIN nume_tabel2 [AS...]
ON conditia de uniune
4) Atunci când uniunea este alcătuită din două tabele, se poate preciza o
legătură de tip RIGHT OUTER sub forma de mai jos. În astfel de cazuri, se afişează
toate datele din tabel2, iar datele din tabel1 se afişează numai dacă este
îndeplinită condiţia din ON, altfel, în locul lor se afişează valoarea implicită (NULL,
de cele mai multe ori). O astfel de uniune se mai numeşte şi uniune exterioară
dreapta. Vezi exemplul 2.51, pct. 3.
nume_tabel1 [AS...]LEFT JOIN nume_tabel2 [AS...]
ON conditia de uniune
Exemplul 2.51. Priviţi tabelele de mai jos, numite "produse" (cel din stânga) şi
"date_produse" (cel din dreapta). Logic, legătura dintre ele este dată de
coloanele "cod", din fiecare tabel. Astfel, pentru un cod dat, din tabelul "produse"
se poate extrage cantitatea existentă într-un magazin dintr-un anumit produs şi
denumirea produsului, producătorul său din tabelul "date_produse".
Figura 2.55. Cele două tabele propuse ca exemplu
1. Pentru fiecare produs existent în magazin,
care este trecut în tabelul "date_produse", să
se afişeze denumirea şi cantitatea. Pentru a
rezolva această problemă, vom utiliza două forme
de interogare şi ambele dau acelaşi rezultat.
a)
SELECT B.denumire, A.cantitate
FROM produse AS A, date_produse AS B
WHERE A.cod=B.cod;
b)
SELECT B.denumire, A.cantitate
FROM produse AS A INNER JOIN date_produse AS B
ON A.cod=B.cod;
Figura 2.56.
Rezultatul interogărilor
86
Baze de date – curs introductiv
2. La fel ca la punctul anterior, numai că se vor
trece datele existente pentru toate produsele din
tabelul ”produse”:
SELECT B.denumire, A.cantitate
FROM produse AS A LEFT OUTER JOIN
date_produse AS B
ON A.cod=B.cod;
Figura 2.57. Rezultat
3. La fel ca mai sus, numai că se vor trece datele
existente pentru toate
”date_produse”:
produsele
din
tabelul
SELECT B.denumire, A.cantitate
FROM produse AS A RIGHT OUTER JOIN
date_produse AS B
ON A.cod=B.cod;
Figura 2.58. Rezultat
4. O problemă serioasă care apare în cerinţele de acest tip este dată de faptul că
nu întotdeauna, orice cod din primul tabel, în exemplu ”produse”, se află printre
codurile din al doilea tabel, în exemplu, ”date_produse”. Se cere să afişăm
codurile din tabelul ”produse” care nu se regăsesc între codurile din tabelul
”date_produse”. Analizaţi interogarea de mai jos, este şi un exemplu de utilizare
a operatorului NOT IN:
SELECT cod FROM produse
WHERE
cod NOT IN (SELECT cod FROM date_produse);
Figura 2.59.
5. Selectaţi codurile de produse din tabelul ”date_produse” care nu
1
se regăsesc printre codurile din tabelul ”produse” .
SELECT cod FROM date_produse
WHERE
cod NOT IN (SELECT cod FROM produse);
Figura 2.60.
Auto-uniuni. Se pot obţine rezultate interesante
dacă cele două tabele sunt, de fapt, unul şi acelaşi,
dar au aliasuri diferite şi se consideră unite printr-o
coloană.
Exemplul 2.52. În tabelul alăturat, numit “st_or“
(referitor la localităţile din care provin studenţii unei
grupe dintr-o facultate), care sunt persoanele care
locuiesc în acelaşi oraş cu Ioana?
Figura 2.61. Tabelul “st_or”
În cazul în care considerăm tabelul ”produse” drept tabel tată şi tabelul ”date_produse”
drept tabel fiu, pentru a fi respectată integritatea referenţială, ar trebui ca mulţimea acestor
coduri să fie vidă.
1
Capitolul 2. Limbajul MySQL
87
Privim acelaşi tabel ca pe două tabele diferite legate prin câmpul
oras. Unul dintre tabele are numele A şi al doilea are numele B.
Interogarea constă în afişarea tuturor numelor din B care au
aceeaşi valoare în câmpul oras cu înregistrarea din A care,
pentru câmpul nume, reţine ‘Ioana’.
SELECT B.nume
FROM st_or AS A INNER JOIN st_or AS B
ON A.oras=B.oras AND
A.nume=’Ioana’;
Figura 2.62.
Rezultatul interogării
Observaţie ! Evident, aceeaşi problemă poate fi rezolvată prin utilizarea
mecanismului subinterogărilor. Exerciţiu!
2.20. Elemente care privesc securitatea bazelor de date
Asigurarea securităţii bazelor de date este o problemă extrem de serioasă.
Paragraful are numai rolul de a vă iniţia în această activitate. În realitate, problema
este cu mult mai complexă.
Sistemul de privilegii MySQL. O primă problemă care apare este de a
securiza, pe cât posibil, bazele de date. Din acest punct de vedere, în afara
administratorului, există posibilitatea ca la bazele de date să aibă acces şi alte
persoane, identificabile prin nume şi parole. Totuşi, aceste persoane au acces
numai la anumite operaţii cu bazele de date. Pentru ca o astfel de persoană (care
nu este utilizator) să acceseze baza de date este necesar ca administratorul să
introducă numele ei, parola şi operaţiile pe care le poate efectua. Astfel,
administratorul va utiliza instrucţiunea MySQL numită GRANT, a cărei formă
simplificată o prezentăm mai jos:
GRANT operaţii
ON nume_bază
TO nume_utilizator IDENTIFIED BY ‘parola’;
Operaţiile permise sunt: SELECT, UPDATE, INSERT, INDEX, ALTER, CREATE,
DROP şi trebuie să fie separate prin virgule. Atunci când accesul utilizatorului este
permis pentru orice bază de date, se utilizează *.*.
Exemplul 5.70. De acum, utilizatorul lavinia cu parola puful are acces la
operaţii de tip SELECT şi INSERT pentru orice bază de date.
GRANT SELECT, INSERT
ON *.*
TO lavinia IDENTIFIED BY ‘puful’
88
Baze de date – curs introductiv
Pentru a revoca unele drepturi ale unui utilizator sau chiar toate,
administratorul foloseşte instrucţiunea REVOKE. Pentru a revoca toate operaţiile
permise, se utilizează ALL.
REVOKE operaţii
ON nume_bază
FROM nume_utilizator
Exerciţiu. Acordaţi drepturi unor utilizatori, verificaţi dacă le au, revocaţi anumite
drepturi şi verificaţi apoi dacă le mai au.
1. ”Materiale”. O firmă dispune de mai multe depozite. În fiecare depozit există
mai multe materiale. Pentru fiecare material se cunoaşte preţul şi cantitatea. Se
cere să se răspundă la întrebările de mai jos. Tabelul se numeşte ”materiale”.
Figura 2.63.
Tabelul “materiale”
1.1. Care sunt materialele existente într-un anumit depozit (în exemplu,
‘Depozit 2’) ?
1.2. Care sunt depozitele în care există un anumit material (în exemplu,
‘material 3’? Se presupune că numele materialului poate fi precedat de blank-uri.
1.3. Care este valoarea totală a tuturor materialelor din depozite?
1.4. Care este valoarea totală a materialelor din fiecare depozit?
1.5. Presupunem că ‘material 1’ se scumpeşte cu 10%. Actualizaţi datele din
tabel.
1.6. Să se şteargă un anumit material (‘material 2’) din tabel.
2. “Împrumuturi”. Există persoane care au credite, în acelaşi timp, la mai multe
bănci. O astfel de situaţie este prezentată în tabelul de mai jos, numit
”imprumuturi”. Se cere să se răspundă la următoarele întrebări:
Capitolul 2. Limbajul MySQL
89
Figura 2.64.
Tabelul “imprumuturi”
2.1. Care sunt persoanele care au împrumutat de la ‘Banca 1’?
2.2. Care este suma împrumutată de fiecare bancă populaţiei?
2.3. Afişaţi, pentru fiecare persoană, numărul împrumuturilor pe care le-a efectuat.
2.4. Care sunt persoanele care au împrumutat o sumă maximă şi care este
această sumă?
2.5. Care sunt persoanele care au împrumutat bani cel puţin de la o bancă la
care a împrumutat şi ‘Ionescu Grigore’?
3. “Proprietari, proprietăţi”. Se dă un tabel (“proprietari“), în care pentru
fiecare persoană se cunoaşte codul (cod) şi numele (nume). Se dă şi un alt tabel
(“proprietati“) în care se cunoaşte codul proprietarului (cod_proprietar),
tipul proprietăţii (tip_p) şi valoarea proprietăţii (valoare):
Figura 2.65. Tabelul
“proprietari”
Figura 2.66. Tabelul “proprietati”
3.1. Afişaţi, pentru fiecare proprietar care are cel puţin o proprietate, numărul
proprietăţilor.
3.2. Afişaţi numele proprietarilor care nu au proprietăţi.
3.3. Afişaţi codurile proprietarilor din tabelul “proprietati“ care nu au
corespondent în tabelul “proprietari“.
3.4. Afişaţi valoarea proprietăţilor pe care le are fiecare proprietar. Datele vor fi
afişate în ordinea descrescătoare a proprietăţilor.
4. “Prietenii”. Se dau două tabele (“baieti” şi “fete”) în care pentru fiecare
persoană se cunoaşte codul (cod), numele (nume) şi vârsta (varsta). De
asemenea, mai există un tabel, numit “prietenii”, în care sunt reţinute relaţiile
dintre băieţi şi fete.
90
Baze de date – curs introductiv
Figura 2.67. Tabelul ” baieti”
Figura 2.68. Tabelul ” fete”
4.1 Care sunt prietenele lui Mihai, cel care are 18 ani?
Observaţie ! Se presupune că există un singur băiat
Mihai care are 18 ani.
4.2 Afişaţi numele fetelor care nu au prieten.
4.3 Pentru fiecare băiat care are cel puţin o prietenă,
afişaţi numele prietenelor pe care acesta le are.
4.4 Afişaţi numele unei fete cu un număr maxim de
prieteni şi numărul prietenilor ei.
4.5 Afişaţi media de vârstă a băieţilor şi a fetelor.
Figura 2.69.
Tabelul ” prietenii”
5. ”Angajaţi”. O firmă doreşte să reţină într-o bază de date un tabel referitor la
angajaţi. Motivul este dat de faptul că se vrea obţinerea rapidă a răspunsurilor la
întrebările de mai jos. Ce date va reţine tabelul? Cum obţinem răspunsul la întrebări?
5.1 Care sunt numele angajaţilor (în ordine alfabetică)?
5.2 Care sunt angajaţii cu vârsta sub 30 de ani?
5.3 Realizaţi o listă a femeilor angajate şi o alta a bărbaţilor angajaţi.
5.4 Realizaţi o listă a angajaţilor care au studii superioare.
5.5 Care sunt angajatele care sunt în concediu de maternitate?
5.6 Care sunt angajaţii cu o vechime în meseria pe care o practică la firmă de sub
trei ani?
5.7 Care sunt angajaţii care au salariul minim pe economie?
5.8 Care sunt angajaţii care au salariul brut mai mare decât cel minim, dar mai
mic decât 1000 de lei?
5.9 Care sunt angajaţii care ies la pensie anul următor?
5.10 Care sunt angajaţii care au copii şi câţi copii au?
5.11 Mâine este Sfânta Maria. Care este lista sărbatoritelor?
5.12 Găsiţi angajaţii care îşi sărbătoresc mâine ziua de naştere!
6. ”Cheltuieli / Venituri”. George este o persoană căreia îi place să-şi ţină
evidenţa veniturilor şi cheltuielilor. El are un tabel cu următoarele câmpuri: Data,
Cheltuiala/Venit, Suma cheltuită sau încasată, Explicaţii (Text). Să presupunem că
George şi-a completat tabelul câteva luni, în fiecare zi. Fiecare sumă cheltuită sau
încasată este înregistrată pe o linie a tabelului. Se cere:
6.1 Care sunt veniturile totale ale lui George şi care sunt cheltuielile sale pe toată
perioada cât a ţinut evidenţa?
Capitolul 2. Limbajul MySQL
91
6.2 A reuşit George să economisească o sumă de bani în această perioadă sau
a fost nevoit să se împrumute? Care este suma economisită sau împrumutată?
6.3 În care lună George a cheltuit cea mai mare sumă?
6.4 În care lună George a avut cele mai mari încasări?
6.5 Care este luna în care George a economisit cea mai mare sumă?
6.6 Creaţi un tabel care să conţină toate veniturile lui George pe întreaga
perioadă şi un altul care să conţină toate cheltuieliule în aceeaşi perioadă.
6.7 Creaţi un tabel care să conţină, pentru fiecare lună în parte, suma încasărilor
şi suma cheltuielilor.
7. ”Biblioteca”. Ioana s-a angajat la o bibliotecă şi doreşte să ţină evidenţa
cărţilor pe calculator.
7.1 Ioana doreşte, în primul rând, să ţină evidenţa titlurilor pe care le are la
bibliotecă. Pentru aceasta, Ioana codifică toate titlurile şi reţine pentru fiecare
titlul, editura şi autorul.
7.2 Pentru a ţine evidenţa numărului de exemplare din fiecare titlu, existente în
gestiune, este nevoie de un alt tabel, numit Nr Exemplare. Creaţi-l!.
7.3 Care este legătura între cele două tabele?
7.4 În continuare, trebuie creat un tabel, numit Cititori, care conţine
persoanele care împrumută cărţi de la bibliotecă (Nume, Adresa, Nr. telefon)
Înainte de a împrumuta o carte, cititorul este înscris în acest tabel. Creaţi-l!.
7.5 De asemenea, trebuie creat un tabel (Imprumuturi) în care, pentru fiecare
carte împrumutată, este scrisă o înregistrare care conţine numele cititorului şi codul
cărţii (o înregistrare conţine un singur exemplar dintr-un titlu). Creaţi-l!
7.6 Se cere o situaţie în care sunt afişaţi cititorii care au împrumutat o carte de
mai mult de două săptămâni.
7.7 Câte exemplare sunt împrumutate din fiecare carte?
7.8 Câte exemplare sunt împrumutate din cartea care are codul x?
7.9 Pentru fiecare carte împrumutată, se cere codul cărţii, tilul şi numărul
exemplarelor aflate la cititori.
7.10 Un cititor solicită un anumit titlu. Ioana vrea să vadă dacă există exemplare
neîmprumutate din acesta.
8. Problemă pentru lucrul în colectiv! “Grilă“. Scrieţi o grilă cu 18 itemi (18
întrebări la care răspunsul corect este unul singur, ales dintre 4 răspunsuri). În final
se va afişa nota obţinută de cel care este testat prin utilizarea acestei grile. Fiecare
răspuns corect este punctat cu 0.5 puncte şi un punct se acordă din oficiu. Desigur,
dacă este necesar, itemii vor fi însoţiţi de imagini. Problema va fi rezolvată de
echipe diferite, pe diverse domenii: informatică, matematică, biologie, limbi străine,
chimie, istorie, ş.a.m.d. Un set de astfel de probleme va fi util elevilor din toată ţara!
9. Problemă pentru lucrul în colectiv! “Magazin“. Creaţi un site prin care o firmă
vinde calculatoare şi diverese componente de calculatoare. Comenzile se pot face
prin intermediul site-ului şi ele sunt stocate în baza de date. Se cere să se
efectueze validarea datelor de intrare. De asemenea, reprezentanţii firmelor pot
extrage din baza de date comenzile dintr-o anumită zi şi pot memora date
referitoare la expedierea produselor.
(pentru verificare, rezolvările se găsesc la finalul cărții)
CAPITOLUL
Limbajul PHP
În acest capitol studiem limbajul PHP. După ce-l vom parcurge, vom şti să
trimitem date de pe calculatorul client către server şi vom şti să le prelucrăm
pe server. Vom cunoaşte cum să personalizăm paginile web, în funcţie de
persoana care le accesează, dar adevărata forţă a limbajului se va
vedea atunci când îl vom folosi la un loc cu limbajul MySQL.




Introducere
Cum realizăm un formular ?
Constante, variabile, operatori
Care sunt instrucţiunile limbajului PHP ?



Funcţii PHP
Funcţii “matematice”
Cum afişăm datele ?
Funcţii pentru prelucrarea şirurilor de caractere




Masive în PHP
Ce sunt variabilele cookie ? Cum le folosim ?
Utilizarea în comun a limbajelor PHP şi MySQL

Cuvinte cheie: formulare, input, submit, radio, checkbox,
password, textarea, select, constante, variabile, operatori,
echo, print, instrucţiuni, funcţii, masive, cookie, securitate
Aplicaţii
Capitolul 3. Limbajul PHP
93
3.1. Introducere
Numele limbajului era iniţial un acronim pentru ”Personal Home Page” şi a fost
inventat în 1994 de Rasmus Lerdof, care dorea să-şi contorizeze vizitatorii paginii
sale de Internet. Astăzi, se cosideră că PHP este un limbaj de scriptare înglobat în
HTML. Documentaţia oficială a limbajului se găseşte pe site-ul www.php.net.
Script-urile scrise în acest limbaj se utilizează pe partea de server.

Limbajul PHP este asemănător limbajului C.

Script-urile scrise în acest limbaj rulează şi trebuie să se găsească pe
server. În linii mari, ele au rolul de a prelucra datele pe care le trimite
utilizatorul de pe propriul calculator şi de a transmite către browser
rezultatele prelucrărilor.

Nu toate site-urile permit utilizarea limbajului PHP. Din acest motiv,
dacă vă interesează să-l utilizaţi, trebuie să studiaţi cu atenţie oferta de
site-uri a firmei la care apelaţi (provider-ul).
În ceea ce ne priveşte, pentru a învăţa limbajul PHP vom utiliza pachetul EasyPHP
(vezi Anexa 1) care ne permite să rulăm PHP pe propriul calculator. Nu uitaţi,
înainte de orice, lansaţi în executare programul EasyPHP din meniul Start/Programs!

Practic, orice script PHP va fi memorat în subfolder-ul www al folder-ului
EasyPHP din Program Files şi va fi apelat din browser prin
” http://192.168.1.217/nume_script.php”.

Orice script PHP va avea extensia ”php”.
În situaţia în care rulaţi pe un site real, după ce creaţi şi testaţi script-urile pe
propriul calculator, cu EasyPHP, le puteţi transfera pe server cu ajutorul unui
program FTP.

Orice script PHP este cuprins între:
<?php
...
?>
Exemplul 3.1. Script-ul de mai jos afişează
un mesaj. Îl vom memora în www sub
numele de "primul.php". Apelul şi
rezultatul se pot observa alăturat.
<?php
echo "eu sunt primul script php";
?>
94
Baze de date – curs introductiv
Observaţie foarte importantă! Atunci când se apelează un script, el este rulat pe
server. Acesta va efectua operaţiile pe care le are programate şi eventual, va scrie
ceva (de exemplu, ca în exemplul următor, cu "echo"). Rezultatul (adică ce este
scris) este returnat către browser, iar acesta
îl va trata ca pe un fişier html.
Exemplul 3.2. Rulăm script-ul de mai
jos care conţine câteva elemente de
formatare. Rezultatul îl vedem în
figura alăturată:
<?php
echo "eu sunt <b>primul</b>
<br>script <b>php</b>";
?>
Exemplul 3.3. Acelaşi script poate fi apelat şi ca un link, aşa cum observaţi mai jos
(fişierul html putând fi plasat oriunde):
<html>
<head></head>
<body>
<p> Un text oarecare!
<a href=" http://192.168.1.217/primul.php">Apeleaza</a>
</body>
</html>
Exemplul 3.4. Script-urile PHP pot conţine direct elemente de HTML, pe lângă
secvenţa propriu-zisă, PHP. Scrieţi script-ul următor în www şi apelaţi-l. Veţi vedea
că se afişează conţinutul unei variabile PHP (variabilele PHP vor fi tratate separat).
La apel se afişează "Bine ati venit, domnule Ion Popescu!".
<html>
<head>
</head>
<body>
<p> Bine ati venit,
domnule
<?php
$nume=" Ion Popescu!";
echo ($nume);
?>
</body>
</html>
Capitolul 3. Limbajul PHP
95
3.2. Formulare
De la început trebuie spus că formularele sunt elemente ale limbajului HTML.
Un formular este o grupare de componente HTML care permit trimiterea datelor şi a
comenzilor către server. Pe server, comenzile sau datele sunt recepţionate de un
script PHP care răspunde comenzilor şi prelucrează datele.
Un formular se descrie între tag-urile <form action script> şi </form>.
Prin script înţelegem numele script-ului care se rulează atunci când datele,
comenzile sosesc pe server. Între cele două tag-uri se inserează diferite
componente care permit introducerea datelor sau trimiterea comenzilor.
Elementul INPUT – este un element HTML de o mare complexitate. Poate fi de
diverse tipuri (type): de la un buton de validare, la unul radio, un edit, etc. După
cum sugerează şi numele, rolul elementului input este de a permite utilizatorului
să introducă date sau comenzi în pagina vizualizată de browser. Un element
input se descrie cu tag-ul următor (formă simplificată):
<input name="nume" type="tip"
value="valoare"
align="tip_aliniere">
unde valoare exprimă valoarea afişată de element.
3.2.1. Tipul “submit”
Are aspectul unui buton. La apăsarea lui, datele sunt transmise către server,
de unde, evident, răspunde un script care are rolul de a le prelucra.
Exemplu 3.5. Nu se transmit date, dar la apăsarea butonului de tip submit se
lansează un script care afişează un mesaj:
<html>
<head>
</head>
<body>
<form action="http://192.168.1.217/exemplu.php">
<input type="submit" value="Primul exemplu de apel PHP">
</form>
</body>
</html>
Alăturat, observaţi cum este afişată
sursa HTML de către browserul web:
96
Baze de date – curs introductiv
Iată şi script-ul PHP reținut în fișierul exemplu.php:
În urma rulării, browser-ul afişează mesajul.
3.2.2. Tipul “text”
Este sub forma unui edit şi permite utilizatorului să introducă date. Acestea
se trimit către browser la apăsarea unui buton de tip submit. Pentru ca datele să
fie recuperate de către script-ul de pe server, trebuie ca tag-ul <form> să conţină
parametrul method ="post".
Atunci când browser-ul execută o cerere către server, trimite şi valorile
reţinute de cele două input-uri de tip text. Variabila $_POST este un vector
1
asociativ care reţine toate valorile astfel transmise. Valoarea transmisă de input-ul
de tip text numit a se recuperează prin $_POST[‘a’], cea transmisă de input-ul
de tip text b se recuperează prin $_POST[‘b’]. Această modalitate de
transmitere şi recepţionare a parametrilor este generală şi trebuie reţinută.
Exemplul 3.6. Vizitatorul trimite două valori numerice
a şi b. Script-ul PHP returnează suma lor:
<html>
<head></head>
<body>
<form
action="http://192.168.1.217/exemplu.php" method ="post">
<input type="text" name="a"><br>
<input type="text" name="b"><br>
<input type="submit" value="Suma?">
</form>
</body></html>
Sursa este vizualizată de către browser, aşa cum puteţi observa în figura de mai
jos. Script-ul PHP care afişează suma celor două numere este:
<?php
// recuperarea datelor
$a=$_POST['a'];
$b=$_POST['b'];
echo $a+$b;
?>

1
În PHP, variabilele încep cu caracterul ”$”.
Vectorii asociativi sunt trataţi în cadrul acestui capitol.
Capitolul 3. Limbajul PHP
97
3.2.3. Tipul “radio”
Tipul radio (butoane radio) se utilizează în cazul în care utilizatorul trebuie să
aleagă o singură opţiune dintre mai multe posibile. Pentru fiecare buton radio se
ataşează câte un element input de tip radio. Pentru a avea un comportament de
grup, în sensul că se poate bifa un singur buton, toate butoanele trebuie să aibă un
singur nume, în exemplul de mai jos, Buton. Opţional, pentru un buton se poate
folosi opţiunea checked şi efectul este acela că de la început butonul este bifat.
La apăsarea butonului submit, butonul bifat va trimite valoarea ataşată lui.
Exemplul 3.7. Utilizatorul trebuie să bifeze un singur
buton radio, iar pe server “se va şti”, în funcţie de
valoarea primită, care buton a fost apăsat:
<html>
<head>
</head>
<body>
<form action="http://192.168.1.217/
exemplu.php"
method ="post">
<p> Cumpar ziarul ...
<br><br>
<input name="Buton" type="radio" value=1 checked> zilnic <br>
<input name="Buton" type="radio" value=2> saptamanal <br>
<input name="Buton" type="radio" value=3> lunar<br><br>
<input type="submit" value="Trimite">
</form>
</body>
</html>
Script-ul PHP şi rezultatul afişat:
<?php
$b=$_POST['Buton'];
echo $b;
?>
3.2.4. Tipul “checkbox”
Acest tip se utilizează pentru ca în fereastra browser-ului să fie afişate
butoane de marcare. Aceste butoane sunt utilizate pentru a permite utilizatorului să
marcheze una, niciuna sau mai multe opţiuni. De reţinut: în acest caz, se transmit
către server doar valorile butoanelor marcate.
Exemplul 3.8. În continuare, observaţi modul în care facem ca browser-ul să
afişeze butoanele de marcare şi script-ul PHP care depistează butoanele marcate:
98
Baze de date – curs introductiv
<form action="http://192.168.1.217/exemplu.php"
method="post">
<p>Urmaresc posturile TV:</p>
<input NAME="buton1" type="checkbox"
value=1 checked> CNN <br>
<input NAME="buton2" type="checkbox"
value=2> Antena 1 <br>
<input NAME="buton3" type="checkbox"
value=3> ProTV <br><br>
<input type="submit" value="GO">
</form>
Iar în exemplu.php vom avea:
<?php
foreach ($_POST AS $i=>$nume)
if ($i=="buton1") echo "CNN"."<br>";
else
if ($i=="buton2") echo "Antena 1" ."<br>";
else
if ($i=="buton3") echo "ProTV";
?>
3.2.5. Tipul “password”
Componentele vizuale de acest tip se utilizează pentru introducerea
parolelor, atât de necesare, de exemplu, pentru a avea acces la un site. Sunt
asemănătoare cu cele de tip text, numai că, pentru fiecare caracter al parolei se
afişează câte un “*”. Desigur, către server, datele sunt transmise corect.
Exemplul 3.9. Se introduce o parolă, iar script-ul
care o primeşte o afişează:
<form action="
http://192.168.1.217/exemplu.php"
method="post">
<p> Introduceti parola </p>
<input name="parola" type="password">
<br><br>
<input type="submit" value="GO">
</form>
<?php
echo $_POST['parola'];
?>
Capitolul 3. Limbajul PHP
99
3.3. Elementul TEXTAREA
Elementul TEXTAREA se utilizează pentru a introduce un text mai lung.
El poate fi folosit în interiorul unui formular şi, la apăsarea butonului submit,
conţinutul său este transmis către server. De remarcat este că pentru un element
TEXTAREA se pot preciza numărul de linii (rows) şi de coloane (cols) pe care
acesta să le afişeze.
Exemplul 3.10. În fișierul primul.php vom scrie:
...
<form action="http://192.168.1.217/exemplu.php"
method="post">
<p>Adaugati comentariul dv.!</p>
<textarea name="textul" rows="10"
cols="20"></textarea><br><br>
<input type="submit" value="Scrie">
</form>
...
Iată şi script-ul PHP care afişează şirul trimis (exemplu.php):
<?php
echo $_POST['textul'];
?>
100
Baze de date – curs introductiv
3.4. Elementul SELECT
Elementul SELECT se utilizează pentru ca browser-ul
să afişeze o listă. Fiecare opţiune din listă este marcată de
un element OPTION. Dacă este introdusă într-un formular,
către server se va transmite opţiunea selectată.
Exemplul 3.11. Mai jos este prezentat formularul care afişează lista din figura de
mai sus şi script-ul PHP care afişează opţinea selectată din formular:
Scriptul PHP este:
Capitolul 3. Limbajul PHP
101
3.5. Constante. Variabile. Operatori
3.5.1. Constante
În PHP se pot defini constante cu ajutorul funcţiei define. Forma generală
a acesteia este:
define("nume_constanta", valoare).
Exemplul 3.12. În script-ul următor se defineşte constanta e şi se probează dacă
este recunoscută. La apel, se afişează 5.42:
3.5.2. Variabile
În PHP numele unei variabile începe cu $. În continuare, trebuie să fie o literă
sau o liniuţă de subliniere. În rest, puteţi folosi şi cifre.

Nu este necesar ca variabilele să fie declarate de la început. Ele se definesc
atunci când sunt folosite. Mai mult, îşi schimbă tipul în funcţie de valoarea
reţinută.
Exemplul 3.13. Analizaţi script-ul următor: iniţial, variabila $x reţine 1. Apoi, i se
atribuie un şir de caractere. Operaţia este posibilă şi în urma ei se reţine şirul, aşa
cum rezultă din valoarea afişată:
102
Baze de date – curs introductiv
În PHP este posibilă şi adresarea indirectă, aşa cum rezultă din exemplele
următoare.
Exemplul 3.14. Se afişează 3. Didactic, putem stabili ceea ce se afişează, astfel:
$$x = $($x) = $y = 3.
<?php
$x="y";
$y=3;
echo ($$x);
?>
Exemplul 3.15. Se afişează "Un sir". Astfel, avem:
$$$z = $$($z) = $$y = $($y) = $x = "Un sir".
<?php
$x="Un sir";
$y="x";
$z="y";
echo ($$$z);
?>
3.5.3. Operatori
Mulţi dintre operatorii limbajului PHP sunt cunoscuţi din C++. Acesta este
motivul pentru care vom prezenta doar anumite particularităţi specifice limbajului.
Pentru început, prezentăm, în ordine descrescătoare, prioritatea operatorilor:
1. !, ++, --, (int), (double), (string);
2. *, %, /;
3. <. <=, >, >=;
4. ==, !=, ===, !=== ;
5. &;
6. ^;
7
&&;
8. ?:;
9. =, +=, -=, /=. *=, %=, &=, |=, ^=;
10. And;
11. Xor;
12. Or;
13 ,.
Capitolul 3. Limbajul PHP

103
În PHP se pot folosi operatori de conversie explicită, cunoscuţi din C++.
Ca şi în C++, ei se aplică prefixat. Astfel, există: (int) - conversie către o
valoare întreagă, (string) - conversie către şir, iar (double) - conversie
către real.
Exemplul 3.16. Conversia unui număr real către un întreg are ca efect eliminarea
zecimalelor. Script-ul următor afişează valoarea 7:
<?php
$x=1;
$y=7.5;
$x=(int)$y;
echo ($x);
?>
Exemplul 3.17. Conversia unui şir către un întreg reuşeşte chiar dacă şirul conţine
şi caractere nenumerice! Caracterele numerice trebuie să ocupe primele poziţii! În
exemplul următor, în urma conversiei, x va reţine 2 şi y va reţine 3. Se afişează
suma, adică 5.
<?php
$x=" 2 siruri";
$y="3siruri";
$x=(int)$x;
$y=(int)$y;
echo ($x+$y);
?>
Observaţie ! Uneori, conversiile se realizează implicit (fără utilizarea operatorului
de conversie explicită).
Exemplul 3.18. Script-ul următor afişează -1.76:
<?php
$x="-2.76"; // sir
echo (1+$x);
?>
Exemplul 3.19. Se afişează -1:
<?php
$x="-2.76"; // sir
$y="1.76";
echo ($x+$y);
?>
Exemplul 3.20. Se afişează ... tot –1:
<?php
$x="-2.76 tren";
$y="1.76masina";
echo ($x+$y);
?>
104
Baze de date – curs introductiv

După efectuarea unei operaţii cu un operator din grupele 3 sau 4, se obţine
o valoare logică: true (1) sau false (0).

Operatorul === se referă la egalitate ca valoare şi ca tip, spre deosebire de
== care se referă la egalitate doar ca valoare. Exemplele următoare vă vor
convinge.
Exemplul 3.21. Script-ul următor afişează “egali ca valoare”:
<?php
$x="3";
$y=3;
if ($x===$y) echo(" egali ca valoare si tip");
else
if ($x==$y) echo ("egali ca valoare");
else echo "inegali ca valoare";
?>
Înlocuiţi în script-ul anterior primele două atribuiri cu atribuirile de mai jos. Veţi
observa că se afişează numai “egali ca valoare”. Aceasta demonstrează că,
deşi valorile logice au reţin 1 sau 0, ele rămân, de fapt, valori logice!
$x=2>1;
$y=1;
Observaţie ! Se poate deduce cu uşurinţă rolul operatorului !==. Operaţia pe care
o efectuează returnează true, dacă este diferenţă între tip sau valoare şi false,
în caz contrar.

Este permisă atribuirea multiplă.
Exemplul 3.22. Script-ul următor afişează “un sir”:
<?php
$x=1;
$y=-2;
$z="un sir";
$x=$y=$z;
echo ($x);
?>

Diferenţa dintre || şi Or, && şi And, ^ şi Xor este doar de prioritate!
Capitolul 3. Limbajul PHP
105
3.6. Instrucţiunile limbajului PHP
Instrucţiunile PHP sunt asemănătoare celor din C/C++. Din acest motiv, ne
vom limita la o scurtă prezentare a lor şi la câteva exemple de utilizare. Pentru
exemplificare, vom folosi următorul document HTML care trimite o valoare x către
server. Pe server se va găsi un script, numit ”index.php”, care răspunde
trimiţând o valoare către browser.
<html>
<head>
</head>
<body>
<form action="http://localhost" method="post">
<input type="text" name="x"> <br><br>
<input type="submit" value="GO">
</form>
</body>
</html>
3.6.1. Instrucţiunea expresie
Se foloseşte pentru diverse calcule sau atribuiri.
Exemplul 3.23. Analizaţi instrucţiunea: $x=$y*$y+1;.
3.6.2. Instrucţiunea IF
Această instrucţiune are forma generală:
if (expresie) instructiune1
else
instructiune2
Dacă expresie produce la evaluare o valoare diferită de 0 (true), se execută
instructiune1, altfel se execută instructiune2.
Exemplul 3.24. Dacă valoarea este în intervalul [1,2], se transmite către browser
valoarea (x+1)/2, altfel se transmite valoarea (x-1)/2:
<?php
if ($x>=1 && $x<=2) $v=($x+1)/2;
else
$v=($x-1)/2;
echo ($v);
?>
106
Baze de date – curs introductiv
3.6.3. Instrucţiunea compusă
Atunci când dorim ca mai multe instrucţiuni să fie interpretate ca una singură,
instrucţiunile se trec între "{" şi "}". Instrucţiunea switch are forma generală:
switch (expresie)

case exp1: secventa instructiuni1; break;
case exp2: secventa instructiuni2; break;
...
case expn: secventa instructiunin; break;
[default: secventa instructiunin+1];

unde expresie are semnificaţia: expresie de tip întreg, expi sunt expresii
constante de tip întreg, iar instrucţiunii, o secvenţă oarecare de instrucţiuni.
Principiul de executare este:

se evaluează expresia;

dacă aceasta produce o valoare egală cu cea produsă de expi, se
execută, în ordine, instrucţiunii şi se trece la instrucţiunea
următoare, altfel se execută numai secvenţa instrucţiunin+1.
Observaţie ! Alternativa default este facultativă. În absenţă, în cazul în care nu
există coincidenţă de valori, se trece la instrucţiunea următoare.
Exemplul 3.25. Dacă valoarea transmisă pentru x este 1, 2, 3, 4, atunci valoarea
respectivă este retransmisă către utilizator alfabetic, altfel, se va transmite un mesaj
oarecare.
<?php
switch ($x)
{
case (1):
case (2):
case (3):
case (4):
default :
}
?>
echo(“unu”); break;
echo(“doi”); break;
echo(“trei”); break;
echo(“patru”); break;
echo (“Nu este 1, 2, 3 sau 4”);
3.6.4. Instrucţiunea FOR
Instrucţiunea for are forma generală:
for(expresieiniţializare;expresietest;expresieincrementare) instrucţiune
Capitolul 3. Limbajul PHP
107
După cum se vede, între paranteze se găsesc 3 expresii:



Expresieinitializare se foloseşte, de regulă, pentru iniţializarea variabilei de
ciclare.
Expresietest se foloseşte pentru a testa dacă se execută instrucţiunea
subordonată - dacă expresia produce la evaluare o valoare diferită de 0
(true), instrucţiunea subordonată for se execută.
Expresieincrementare se foloseşte pentru incrementarea variabilei de
ciclare.
Principiul de executare este:
P1. Se evaluează expresieiniţializare.
P2. Se evaluează expresiatest. În cazul în care aceasta produce o valoare
diferită de 0, se execută instrucţiunea subordonată for; apoi se trece la P3,
altfel se trece la instrucţiunea următoare (se termină executarea instrucţiunii for).
P3. Se evaluează expresia de incrementare şi se revine la P2.
Exemplul 3.26. Se calculează suma pătratelor primelor x numere naturale (x este
număr natural):
<?php
$s=0;
for ($i=1;$i<=$x;$i++) $s+=$i*$i;
echo($s);
?>
3.6.5. Instrucţiunea WHILE
Instrucţiunea while are forma generală:
while (expresie) instructiune
Principiul de executare este următorul:
P1. Se evaluează expresia;
P2. Dacă valoarea produsă de aceasta este diferită de 0, se execută instrucţiunea subordonată, apoi se revine la P1, altfel se trece la instrucţiunea următoare.
Exemplul 3.27. Se calculează suma de la exemplul anterior:
<?
$s=0; $i=1;
while ($i<=$x)
{ $s+=$i*$i;
$i++;
}
echo($s);
?>
Observaţie ! Script-ul oferă şi un exemplu de instrucţiune compusă.
108
Baze de date – curs introductiv
3.6.6. Instrucţiunea DO WHILE
Forma generală a acestei instrucţiuni este următoarea:
do
instructiune
while(expresie);
Principiul de executare este următorul:
P1. Se execută instrucţiunea subordonată;
P2. Se evaluează expresia. În cazul în care valoarea produsă la evaluare este
0 (false), executarea instrucţiunii do se termină, altfel se trece la P1.
Exemplul 3.28. Se calculează suma pătratelor primelor x numere naturale (x este
natural):
<?php
$s=0; $i=1;
do
{
$s+=$i*$i;
$i++;
} while ($i<=$x);
echo($s);
?>
3.7. Funcţii în PHP
În PHP se pot crea funcţii fără prea mari diferenţe faţă de ce ştim din C/C++.
Exemplul 3.29. Mai jos este prezentat un script care utilizează o funcţie pentru a
calcula aria unui triunghi, pe care apoi o afişează:
<?php
function aria_t($b, $h)
{ return $b*$h/2; }
$x=3;
$y=8;
echo(aria_t($x,$y));
?>

Pentru a întoarce rezultate se utilizează, aşa cum suntem deja obişnuiţi,
return. Forma generală este: return expresie.

Transmiterea parametrilor se face prin valoare şi prin referinţă.
Capitolul 3. Limbajul PHP
109
A) Dacă un parametru este transmis prin valoare, atunci valoarea sa rămâne
neschimbată după executarea funcţiei. Prin valoare se pot transmite atât valori, cât
şi conţinutul unor variabile.
Exemplul 3.30. Script-ul următor afişează 5, chiar dacă în funcţie s-a încercat
modificarea valorii transmise:
<?php
function f($x)
{ $x++; }
$x=5;
f($x);
echo($x);
?>
Exemplul 3.31. Script-ul următor exemplifică faptul că o funcţie poate fi apelată
atât printr-o valoare care este conţinutul unei variabile, cât şi printr-o valoare
oarecare. Se afişează 3 şi 7, deci 37.
<?php
function f($x)
{ echo($x); }
$x=3;
echo(f($x));
echo (f(7));
?>
B) Dacă un parametru este transmis prin referinţă atunci, în corpul funcţiei, se
poate modifica valoarea sa. Evident, un parametru transmis prin valoare trebuie să
fie o variabilă. Pentru a transmite un parametru prin referinţă, el trebuie precedat
de caracterul &.
Exemplul 3.32. În script-ul următor, se modifică valoarea parametrului transmis
prin referinţă. Se va afişa 6, nu 5, cât era valoarea iniţială a variabilei $x:
<?php
function f(&$x)
{ $x++; }
$x=5;
f($x);
echo($x);
?>

O variabilă se numeşte globală dacă a fost definită în afara oricărei funcţii.
Implicit, ea nu poate fi adresată din corpul unei funcţii. Totuşi, există o
posibilitate de a face acest lucru: ataşăm cuvântul global înaintea acestei
variabile!
Exemplul 3.33. Funcţia din script-ul următor returnează 3. Aceasta arată că a fost
recunoscută variabila globală $x. În absenţa cuvântului global, această valoare
nu ar fi putut fi returnată:
110
Baze de date – curs introductiv
<?php
function f()
{ global $x;
return $x;
}
$x=3;
echo(f());
?>

Variabilele locale sunt variabile create în corpul unei funcţii sau cele create
prin transmiterea parametrilor formali (din antetul funcţiilor). Ele nu sunt
recunoscute în afara funcţiilor. Nimic nou...

În PHP, funcţiile pot fi şi recursive.
Exemplul 3.34. Script-ul de mai jos calculează n! prin utilizarea unei funcţii
recursive:
<?php
function fact($n)
{ if ($n==0) return 1;
else return $n*fact($n-1);
}
echo(fact(4));
?>
Desigur, atunci când scriem un script mai complicat, cu multe funcţii, este necesar
să dispunem de un mecanism prin care să putem include funcţii pe care le-am
scris mai demult, sau pe care le-am primit de undeva...

Includerea unor funcţii, dar nu numai, se realizează prin funcţia
require("nume_fisier").
Funcţiile trebuie să se găsească pe site, într-un fişier text. Observaţi faptul
că textul funcţiei (funcţiilor inserate) trebuie să fie încadrat între <? şi ?>.
Exemplul 3.35. Funcţia afis() se găseşte în fişierul functia.ex, aflat pe site.
Script-ul care o utilizează conţine require():
<?php
function afis()
{ echo("Eu sunt functia inserata"); }
?>
<?
require("functia.ex");
afis();
?>
Pe lângă faptul că putem să scriem diverse funcţii, limbajul PHP este
înzestrat cu numeroase alte funcţii. Cele mai importante vor fi tratate pe parcurs.
Capitolul 3. Limbajul PHP
111
3.8. Funcţii “matematice”
Multe dintre funcţiile prezentate le-aţi întâlnit dacă aţi studiat limbajul C/C++.
Tabelul următor le prezintă succint:
Funcţia
Ce realizează
Exemple
abs(numar)
Returnează modulul
numărului.
abs(-7)=7;
abs(-2.23)=2.23;
abs(2.3)=2.3
sin(x), cos(x),
tan(x)
Sinusul, cosinusul şi
tangenta unui unghi.
Argumentul x este dat
în radiani
exp(x)
Returnează ex .
pow(x,y)
Returnează xy.
log10(x), log(x)
max(x1, x2,... xn),
min(x1, x2,... xn)
ceil(x)
round(x)
floor(x)
rand(min,max)
.
Returnează
log 10 ( x) ,
respectiv log 2 ( x) .
Returnează maximul,
minimul dintr-un şir de
argumente numerice.
Returnează cel mai mic
întreg mai mare sau
egal cu x.
Returnează întregul
rezultat prin rotunjirea
lui x.
Returnează cel mai
mare întreg mai mic sau
egal cu x.
Returnează o valoare
întreagă aleatoare între
valorile întregi min şi
max (inclusiv).
pi()
Returnează numărul .
sqrt(x)
Returnează rădăcina
pătrată a lui x.
Tabelul 3.1. Funcţii “matematice”
ceil(4.3)=5,
ceil(-4.3)=-4
round(4.3)=4,
round(4.7)=5.
floor(4.3)=4,
floor(-4.3)=-5
rand(1,10) poate
returna orice valoare
întreagă din [1,10].
sqrt(4)=2;
112
Baze de date – curs introductiv
3.9. Afişarea datelor - echo şi print
Pentru a afişa datele pe browser se folosesc echo şi print. Acestea nu
sunt funcţii în accepţiunea clasică a cuvântului, deşi pot fi utilizate asemenea
funcţiilor. Ele sunt construcţii speciale PHP - ambele afişează şiruri de caractere.
A) echo – datorită simplităţii, a fost utilizată de multe ori până acum. Pentru că
poate fi utilizată în multe feluri, o vom prezenta prin exemple şi vom renunţa la
prezentarea formei generale.
Exemplul 3.36. Afişăm un şir de caractere folosind parantezele rotunde (apel ca în
cazul funcţiilor):
echo("Un mesaj");
Exemplul 3.37. Afişăm un şir de caractere fără să utilizăm parantezele rotunde.
Pentru că este permisă o astfel de utilizare, spunem că echo nu este funcţie, ci
construcţie specială.
echo "Un mesaj";
Exemplul 3.38. În cazul în care nu se folosesc paranteze, se pot afişa mai multe
şiruri de caractere:
echo "Un mesaj ", "Alt mesaj";
Exemplul 3.39. Putem afişa şi conţinutul unor variabile, aşa cum rezultă din
exemplul următor:
<?php
$x=6;
echo ("Am $x mere"); // sau echo "Am $x mere";
?>
B) print – se utilizează la fel ca echo, dar, dacă utilizăm paranteze, se poate
folosi valoarea întoarsă: true, dacă şirul a fost expediat sau false, în caz contrar.
Exemplul 3.40. Priviţi exemplul de mai jos:
print ("Un exemplu");
<?php
$x=6;
$y=8;
print ("Ana are
?>
$x mere
si <br>
$y pere");
Observaţie ! ”<br>” se utilizează pentru salt la linie nouă! Vezi HTML...
Capitolul 3. Limbajul PHP
113
Observaţii foarte importante !
1. În loc de “” se pot folosi şi ‘’. Diferenţa este dată de faptul că, în cazul folosirii
‘’, dacă şirul de caractere conţine numele unei variabile, nu se afişează conţinutul
variabilei, ci se afişează numele variabilei.
Exemplul 3.41. Dacă comanda este echo ‘Am $x mere’ se va afişa
Am $x mere.
2. Nu se pot folosi “” incluse între “” şi nici ‘’ incluse între ‘’.
Exemplul 3.42. Secvenţele de mai jos sunt incorecte:
echo " Am “o multime” de prieteni";
echo ‘ Am 'o multime' de prieteni’;
3. În schimb, putem include între “” caracterele ‘’.
Exemplul 3.43. Instrucţiunea următoare
echo " Am 'o multime' de prieteni";
afişează
Am ‘o multime’ de prieteni.
4. În schimb, putem include între ‘’ caracterele “”.
Exemplul 3.44. Instrucţiunea următoare
echo ‘ Am “o multime” de prieteni’;
afişează
Am “o multime” de prieteni.
3.10. Funcţii pentru prelucrarea şirurilor de caractere
În PHP există un set puternic de funcţii, asemănătoare celor din C++, care
lucrează cu şiruri de caractere. De asemenea, există şi un operator de
concatenare a şirurilor.

Şirurile se memorează ca o succesiune de caractere ASCII. Putem adresa
fiecare caracter al şirului, aşa cum suntem obişnuiţi, prin indicele său. Primul
caracter are indicele 0.
Exemplul 3.45. În secvenţa următoare, se afişează caracterul “U”:
$sir="Un exemplu";
echo ($sir[0]);
114

Baze de date – curs introductiv
Operatorul de concatenare a şirurilor este punctul.
Exemplul 3.46. Se afişează "Ana are 9 mere!". Observaţi faptul că valoarea
numerică a fost convertită implicit către şir.
$x=9;
$sir="Ana ". "are ".
echo $sir;

$x. " mere!";
Funcţia strlen(sir) returnează lungimea şirului (numărul de caractere
ale şirului).
Exemplul 3.47. În secvenţa de mai jos se afişează 10 (se numără şi blank-ul):
$sir="Un exemplu";
echo strlen($sir);

funcţia strpos(sir1, sir2, [poz_start]) caută dacă sir2 este
subşir al lui sir1. În caz afirmativ, returnează poziţia de început a acestuia,
altfel returnează false. Al treilea parametru specifică funcţiei indicele
caracterului de unde să înceapă căutarea. Dacă nu este completat, căutarea
începe din poziţia 0.
Exemplul 3.48. La executarea secvenţei următoare, se afişează 5:
$sir="Un exemplu";
echo (strpos($sir, "em"));

Funcţia se utilizează şi pentru a testa dacă un şir include sau nu un anumit
subşir. Dacă subşirul este găsit, se returnează poziţia de început a acestuia
în subşir, dacă nu, se returnează false. După cum ştim, valoarea lui false
este, de fapt, 0. Ce ne facem în cazul în care subşirul se găseşte şi începe
în poziţia 0? Cum facem distincţia între acest caz şi cel în care subşirul nu
este găsit? Priviţi secvenţa din exemplul de mai jos, care rezolvă corect
problema şi subliniază importanţa operatorului “===”.
Exemplul 3.49. Secvenţa este următoarea:
<?php
$sir="Un exemplu";
$gasit=strpos($sir, "U");
if ($gasit===false) echo ("Nu este");
else echo ("Este");
?>
Valoarea întoarsă de funcţie este reţinută de variabila $gasit. Pentru a face
distincţie între false şi 0, se foloseşte operatorul “===”, care testează
coincidenţa atât ca valoare, cât şi ca tip. De altfel, acesta este şi rostul unui astfel
de operator. Acest procedeu se poate folosi şi pentru alte funcţii.
Capitolul 3. Limbajul PHP

115
Funcţia strstr(sir1,sir2) returnează sir1 din poziţia în care a fost
găsit sir2, dacă sir2 este subşir pentru sir1 sau false, în caz contrar.
Exemplul 3.50. În secvenţa următoare se afişează “exemplu”:
$sir="Un exemplu";
$gasit=strstr($sir, "ex");
if ($gasit===false) echo ("Nu este in sir");
else echo ($gasit);

Funcţia strcmp(sir1,sir2) compară lexicografic (alfabetic) sir1 cu
sir2. Valoarea returnată este:



<0, dacă sir1 < sir2;
>0, dacă sir1 > sir2;
0, dacă sir1 = sir2.
Exemplul 3.51. Priviţi comparaţiile de mai jos:



strcmp ("mama", "tata"); returnează un rezultat <0.
strcmp ("ab", "a"); returnează un rezultat >0.
strcmp ("abc", "abc"); returnează 0.
Observaţie ! Comparaţia face distincţie între literele mari şi cele mici!

Funcţia substr(sir,ind,[lung]) returnează subşirul şirului sir, care
începe în poziţia ind şi are lungimea lung. Dacă parametrul lung este
absent, se returnează şirul care începe în poziţia ind şi ţine până la
sfârşitul şirului sir.
Exemplul 3.52. După executarea secvenţei, se afişează “exemplu”:
$sir="Un exemplu";
echo (substr($sir,3));
Exemplul 3.53. După executarea secvenţei, se afişează “ex”:
$sir="Un exemplu";
echo (substr($sir,3,2));

Funcţia substr_replace(sir1, sir2, ind, [lung]) returnează şirul
rezultat prin înlocuirea în sir1, a subşirului care începe în poziţia ind şi are
lungimea lung cu sir2. Dacă parametrul lung este absent, sir2
înlocuieşte subşirul care începe cu ind şi ţine până la sfârşitul şirului sir2.
Exemplul 3.54. Secvenţa următoare afişează “Un templu”:
$sir="Un exemplu";
echo (substr_replace($sir,"t",3,2));

Funcţia strtoupper(sir) returnează şirul convertit în litere mari, iar funcţia
strtolower(sir) returnează şirul convertit în litere mici.
116
Baze de date – curs introductiv
3.11. Masive în PHP
În PHP există o “libertate” extraordinară de lucru cu masive. Începem prin a
spune că masivele nu se declară.
Exemplul 3.55. În script-ul următor, se creează şi se afişează un vector cu 5
componente:
<?php
for ($i=0;$i<5;$i++) $x[$i]=$i;
for ($i=0;$i<5;$i++) echo( "$x[$i] <br>" );
?>
Exemplul 3.56. Se creează şi se afişează o matrice cu 5 linii şi 5 coloane.
Elementele din linia i şi coloana j reţin valorile i+j.
<?php
for ($i=0;$i<5;$i++)
for ($j=0;$j<5;$j++) $mat[$i][$j]=$i+$j;
for ($i=0;$i<5;$i++)
{ for ($j=0;$j<5;$j++) echo($mat[$i][$j]." ");
echo("<br>");
}
?>

În PHP, indicii pot fi şiruri de caractere.
Exemplul 3.57. Probaţi script-ul următor, unde un vector de indici nume de
persoane, reţine numerele lor de telefon. Acesta este un tablou asociativ:
<?php
$x["Ioana"]="0724xxx";
$x["Valentina"]="031xxx";
$x["Paul"]="0211xxx";
$x["Cristian"]="0232xxx";
print $x["Ioana"]."<br>";
print $x["Valentina"]."<br>";
print $x["Paul"]."<br>";
print $x["Cristian"]."<br>";
?>
Faptul că există posibilitatea utilizării unor astfel de indici creează, pe lângă
avantaje, probleme. Imaginaţi-vă că vreţi să parcurgeţi şi să listaţi un astfel de
vector. Care este numărul componentelor? Să zicem că pe acesta îl reţinem într-o
variabilă, dar ce valori ia variabila de ciclare?

Funcţia count(nume_vector) returnează numărul de componente ale
vectorului.
Capitolul 3. Limbajul PHP
117
Exemplul 3.58. Pentru vectorul din script-ul anterior, cu ajutorul expresiei
echo(count($x));, se afişează 4.

Instrucţiunea de mai jos are rolul de a ne permite o parcurgere uşoară a unui
vector cu numele vector, cu variabila de ciclare indice, în care citirea se
face în variabila variabila:
foreach(vector as indice=>variabila).
Exemplul 3.59. Se creează un vector şi se parcurge cu foreach(...), afişând
rezultatele parcurgerii:
<?php
$x["Ioana"]="0724xxx";
$x["Valentina"]="031xxx";
$x["Paul"]="0211xxx";
$x["Cristian"]="0232xxx";
foreach($x as $i=>$nume)
echo($i." ".$nume."<br>");
?>
Iată ce se afişează, alăturat!
Există şi alte funcţii care permit accesarea cu uşurinţă a elementelor
vectorului. Ideea de la care se pleacă este următoarea: există un pointer care
întotdeauna este asupra unui element al vectorului.

Funcţia current(vector); returnează valoarea reţinută de elementul din
vector asupra căruia se găseşte pointer-ul.

Funcţia key(vector); returnează indicele elementului din vector asupra
căruia se găseşte pointer-ul.

Funcţia next(vector); deplasează pointer-ul pe elementul următor din
vector şi returnează valoarea reţinută de acesta.

Funcţia prev(vector); deplasează pointer-ul pe elementul anterior al
vectorului şi returnează valoarea reţinută de acesta.
Exemplul 3.60. Analizaţi script-ul de mai jos:
<?php
$x["Ioana"]="0724xxx";
$x["Valentina"]="031xxx";
$x["Paul"]="0211xxx";
$x["Cristian"]="0232xxx";
echo(current($x)." ".key($x)."<br>");
echo(next($x)." ".key($x)."<br>");
echo(prev($x)." ".key($x)."<br>");
echo(count($x)."<br>");
?>
118
Baze de date – curs introductiv
Dacă, în general, sortarea unui vector (tablou) se poate efectua cu ajutorul
unui algoritm oarecare de sortare, în cazul unui tablou asociativ, cum lesne vă
puteţi da seama, problema este mai complicată. Din acest motiv, PHP-ul pune la
dispoziţia programatorilor funcţii specifice.
Exemplul 3.61. Pentru a testa modul în care acestea efectuează sortarea, vom
folosi script-ul următor, în care linia “metoda de sortare“ se va înlocui cu
funcţia respectivă:
<?php
$x["Ioana"]="0724xxx";
$x["Valentina"]="031xxx";
$x["Paul"]="0211xxx";
$x["Cristian"]="0232xxx";\
foreach($x as $i=>$nume) echo($i." ".$nume."<br>");
//metoda de sortare
?>

Funcţia Asort(vector) sortează crescător vectorul
după valoarea reţinută de fiecare element. Rezultatul
este prezentat în figura alăturată.

Funcţia Arsort(vector) sortează descrescător
vectorul după valoarea reţinută de fiecare element.
Rezultatul este prezentat alăturat.

Funcţia Ksort(vector) sortează crescător vectorul
după indici (vezi figura alăturată).

Funcţia Krsort(vector) sortează descrescător
vectorul după indici. Rezultatul este cel alăturat.

Funcţiile sort() şi rsort() sortează crescător, respectiv
descrescător, un masiv de indici 0, 1, ..., n. În cazul în care
avem un masiv asociativ, vechile valori ale indicilor se pierd
(vezi figura alăturată).
Capitolul 3. Limbajul PHP
119
3.12. Variabile cookie
Atunci când utilizarea Internet-ului a luat amploare, s-a pus următoarea
problemă: cum trebuie procedat pentru ca server-ul să utilizeaze anumite opţiuni
ale utilizatorului, astfel încât, atunci când acesta intră pe site, să nu mai piardă
timpul selectându-le din nou? Mai mult, dacă se dispune de astfel de informaţii,
pagina afişată pentru un anumit utilizator ar putea fi personalizată. Problema a fost
rezolvată de cei de la firma Netscape în anul 1994.
Mecanismul care stă la baza acestei probleme se bazează pe memorarea,
pe calculatorul vizitatorului unui anumit site, a unor informaţii sub forma unor mici
fişiere text. Operaţia poate fi comandată de pe server şi tot de pe server se poate
comanda citirea, actualizarea sau ştergerea acestor mici fişiere, numite uzual, prin
abuz de limbaj, variabile cookie.
În PHP se poate lucra foarte uşor cu variabilele cookie.

Pentru a crea o variabilă cookie se utilizează funcţia
setcookie (nume_variabila, valoare, data_expirare)
Exemplul 3.62. În script-ul de mai jos, se creează o variabilă cookie numită
copac. Variabila reţine valoarea verde şi expiră într-o oră.
<?php
// creeaza o variabila cookie
setcookie("copac", "verde", time()+3600);
?>
Observaţii !
1. Nu pot exista simultan mai mult de 20 de variabile cookie. Dacă se creează una
în plus, prima creată este ştearsă automat.
2. Pentru a şterge o variabilă cookie se creează o alta cu acelaşi nume, dar cu
data de expirare înaintea datei curente (de exemplu, time()-1).

Pentru a citi o variabilă cookie se utilizează conţinutul unui masiv asociativ,
numit $HTTP_COOKIE_VARS. Fiecare componentă a sa, de indice numele
variabilei cookie, reţine valoarea variabilei cookie.
Exemplul 3.63. În script-ul de mai jos se afişează valoarea variabilei cookie creată
de script-ul anterior:
<?php
// afiseaza verde
echo $HTTP_COOKIE_VARS["copac"];
?>
Analizaţi şi exemplele următoare …
120
Baze de date – curs introductiv
Exemplul 3.64. În script-ul de mai jos se creează 20 de variabile cookie numite
V1, V2, ..., V20 care reţin respectiv 1, 2, ..., 20:
<?php
for ($i=1;$i<=20;$i++)
setcookie("V".$i, $i, time()+10000);
echo "OK complet"
?>
Exemplul 3.65. În script-ul de mai jos se afişează conţinutul variabilelor cookie
existente pe calculatorul vizitatorului:
<?php
foreach($HTTP_COOKIE_VARS as $i=>$nume)
echo $i." ".$nume."<br>";
?>
Exemplul 3.66. Script-urile care urmează exemplifică modul în care se pot reţine
anumite informaţii pe care utilizatorul le-a tastat o dată. Apelat pentru prima dată,
atunci când nu există variabila cookie nume, se cere numele vizitatorului. Acesta
va introduce numele şi va apăsa butonul insereaza (vezi fig. din stânga). Dacă
respectivul vizitator, reintră pe acel site, reapelând script-ul, acesta va identifica
variabila cookie nume, va prelua numele memorat şi, în loc ca vizitatorului să i se
ceară din nou numele, se va afişa mesajul (vezi fig. din dreapta).
<?php
$gasit=0;
// se cauta daca exista variabila cookie nume
foreach($HTTP_COOKIE_VARS as $i=>$v)
if($i=="nume")
$gasit=1;
//daca exista se afiseaza un mesaj
if ($gasit==1)
echo " Bine ati venit pe site-ul nostru domnule:
".$HTTP_COOKIE_VARS["nume"];
// daca nu exista, se afiseaza cele necesare pentru
// identificare si se creeaza variabila nume
else
echo "<FORM action='cc.php' method ='post'>"."Nume<br>".
"<input name='Nume' type='text'>;". "<br>".
"<input type='submit', value='insereaza'>";
?>
Capitolul 3. Limbajul PHP
121
3.13. Utilizarea în comun a limbajelor PHP şi MySQL
3.13.1. Crearea unei baze de date
În acest paragraf prezentăm modul în care se utilizează împreună PHP şi
MySQL. Vom presupune că server-ul care găzduieşte site-ul dispune de soft-ul
necesar. Desigur, prezentarea aplicaţiilor se va face în continuare pe propriul
calculator, prin utilizarea pachetului EasyPHP. Orice script PHP va fi scris în folder-ul
www, inclus în folder-ul EasyPHP (versiunea pe care o aveam în momentul scrierii
cărţii pe calculatorul nostru este 14).

Orice script PHP care lucrează cu MySQL trebuie să se conecteze la acesta.
Pentru conectare, se utilizează funcţia mysql_connect() sub forma:
resursa = mysql_connect("nume_gazda","nume_utilizator",
"parola")
În cazul nostru, numele gazdei este http://localhost:3388, iar numele
utilizatorului şi parola sunt cele utilizate în Anexa 1, atunci când am creat parola
pentru root. În cazul în care conectarea a reuşit se returnează resursa, altfel, se
returnează FALSE. 3388 este portul folosit pentru a comunica cu serverul.

Pentru a da o comandă MySQL dintr-un script PHP se utilizează funcţia
mysql_query(), care primeşte instrucţiunea sub forma unui şir de
caractere. Şi aici, în caz că operaţia a reuşit, se returnează o valoare diferită
de 0, altfel se returnează 0.
resursa = mysql_query(instructiune_mysql)
Exemplul 3.67. Se cere să se scrie un script, cre_baza.php, care creează baza
de date, numită baza. Practic, script-ul va realiza conexiunea la MySQL, după care
va da comanda de creare a bazei de date. În ambele operaţii, în caz de nereuşită,
se va da un mesaj de eroare lămuritor.
<?php
// conectarea la MySQL
$msql=mysql_connect("localhost:3388","root","parolamea");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL!"; exit; }
// crearea bazei de date numita baza
$rezultat=mysql_query("CREATE DATABASE baza");
if (!$rezultat)
echo "Nu s-a reusit crearea bazei de date...";
else
echo "Baza de date a fost creată cu succes!"
?>
122
Baze de date – curs introductiv
Pentru a rula script-ul, se dă următoarea comandă browser-ului:
http://192.168.1.217/cre_baza.php
Dacă dorim ca mesajele de eroare să ne ajute mai mult în depanare, vom
utiliza două funcţii MySQL.

Funcţia string mysqlerrno() returnează codul numeric al ultimei erori.
Lista parametrilor este vidă.

Funcţia string mysqlerror() returnează mesajul asociat ultimei erori.
Şi în cazul ei, lista parametrilor este vidă.
Exemplul 3.68. Înlocuiţi ultimul echo din scriptul anterior cu:
echo mysql_errno().":".mysql_error();
În cazul în care veţi rula din nou script-ul, va apărea o eroare care se
datorează faptului că se încearcă crearea unei baze de date care există deja. Iată
cum este afişată eroarea în acest caz:
1007: Can’t create database ‘baza’; database exists
Codul arătă acum ca mai jos:
<?php
//conectarea la MySQL
$msql=mysql_connect("localhost:3388","root","parola23");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL!";
echo mysql_errno()." : ".mysql_error();
exit;
}
//crearea bazei de date numita baza
$rezultat=mysql_query("CREATE DATABASE baza");
if (!$rezultat)
echo "Nu s-a reusit crearea bazei de date.";
else
echo "Baza de date a fost creata cu succes!";
?>
Bineînțeles, acesta va fi apelat o singură dată deoarece ulterior vom obține o
eroare – baza de date deja există, nu?
Capitolul 3. Limbajul PHP
123
3.13.2. Accesul la o bază de date şi crearea unui tabel
în baza de date

Pentru a avea acces la o bază de date, se utilizează funcţia de mai jos, care
returnează, aşa cum suntem obişnuiţi, o valoare diferită de 0 în caz de
reuşită şi 0, în caz contrar.
bool mysql_select_db(nume_baza)
După realizarea accesului, putem crea tabelul prin utilizarea instrucţiunii
mysql_query().
Exemplul 3.69. Se cere să se scrie un script, cre_tabel.php, prin care să se
creeze un tabel, numit vizitatori, care reţine, pentru fiecare persoană trecută
în tabel, numele, vârsta şi adresa de e-mail.
<?php
// conectarea la MySQL
$msql=mysql_connect("localhost:3388","root","parolamea");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL."; exit;
}
// conectarea la baza de date
$baza=mysql_select_db("baza");
if (!$baza)
{ echo mysql_errno().":".mysql_error(); exit; }
// crearea tabelului
$interogare="CREATE TABLE vizitatori (nume CHAR(30), varsta
INT, email CHAR(20) PRIMARY KEY)";
$rezultat=mysql_query($interogare);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>
Testaţi script-ul apelând: http://192.168.1.217/cre_tabel.php.
UTIL
În toate operaţiile pe care le vom face de acum înainte cu această bază de
date vom avea nevoie, în mod evident, de conectarea la MySQL şi accesul la baza
de date. Pentru ca să nu repetăm această secvenţă, se scrie script-ul de mai jos,
numit conectare.php():
<?php
// conectarea la MySQL
$msql=mysql_connect("localhost","root","parolamea");
124
Baze de date – curs introductiv
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL..."; exit; }
// conectarea la baza de date
$baza=mysql_select_db("baza");
if (!$baza)
{ echo mysql_errno().":".mysql_error(); exit; }
?>

Pentru ca un script să includă un altul şi să-l execute se foloseşte funcţia
MySQL de mai jos, care are ca parametru numele script-ului care urmează
să fie inclus: require_once(nume_script);
Exemple de utilizare ale acestui script veţi găsi în paragrafele următoare.
3.13.3. Inserarea liniilor în tabel
Am creat o bază de date, numită baza, cu un tabel, numit vizitatori.
Rămâne să introducem date în acest tabel. Vom presupune că fiecare utilizator al
bazei de date se autoînregistrează, scriind datele în nişte edit-uri afişate de pagină.
Problema se rezolvă în două părţi.
A) Se creează o pagină, s-o numim i_date.php, care conţine edit-urile prin care
se introduc datele şi butonul la apăsarea căruia datele sunt transmise către server.
Modul de creare a unei astfel de pagini a fost descris, prin urmare prezentăm
numai codul ei şi tabelul pe care-l afişează. La apăsarea butonului inserează se
apelează script-ul insereaza.php aflat pe server (în cazul nostru, în folder-ul
www). Pagina va fi apelată prin comanda următoare:
http:// 192.168.1.217/cre_tabel.php.
Codul sursă pentru pagina i_date.php este:
<html>
<head></head>
<body>
<form action="insereaza.php"
method ="post">
Nume <br>
<input name="nume" type="text">; <br>
Varsta <br>
<input name="varsta" type="text">; <br>
Adresa e-mail <br>
<input name="email" type="text">; <br>
<input type="submit", value="insereaza">
</form>
</body>
</html>
Capitolul 3. Limbajul PHP
125
B) După ce vizitatorul paginii respective îşi completează datele şi apasă butonul
insereaza, acestea sunt transmise către server şi sunt preluate de către script-ul
insereaza.php. Acesta preia datele şi le introduce în tabelul vizitatori.
<?php
require_once("conectare.php");
$nume= $_POST['nume'];
$varsta= $_POST['varsta'];
$email= $_POST['email'];
$cerere="INSERT INTO vizitatori (nume,varsta,email)
VALUES('$nume',$varsta,'$email')";
$rezultat=mysql_query($cerere);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>
Observaţii !
1. Pentru câmpurile nume şi email datele sunt de tip şir de caractere. Ele sunt
memorate de variabilele $nume şi $email. Pentru a le introduce ca şiruri, vom
trece variabilele între apostrofuri: ‘$nume’, ‘$email’.
2. După introducerea unui rând, testaţi dacă acesta a fost sau nu folosind
comanda SQL sau direct din phpmyadmin: SELECT * FROM vizitatori.
Este foarte important ca datele introduse să fie validate. Astfel, numele
trebuie să fie nevid, varsta trebuie să fie o valoare numerică mai mare sau egală
ca 10 şi mai mică sau egală cu 90 şi adresa de e-mail trebuie să conţină caracterul
‘@’. Vom rescrie script-ul, de această dată cu validări.
Observaţie ! Atunci când se depistează o eroare, se afişează un mesaj lămuritor şi
se reafişează formularul de introducere a datelor!
<?php
require_once("conectare.php");
$nume= $_POST['nume'];
if (strcmp($nume,"")==0)
{echo "Nu ati scris numele";
require_once("i_date.php");
exit;
}
$varsta= $_POST['varsta'];
if (!is_numeric($varsta) || $varsta<10
{echo "Varsta incorecta";
require_once("i_date.php");
exit;
}
||$varsta>90)
126
Baze de date – curs introductiv
$email= $_POST['email'];
if (!strpos($email,"@"))
{
echo "Adresa de e-mail gresita";
require_once("i_date.php");
exit;
}
$cerere="INSERT INTO vizitatori (nume,varsta,email)
VALUES('$nume',$varsta,'$email')";
$rezultat=mysql_query($cerere);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>
3.13.4. Afişarea unui tabel
În acest paragraf vom arăta modul în care se listează rezultatul unei
interogări. După cum am văzut, o interogare se realizează cu mysql_query().
Ea returnează o valoare care, în cazul în care interogarea a reuşit, este diferită de
0. În cazul în care rezultatul unei interogări este alcătuit din mai multe rânduri, ca
de exemplu în cazul listării unui tabel, nu se afişează direct rezultatul, aşa cum
suntem obişnuiţi. În astfel de cazuri, pornind de la valoarea returnată de
mysql_query(), se afişează tabelul rând cu rând.

Funcţia mysql_fetch_array() returnează un rând al unei interogări (în
cazul de faţă, al unui tabel) sub forma unui tablou asociativ. După returnarea
rândului, automat se trece la rândul următor.
array mysql_fetch_array(resursa)
Pornind de la tabloul asociativ returnat, se poate accesa orice câmp al
interogării.
Exemplul 3.70. Analizaţi script-ul
următor, unde se afişează datele
introduse în tabel. Rezultatul îl puteţi
observa în figura alăturată.
<?php
require_once("conectare.php");
$cerere="SELECT * FROM vizitatori";
$rezultat=mysql_query($cerere);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
// pentru fiecare rand al tabelului
while($rand=mysql_fetch_array($rezultat))
echo $rand["nume"]." ".$rand["varsta"]." ".
$rand["email"]."<br>";
?>
Capitolul 3. Limbajul PHP
127
Desigur, datorită formei inestetice,
această afişare a tabelului nu ne
convine. Din acest motiv, vom afişa
tabelul, aşa cum îl observaţi alăturat.
Pentru aceasta, vom rescrie script-ul
afisare_tabel:
<?php
require_once("conectare.php");
$cerere="SELECT * FROM vizitatori";
// in urma interogarii, se returneaza tabelul
$rezultat=mysql_query($cerere);
if (!$rezultat)
{ echo mysql_errno().":".mysql_error(); exit; }
// afisam datele sub forma unui tabel
echo "<table border=5>";
// afisam capul de tabel
Echo "<tr><td align='center'>
<b>Nume</b><td><b>Varsta</b><td><b>Adresa e-mail</b>";
// Pentru fiecare rand al tabelului
while($rand=mysql_fetch_array($rezultat))
{ echo "<tr>";
echo "<td>".$rand["nume"].
"<td align='right'>".$rand["varsta"]."<td>".
"<a href=mailto:".$rand["email"].">".$rand["email"]."</a>";
echo "</tr>";
}
echo "</table>";
?>
Apelaţi script-ul prin: http:// 192.168.1.217/afisare_tabel.php.
128
Baze de date – curs introductiv
3.14. Aplicaţii
3.14.1. Inscrierea pe un site
În unele site-uri se cere ca, în prealabil, vizitatorii respectivului site să se
înscrie în baza de date a acestuia. De regulă, utilizatorului i se cere ID-ul
(nickname-ul) şi parola. Acestea sunt memorate într-un tabel şi de câte ori utilizatorul
doreşte să acceseze din nou site-ul, ele sunt cerute pentru identificare. Accesul la
site se realizează numai atunci când ID-ul şi parola se regăsesc în baza de date.
A) Pentru început, este necesar ca să se creeze o bază de date, de exemplu,
inscrisi, care conţine un singur tabel, parole.
Script-ul următor, btab.php, realizează cele de mai sus:
<?php
//conectarea la MySQL
$msql=mysql_connect("localhost:3388","root","parola");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit; }
//crearea bazei de date numita baza
$rezultat=mysql_query("CREATE DATABASE inscrisi");
if (!$rezultat)
{ echo "Nu s-a reusit crearea bazei de date...";
exit;
}
$baza=mysql_select_db("inscrisi");
$interogare="CREATE TABLE parole ( nume CHAR(30) PRIMARY
KEY, parola CHAR(10))";
$rezultat=mysql_query($interogare);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>
În cele ce urmează, vom presupune că am rulat script-ul btab.php, deci
baza de date şi tabelul sunt create:
Capitolul 3. Limbajul PHP
129
B) Dacă un vizitator accesează site-ul, este afişată pagina alăturată, în care i se
cere, fie să se identifice, în cazul în care este înscris deja, fie să se înscrie, în caz
contrar.
Pentru a realiza pagina respectivă, se foloseşte un simplu fişier HTML (sau
PHP), vedeţi mai jos (index.php). În fapt, acesta conţine două ancore, către cele
două script-uri PHP: identificare.php sau inscriere.php. Vizitatorul poate
opta pentru oricare dintre ele:
130
Baze de date – curs introductiv
<html>
<title>
Autentificare
</title>
<body>
<h1>Bine ati venit pe site-ul...</h1>
<a href="http://192.168.1.217/identificare.php">
Identificare</a>
<br><br>
<a href="http://192.168.1.217/inscriere.php">Inscriere</a>
</body>
</html>
C) Dacă utilizatorul optează pentru înscriere, atunci
este rulat script-ul inscriere.php, care afişează
fereastra alăturată. Vizitatorului i se cere să introducă
numele (ID-ul) şi parola. Atunci când se introduce
parola, se afişează * pentru fiecare caracter introdus.
Pentru a evita introducerea greşită a parolei, aceasta
trebuie să fie introdusă de două ori.
După introducerea datelor, vizitatorul va apăsa butonul
“inscrie-te”. Efectul va fi acela de trimitere a datelor
către server şi de apel al script-ului inscrie.php.
<html>
<body>
<form action="inscrie.php" method ="post">
Nume<br>
<input name="nume" type="text">; <br>
Parola <br>
<input name="parola1" type="password">; <br>
Reintroduceti parola <br>
<input name="parola2" type="password">; <br>
<input type="submit", value="inscrie-te!">
</form>
</body>
</html>
C1) Script-ul inscrie.php validează datele şi, în caz că acestea sunt valide, le
înscrie în tabelul parole:
-
se testează dacă numele este nevid;
dacă cele două parole coincid;
dacă nu mai există un vizitator cu aceeaşi parolă (parola este cheie primară).
În cazul în care una dintre aceste condiţii nu este îndeplinită, se afişează un mesaj
de eroare corespunzător şi se reafişează formularul de introducere a datelor.
Capitolul 3. Limbajul PHP
<?php
// conectare la mysql
$msql=mysql_connect("localhost:3388","root","parola");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit; }
// declarare baza folosita
$baza=mysql_select_db("inscrisi");
//Citirea numelui - trebuie sa fie nevid
$nume= $_POST['nume'];
if (strcmp($nume,"")==0)
{echo "Nu ati scris numele";
require_once("inscriere.php");
exit;
}
// citirea parolelor - trebuie sa fie identice
$parola1= $_POST['parola1'];
$parola2= $_POST['parola2'];
if (strcmp($parola1,$parola2)!=0)
{echo "parola incorecta";
require_once("inscriere.php");
exit;}
// se incearca inscrierea in tabel
$cerere="INSERT INTO parole (nume,parola)
VALUES('$nume','$parola1')";
$rezultat=mysql_query($cerere);
if (!$rezultat)
{ echo "Nume existent in baza de date";
require_once("inscriere.php");
}
else echo "OK! Ati fost introdus in baza noastra de date";
?>
D) În cazul în care vizitatorul este deja înscris, va
apela script-ul identificare.php prin intermediul
ancorei respective. Acesta va cere numele şi parola,
iar la apăsarea butonului “Conecteaza-ma” va
trimite datele către server. Acestea sunt preluate de
script-ul “verif.php”.
<html>
<body>
<form action="verif.php" method ="post">
Nume<br>
<input name="nume" type="text">; <br>
Parola <br>
<input name="parola" type="password">; <br>
<input type="submit", value="Conecteaza-ma">
</form>
</body>
</html>
131
132
Baze de date – curs introductiv
D1) Se testează dacă în tabelul parole există înregistrarea cu ID-ul şi parola
introdusă de utilizator. În caz că există, se rulează, de exemplu, un script php, în
acest caz, rezultat.php, altfel se cere ca datele să fie reintroduse:
<?php
// conectare la mysql
$msql=mysql_connect("localhost:3388","root","parola");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit; }
// declarare baza folosita
$baza=mysql_select_db("inscrisi");
// citirea numelui si parolei
$nume= $_POST['nume'];
$parola= $_POST['parola'];
// selectez, daca exista in tabel, randul corespunzator
$cerere="SELECT nume FROM parole
WHERE nume='$nume' AND parola='$parola'";
$rezultat=mysql_query($cerere);
$rand=mysql_fetch_array($rezultat);
//echo $rand['nume'];
if ($rand["nume"]!=$nume)
{echo "Numele si/sau parola sunt eronate";
require_once("identificare.php");
}
else require_once("rezultat.php"); ;
?>
Fişierul rezultat.php este:
<html>
<body>
<h1> pagina ce ar trebui afisata...
</body>
</html>
3.14.2. Determinarea adresei IP şi a browser-ului utilizatorului
Uneori se doreşte obţinerea unor informaţii despre vizitatorii unui site. Astfel,
se poate afla adresa IP a vizitatorului, browser-ul utilizat de acesta sau sistemul de
operare pe care acesta îl utilizează. Toate acestea pot fi stocate în baze de date.
Informaţiile astfel dobândite sunt extrem de importante pentru aplicaţii precum:
-
Aplicaţii prin care vizitatorii votează răspunsul la o anumită întrebare. Pentru
a evita ca un vizitator să voteze de mai multe ori într-o zi, într-un tabel se va
memora adresa IP a acestuia. De la o anumită adresă IP se poate vota o
singură dată sau o singură dată pe zi, caz în care se va reţine şi ziua votării.
Capitolul 3. Limbajul PHP
133
-
Aplicaţii prin care se contorizează vizitatorii unui site. Dacă o persoană
vizitează site-ul într-o zi de mai multe ori, dar cu aceeaşi adresă IP, aceasta
este numărată ca vizitator o singură dată.
-
Determinarea browser-ului are şi ea mai multe utilizări. Se ştie că, din
păcate, diferite browser-e afişează uneori diferit acelaşi fişier download-at de
pe server. Pentru a nu mai avea astfel de probleme, dacă se cunoaşte
browser-ul utilizatorului, atunci server-ul expediază către calculatorul
vizitatorului fişierul corespunzător.
-
Informaţii precum cele de mai sus pot fi folosite de site-urile care
monitorizează vizitele la diferite alte site-uri şi întocmesc clasamentul
acestora în funcţie de numărul de vizitatori.
În acest paragraf vom învăţa să determinăm adresa IP şi browser-ul vizitatorului.
$_SERVER este o variabilă predefinită de tip masiv asociativ. Cu ajutorul ei,
script-ul PHP poate accesa o mulţime de informaţii. Pentru a afla adresa IP a
vizitatorului se utilizează $_SERVER["REMOTE_ADDR"] şi pentru a afla informaţii
despre browser se utilizează $_SERVER["HTTP_USER_AGENT"].
Exemplul 3.71. Mai multe informaţii puteţi obţine analizând script-ul următor care
afişează browser-ul utilizatorului şi adresa IP a acestuia (vezi figura de mai jos):
Rezultatele script-ului propus ca exemplu
1. Creaţi un contor pentru un site care să numere vizitatorii site-ului respectiv.
Un vizitator cu o anumită adresă IP se numără o singură dată într-o zi, indiferent
de numărul de vizite ale site-ului pe care acesta le efectuează.
134
Baze de date – curs introductiv
2. Creaţi un site care afişează o anumită întrebare, la care vizitatorii sunt invitaţi să
răspundă alegând o opţiune dintre mai multe, afişate cu ajutorul unor butoane
radio. Un vizitator cu o anumită adresă IP poate vota o singură dată într-o zi.
În situaţia în care acesta încearcă să voteze de mai multe ori, se va afişa un mesaj
prin care acesta este anunţat că a votat deja.
Observaţie ! În ambele cazuri veţi crea o bază de date cu un singur tabel, care
reţine adresa IP a vizitatorului şi (eventual) data efectuării vizitei respective.
3.14.3. Cum se creează un forum?
De câte ori n-am văzut sau am scris în diverse forum-uri... Unele sunt pe
marginea unor articole din ziare, altele au scopuri precise, cu discuţii pe anumite
teme (limbaje de programare, politică, literatură, etc.).
În cele ce urmează ne propunem să creăm un forum mult simplificat, în care
cei care doresc scriu mesaje, iar toţi ceilalţi le citesc. De ce avem nevoie pentru a
realiza un astfel de forum?
A) În primul rând, este necesară o bază de date, s-o numim forum şi un tabel, să-l
numim mesaje. Un rând al tabelului va conţine un mesaj. În acest sens, va exista
un număr de ordine pentru mesajul respectiv (nr), id-ul celui care a scris mesajul
(id), titlul mesajului (titlu) şi textul propriu-zis al acestuia (textul). Script-ul următor,
să-l numim f1.php, creează baza de date şi tabelul. Iniţial, tabelul este vid.
<?php
// conectarea la MySQL
$msql=mysql_connect("localhost:3388","root","parola");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL..."; exit; }
// crearea bazei de date numita baza
$rezultat=mysql_query("CREATE DATABASE forum");
if (!$rezultat)
{ echo "Nu s-a reusit crearea bazei de date...";
exit;
}
$baza=mysql_select_db("forum");
$interogare="CREATE TABLE mesaje(nr INT UNIQUE KEY
AUTO_INCREMENT, id CHAR(20), titlu CHAR(100),
textul LONGTEXT)";
$rezultat=mysql_query($interogare);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>
Capitolul 3. Limbajul PHP
135
B) Acum este necesar un script prin care utilizatorul scrie un mesaj:
Practic, acesta trebuie să introducă mesajul, adică informaţiile cerute de tabel şi la
apăsarea butonului “Adauga mesajul” să fie trimis către server.
<html>
<head></head>
<body>
<form action="insereaza.php"
method ="post"> ID <br>
<input name="id"
type="text">
<br> Titlu <br>
<input name="titlu"
type="text">
<br><br> Mesajul dvs. <br>
<textarea name="mesajul"
rows="10" cols="30"></textarea>
<br>
<input type="submit", value="Adauga mesajul">
</form>
</body>
</html>
136
Baze de date – curs introductiv
C) Pe server, informaţiile transmise de către cel care a scris mesajul sunt preluate
de către script-ul insereaza.php. Practic, se verifică dacă fiecare câmp în parte
este nevid, după care mesajul este memorat în tabel:
<?php
// conectarea la MySQL
$msql=mysql_connect("localhost:3388","root","parola23");
if(!$msql) echo "Nu s-a realizat conectarea la MySQL ";
// conectarea la baza de date
$baza=mysql_select_db("Forum");
if (!$baza) echo mysql_errno().":".mysql_error();
$id= $_POST['id'];
if (strcmp($id,"")==0)
{ echo "Nu ati introdus ID-ul";
require_once("f2.php"); exit; }
$titlu= $_POST['titlu'];
if (strcmp($titlu,"")==0)
{ echo "Nu ati scris titlul";
require_once("f2.php"); exit; }
$mesajul= $_POST['mesajul'];
if (strcmp($mesajul,"")==0)
{ echo "Nu ati scris mesajul";
require_once("f2.php"); exit; }
$cerere="INSERT INTO mesaje (id,titlu,textul)
VALUES('$id','$titlu','$mesajul')";
$rezultat=mysql_query($cerere);
if (!$rezultat) echo mysql_errno().":".mysql_error();
?>
D) O persoană care doreşte să vizualizeze mesajele scrise de alţii, va apela
script-ul următor, f3.php. Practic, acesta afişează tabelul mesajelor. După cum
observaţi, pentru un mesaj, nu este afişat textul propriu-zis:
Pentru a-l vizualiza pe acesta, va trebui să se execute clic pe titlul mesajului. De aici
rezultă că titlul va trebui afişat ca un link. Aici intervine ceva interesant. Atunci când
se execută clic, se va apela un alt script, f4.php, care va afişa mesajul cerut.
Problema este că va trebui să fie cunoscut numărul curent al mesajului respectiv.
Prin urmare, este necesar un link care să transmită şi un parametru. Este necesar
un apel de forma: f4.php?nr_mesaj. De exemplu, dacă numărul mesajului este
3, vom scrie: f4.php?3. În rest, script-ul f3 afişează datele într-un tabel, aşa cum
suntem deja obişnuiţi.
<?php
$msql=mysql_connect("localhost:3388","root","parola");
Capitolul 3. Limbajul PHP
137
if(!$msql)
{echo "Nu s-a realizat conectarea la MySQL "; exit; }
//conectarea la baza de date
$baza=mysql_select_db("forum");
if (!$baza)
{echo mysql_errno().":".mysql_error(); exit;}
$cerere="SELECT * FROM mesaje";
// in urma interogarii, se returneaza tabelul
$rezultat=mysql_query($cerere);
if (!$rezultat)
{ echo mysql_errno().":".mysql_error(); exit; }
echo "<table border=5>";
// afisam capul de tabel
echo "<tr> <td align='left'><b>nr.curent</b>
<td align='center'><b>ID</b><td><b>Titlu mesaj</b>";
while($rand=mysql_fetch_array($rezultat))
{ echo "<tr>";
echo "<td align='right'>".$rand["nr"].
"<td>".$rand["id"]."<td>"."<a
href=http://localhost/f4.php?".$rand["nr"].
">".$rand["titlu"]."</a>";
echo "</tr>";
}
echo "</table>";
?>
E) Script-ul de mai jos, f4.php, apelat de f3.php, primeşte ca parametru de
intrare numărul mesajului. Practic, apelează MySQL-ul, deschide baza de date şi
afişează corpul mesajului (textul propriu-zis al acestuia), indentificându-l cu ajutorul
unei interogări:
<?php
$nr= $_SERVER["QUERY_STRING"];
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{echo "Nu s-a realizat conectarea la MySQL"; exit;}
// conectarea la baza de date
$baza=mysql_select_db("forum");
if (!$baza) {echo mysql_errno().":".mysql_error(); exit;}
$cerere="SELECT textul FROM mesaje WHERE nr=$nr";
// in urma interogarii, se returneaza tabelul
$rezultat=mysql_query($cerere);
$rand=mysql_fetch_array($rezultat); echo $rand["textul"];
?>
138
Baze de date – curs introductiv
1. Adăugaţi script-ului f3.php o secvenţă în urma căreia, la apăsarea unui buton,
să se poată introduce un mesaj (practic, să fie apelat script-ul f2.php).
2. Reproiectaţi aplicaţia astfel încât să existe posibilitatea unui răspuns la un
mesaj.
3. Dezvoltați aplicația astfel încât să arate ca un mic forum pe un subiect ales la
alegere. Permiteți doar utilizatorilor autentificați să poată posta un subiect nou.
3.15. Proiectarea paginilor web
În acest moment, puteţi spune că aveţi cunoştinţe solide astfel încât să puteţi
dezvolta o aplicaţie hipermedia. Definirea modelului conceptual vă ajută la etapa
de proiectare a unei baze de date, normalizarea acesteia asigură robusteţe şi
siguranţă, iar prin intermediul limbajului MySQL o puteţi implementa. Limbajele
HTML şi CSS oferă nenumărate posibilităţi de realizare a interfeţei cu utilizatorul
final, iar PHP-ul, accesul la baza de date stocată pe server.
Observaţie ! Recitiţi Capitolul 1 pentru a vă reaminti noţiunile fundamentale care
privesc proiectarea bazelor de date!
O planificare riguroasă a proiectului este imperativă şi de cele mai multe ori,
ducerea la bun sfârşit a acestuia necesită o întreagă echipă care să lucreze
coordonat. Astfel, în cazul în care nu realizaţi proiectul singur, trebuie să formaţi o
echipă care să-şi distribuie sarcinile cât mai eficient, în funcţie de aptitudini. Puteţi
revedea subcapitolul 1.4. care descrie managementul de proiect.
Nimeni nu “pleacă la drum” fără un plan bine pus la punct. De aceea, înainte
de toate, trebuie să fixaţi clar toate etapele pe care trebuie să le parcurgeţi.
1. Trebuie să ştiţi cui i se adresează site-ul pe care doriţi să-l dezvoltaţi şi
bineînţeles, discutaţi cu beneficiarul acestuia pentru a obţine toate
informaţiile de care aveţi nevoie. În funcţie de datele pe care acesta
doreşte să le cunoască despre vizitatorii site-ului sau pe cele care vrea să
le reţină în urma interacţiunii cu aceştia, puteţi realiza modelul conceptual
al bazei de date.
2. Analizaţi cu atenţie modelul conceptual, iar dacă este cazul, utilizaţi
tehnica de normalizare a datelor pentru a preveni eventualele anomalii.
3. Utilizând modelul relaţional al bazelor de date, implementaţi modelul conceptual, iar cu ajutorul limbajului MySQL, creaţi baza de date!
4. Interfaţa grafică cu utilizatorul trebuie să fie bine structurată, simplu de
utilizat, iar datele de intrare şi cele de ieşire trebuie alese corespunzător.
Capitolul 3. Limbajul PHP
139
Nu uitaţi ! Realizarea interfeţei grafice reprezintă o etapă esenţială pentru
că paginile web sunt unicul loc unde utilizatorul interacţionează în mod
direct cu aplicaţia dvs. Upload-aţi pe server fişierele html astfel formate şi
testaţi-le cu atenţie!
5. Realizaţi formularele care asigură colectarea şi trimiterea datelor către
server. Multe aplicaţii hipermedia conţin formulare care au câmpuri
opţionale, permiţând colectarea unor informaţii suplimentare despre
utilizatori.
6. Creaţi script-urile PHP care să prelucreze datele introduse de utilizator şi
care să răspundă comenzilor recepţionate.
7. La final, testaţi aplicaţia pentru a elimina anumite erori care pot apărea!
Observații

De multe ori, codurile sursă pot avea sute de linii de cod, la care trebuie să
adăugaţi comentarii sugestive pentru a putea vizualiza rapid secţiuni din
cadrul acestora.

Corectitudinea datelor introduse de către utilizatori trebuie să fie asigurată
prin “mesajele ajutătoare” sau de eroare care trebuie să se regăsească în
cadrul paginilor web – se evită astfel introducerea unor informaţii eronate în
baza de date.

Cu ajutorul variabilelor cookie, puteţi oferi posibilitatea personalizării site-ului,
în funcţie de preferinţele utilizatorului (de exemplu: diverse teme – care au la
bază câte un stil – vezi CSS; afişarea informaţiilor de interes – listă cu
diverse categorii, etc.).

Nicio aplicaţie nu poate fi considerată în totalitate terminată, ea fiind
deschisă la eventuale îmbunătăţiri. De asemenea, pentru a fi asigurat
succesul site-ului web, actualizaţi frecvent informaţiile pentru a ţine la curent
vizitatorii fideli!
Important! Pentru ca posesorul site-ului să poată vizualiza informaţiile reţinute în
baza de date, realizaţi o interfaţă (o pagină web) specială, stabilind de comun
acord care date trebuie să fie afişate în respectivele rapoarte, grafice, etc.
140
Baze de date – curs introductiv
1. Care dintre afirmaţiile de mai jos sunt adevărate şi care sunt false?
a)
b)
c)
d)
Un script PHP este executat de către browser.
PHP-ul se instalează pe server.
Un fişier HTML poate conţine un script PHP.
Formularele se descriu în HTML.
2. “Variantă simplificată de test online”. Reluaţi problema 1. Veţi crea o pagină
HTML care afişează problema şi oferă vizitatorului ca, acolo unde consideră că
răspunsul este adevărat, să bifeze un buton de marcare. Datele se trimit către server.
Pe server, răspunde un script PHP care, acolo unde vizitatorul a răspuns corect,
afişează OK, iar unde nu a răspuns corect, afişează răspunsul corect şi o explicaţie.
3. Dintre afirmaţiile de mai jos, una singură este falsă. Care este?
a)
b)
c)
d)
Funcţiile PHP admit parametri transferaţi prin referinţă.
Funcţiile apelate de un script PHP trebuie să fie conţinute de acesta.
Funcţiile PHP admit parametri transferaţi prin valoare.
În PHP nu este necesar să declarăm tipul unei variabile.
4. Cum se testează online problema 3 (vedeţi problema 2)?
5. ”Validarea datelor”. Scrieţi un fişier HTML care conţine un formular prin
intermediul căruia se pot trimite către server numele vizitatorului şi vârsta sa. Pe
server, se va găsi un script care testează dacă numele este alfabetic şi dacă vârsta
este între 5 şi 90 de ani. Dacă aceste condiţii sunt îndeplinite, browser-ul va afişa
OK, altfel se vor afişa mesaje de eroare corespunzătoare.
6. ”Semnalarea erorilor găsite la validare”. Se cere să se scrie un formular prin
care vizitatorul trimite către server un număr întreg din intervalul [1,10] şi un
script PHP care verifică valoarea introdusă. În cazul în care valoarea introdusă este
corectă, se va afişa OK, altfel se va da un mesaj de eroare, după care se va afişa
din nou formularul (vezi figurile de mai jos).
a) Formular iniţial
b) Mesaj de eroare
Capitolul 3. Limbajul PHP
141
7. ”Verificare parolă”. Se cere să se scrie un formular prin care i se cere
vizitatorului să introducă o parolă. Pe server răspunde un script PHP care verifică
parola. În caz de coincidenţă, se va afişa o pagină HTML, la alegerea dvs., iar altfel
se va afişa un mesaj de eroare.
8. ”Imagini la alegere”. Să se creeze un formular care conţine o listă. Vizitatorul
selectează, după nume, o anumită fotografie şi trimite selecţia sa către server.
Acolo, un script PHP afişează imaginea, dar şi lista, pentru ca vizitatorul să poată
selecta o altă imagine.
9. ”Afişarea unui tabel atunci când nu se cunosc de la început datele”. Să se
creeze un formular care trimite 4 valori către server. Acolo se va găsi un script care
afişează cele 4 valori sub forma unui tabel. Vedeţi mai jos.
a) Formular iniţial
b) Tabelul obţinut
Figura 5.34. Pagini propuse pentru problema 9
(pentru verificare, rezolvările se găsesc la pag. 383)
142
Baze de date – curs introductiv
Formaţi echipe de 2 - 4 elevi, alegeţi-vă o temă de proiect, fie din temele
propuse în această secţiune, fie una propusă chiar de voi.
Atenţie! Repartizaţi sarcinile în mod echitabil în cadrul echipei de proiect.
Puteţi chiar organiza împreună cu cadrul didactic, un concurs la nivelul clasei
sau al şcolii, la care să invitaţi şi alţi profesori din şcoală.
Nu uitaţi să documentaţi fiecare presupunere pe care aţi făcut-o în realizarea
proiectului!
1. “Şeful clasei”. Este de preferat ca orice clasă să aibă ales un elev care să se
ocupe de problemele “administrative”. Dacă aveţi sau nu unul, este momentul unui
nou scrutin! Nominalizaţi-vă un număr de 4-5 elevi care să candideze pentru acest
titlu şi realizaţi o aplicaţie hipermedia care să permită sistemul “votului electronic”.
Bineînţeles, problema poate fi extinsă: fiecare candidat să aibă o pagină
separată, unde să poată să-şi facă o “campanie electorală“ cât mai interesantă,
rezultatele parţiale sau finale să poată fi vizualizate on-line, etc.
Mult succes!
2. “Forum”. Fie că este vorba de maşini sau calculatoare, probleme personale sau
profesionale, tuturor ne place să “discutăm” pe Internet! Păreri sunt multe şi de
multe ori ne place să ne amuzăm sau să deschidem un nou “topic” pe forum, în
speranţa că măcar virtual să ne facem “auziţi”. Realizaţi un astfel de site web!
3. “Vânzare/Cumpărare”. Toată lumea a auzit de succesul site-ului ebay,
recunsocut la nivel mondial în lumea comerţului electronic. Chiar dacă nu atât de
complex, realizaţi şi voi un site care să permită:

posibilitatea creării unui cont care să identifice unic fiecare vizitator;

introducerea anunţurilor de tip vânzare/cumpărare;

vizualizarea produselor existente în funcţie de categorie, preţ, etc.;

afişarea unor rapoarte care să evidenţieze cele mai vândute produse,
preferinţele obiectelor cumpărate în funcţie de vârstă, etc.;

trimiterea unor mesaje între utilizatori – simularea unei căsuţe poştale.
ANEXA 1
Instalarea mediului de dezvoltare EasyPHP
Pentru a putea lucra cu MySQL și php, avem nevoie de un server de test.
Cu ajutorul pachetului EasyPHP putem realiza toate acestea ușor pe calculatorul
nostru, având apoi posibilitatea de a le studia chiar dacă nu avem acces la
Internet. În ipoteza în care am învăţat să le folosim şi dorim să construim un site
web, atunci vom închiria spaţiu pe server şi acolo vom transfera script-urile
realizate pe propriul calculator.
EasyPHP este open-source, deci gratuit, iar pachetul conține cam tot ce ne
trebuie pentru moment a.î. să creăm propriul nostru webhosting server, adică
Apache, MySQL, php, Nginx, Dev Tools.
Adresa de unde poate fi descărcat este:
https://www.easyphp.org/
În cazul nostru, vom alege opțiunea Webserver, versiunea 14.1 (sistemul de
operare al autorului este Windows 8.1 Pro):
144
Baze de date – curs introductiv
Efectuâm clic pe buton și se va deschide o nouă fereastră de unde se descarcă un
executabil care, apelat, va instala programele din pachet (alegeţi opţiunile
implicite). Executabilul downloadat de noi este ”EasyPHP-Webserver-14.1b2setup.exe”:
Urmăm pașii la instalare cu atenție, alegând opțiunile potrivite pentru noi:
Observăm faptul că avem nevoie de cel puțin 256.7MB spațiu pe disc, apoi
programul se va instala în folderul menționat în mod automat de program.
Nu modificăm nimic și apăsăm butonul Next.
Anexa 1. Instalarea EasyPHP
145
Fereastra următoare ne indică numele programului accesibil din Start Menu, iarăși
ales implicit și apăsăm din nou Next:
Pe pagina următoare nu avem decât să alegem opțiunea Install:
146
Baze de date – curs introductiv
Dacă totul a fost efectuat cu succes, va apărea mesajul următor:
Suntem întrebați prin acel checkbox dacă dorim să lansăm în executare imediat
serverul EasyPHP. În cazul meu sunt de acord și apăs butonul Finish.
...
Aparent, nu s-a întâmplat nimic, însă putem observa faptul că pe bara de jos a
sistemului de operare Windows, în dreapta, a apărut o nouă pictogramă ce ne
indică faptul că programul nostru este deja funcțional:
Efectuăm clic dreapta din curiozitate și apare următorul meniu:
Alegem apoi prima opțiune, adică Open Dashboard.
Anexa 1. Instalarea EasyPHP
147
Prima oară când apelăm această comandă va deschide o fereastră nouă a
browser-ului nostru curent la adresa
http://127.0.0.1:10000/
și ne va întreba dacă suntem de acord cu termenii și condițiile de utilizare pe care
trebuie să le acceptăm apăsând butonul Agree:
Se va afișa următoarea pagină web:
148
Baze de date – curs introductiv
Observ niște informații despre noul nostru server, apoi citesc faptul că pentru a
instala anumite Module, trebuie mai întâi să pornesc serverul HTTP:
Am apăsat acest buton ce mă duce la zona de setări de unde instalez serverul
HTTP Apache, apoi îl activez:
Mai sus el este deja pornit.Super!
Adresa la care vom accesa paginile noastre web de acum înainte este, în cazul
meu, cea locală (URL) și anume: http://192.168.1.217:888/.
Dacă o deschidem în browser, vom observa faptul că nu există implicit un fișier
index, ci doar unul de test numit hello.php:
Anexa 1. Instalarea EasyPHP
149
Precum putem citi din pagina de administrare, folderul care conține acest prim
fișier este următorul:
C:\Program Files\EasyPHP-Webserver-14.1b2\www
mai exact, rădăcina website-ului (root) nostru local. În cadrul acestui director va
trebui să reținem pe disc fișiere noastre care vor forma proiectul nostru web
(imagini, fisiere html și php, etc.).
ALTE CONFIGURĂRI
Nu am terminat încă... În pagina de configurare observăm că există mai multe
secțiuni, cum ar fi System, PHP, DB SERVER. Accesăm System și se va
deschide următoarea pagină:
Pentru a putea să avem acest server repornit automat atunci când deschidem
calculatorul, trebuie să instalăm Serviciul Windows care se ocupă de acest lucru,
așadar vom alege opțiunea install service.
Dacă totul a fost efectuat cu succes, veți fi anunțat în acest sens.
150
Baze de date – curs introductiv
Alegând apoi secțiunea DB SERVER, vom instala similar și serverul pentru bazele
de date:
Apoi, apăsați butonul start service.
PHPMYADMIN
În zona de administrare (Dashboard) care se găsește la adresa
http://127.0.0.1:10000/
avem instalat inițial un singur modul și anume PhpMyAdmin care ne permite să
vizualizăm bazele noastre de date. Pentru a deschide fereastra modulului, apăsați
butonul Open:
Anexa 1. Instalarea EasyPHP
151
Vom fi rugați să introducem username-ul (root) și parola de acces (nu o are setată)
și se va deschide apoi fereastra principală:
Evident, nu există nicio bază de date la început...
Apăsați comanda Modifică parola pentru a introduce una nouă astfel încât
accesul să fie restricționat:
După ce ați ales una potrivită și complexă, apăsați butonul Execută.
De acum accesul la phpMyAdmin va fi posibil doar cu ajutorul autentificării.
152
Baze de date – curs introductiv
CONCLUZII
Am reușit ușor să instalăm pe calculator EasyPHP. Bineînțeles că există o
sumedenie de alte opțiuni care pot fi impuse unui server, care conduc spre
o adevărată meserie, bazată pe multă experiență, noțiuni ce nu privesc direct
documentul prezent. Spre exemplu, nu am rezolvat problema https vs. http sau
instalarea unui modul precum cPanel, ș.a.m.d.
Informatica necesită mult studiu individual, precum căutarea optimă a
informației pe Internet folosind cuvinte cheie potrivite, analizând soluțiile oferite de
alte persoane, ca și tine. De multe ori postezi o întrebare care are un răspuns rapid
la doar un clic distanță. Spre exemplu, pentru a putea activa SSL trebuie să
accesezi fișierul php.ini și să elimini “ ; ” din fața liniei de cod:
;extension=php_openssl.dll
Trebuie doar să ștergi caracterul punct și virgulă pentru ca extensia să nu mai fie
comentată din cod. Unde se găsește acest fișier? Păi, îl cauți unde a fost instalat
programul EasyPHP, nu?
În practică, noi reținem adesea datele pe un server extern, apelând la serviciile de
găzduire dedicate promovate de diverse companii, unde vom avea acces facil la
cPanel, phpMyAdmin, precum și alte unelte utile – transfer FTP, File Manager,
alegerea versiunii limbajului php, diverse statistici și ... multe, multe altele.
Mai exact, un Univers și – o meserie.
Pentru moment, avem acces la serverul nostru folosind adresa:
http://192.168.1.217:888/.
Dacă dorim să modificăm portul 888 a.î. să nu mai fie necesară specificarea
acestuia (portul 80), va trebui să modificâm o line de cod din fișierul httpd.conf
care în cazul nostru se găsește în folderul:
C:\Program Files\EasyPHP-Webserver-14.1b2\binaries\httpserver\conf
Căutați linia de cod care conține
ServerName 192.168.1.217:888/
și înlocuiți cu
ServerName 192.168.1.217:80/
Va fi necesară oprirea și repornirea serverului HTTP din panoul de administrare
(Dashboard) de la adresa:
Anexa 1. Instalarea EasyPHP
http://127.0.0.1:10000/
Oprim apoi repornim:
De acum avem noile valori potrivite pentru IP-urile de acces:
153
Indicaţii / Răspunsuri
Capitolul 1. Baze de date
1.1.
Barem de corectare şi notare pentru testul 1:
Răspunsurile corecte sunt: 1-b, 2-c, 3-b, 4-d, 5-b, 6-c
6 x 1.5 =
Oficiu
1p
Total
10 p
9p
Barem de notare pentru testul 2:
1. 3 x 0,2 = 0,6 p
2. 8 relaţii x 0,30 p = 2,4 p (0,15 puncte pentru cardinalitatea relaţiei şi 0,15
puncte pentru opţionalitate)
3. 2 x 2 p = 4 p (pentru fiecare relaţie se acordă 4x0,15p=0,60 p; pentru
opţionalitatea relaţiilor, 4x0,15p=0.60 p pentru cardinalitatea relaţiilor, 0,3 p
pentru alegerea entităţii de intersecţie, 0,3 p pentru atributele entităţii de
intersecţie, 0,2 p pentru UID).
4. 2 x 0.5 = 1 p
Oficiu
2p
Total
10 p
1.3.
Barem de corectare şi notare pentru testul de autoevaluare:
Răspunsurile corecte sunt:
1-c, 2-b, 3-b, 4-a.
Răspunsul corect pentru punctul 5
este prezentat în figura alăturată:
Se acordă:
1.5 p x 4 (pentru întrebările 1, 2, 3, 4)
2 p (pentru întrebarea 5)
Oficiu 2 p
Total 10 p
Indicaţii / Rezolvări
155
Capitolul 2. MySQL
Rezolvările problemelor propuse:
1.
1.1.
SELECT nume_m FROM materiale
WHERE depozit=’Depozit 2’;
1.2.
SELECT depozit FROM materiale
WHERE nume_m LIKE ‘%Material 3%’;
1.3.
SELECT SUM(cantitate*pret_u)
AS valoare_totsla_materiale
FROM materiale;
1.4.
SELECT depozit,
SUM(cantitate*pret_u)
AS valoare_totala FROM
materiale GROUP BY depozit;
1.5.
UPDATE materiale
SET pret_u=1.1 pret_u
WHERE nume_m=’material 1’;
1.6.
DELETE from materiale
WHERE nume_m=’material 3’;
2.
2.1.
SELECT nume FROM imprumuturi
WHERE nume LIKE ‘%Banca 1%’;
2.2.
SELECT banca, SUM(suma) AS suma_imprumutata FROM imprumuturi
GROUP BY banca;
2.3.
SELECT nume, COUNT(suma) AS nr_imprumuturi FROM imprumuturi
GROUP BY nume;
2.4. Pentru simplitate, descompunem problema în mai multe subprobleme. Ideea
este de a crea un tabel de manevră, să-l numim ”pers”, care să reţină pentru
fiecare persoană totalul sumei pe care a împrumutat-o.
a) Creăm tabelul de manevră ”pers”:
156
Baze de date – curs introductiv
CREATE TABLE pers AS
SELECT nume, SUM(suma) AS suma_imprumutata
FROM imprumuturi GROUP BY nume;
b) Selectăm răspunsul la problemă, pornind de la tabelul ”pers”:
SELECT nume, suma_imprumutata AS suma_maxima FROM pers
WHERE suma_imprumutata=(SELECT MAX(suma_imprumutata)
pers);
FROM
c) Întrucât nu mai este necesar, tabelul de manevră pers este şters.
DROP TABLE pers;
2.5.
a) Rezolvare cu subinterogare:
SELECT DISTINCT nume FROM imprumuturi
WHERE banca IN
(SELECT banca FROM imprumuturi WHERE nume=’Ionescu Grigore’);
b) Rezolvare utilizând mecanismul auto-uniunii:
SELECT DISTINCT B.nume
FROM imprumuturi AS A INNER JOIN imprumuturi AS B
ON A.banca=B.banca AND A.nume=’Ionescu Grigore’;
3.
3.1.
SELECT nume,
COUNT(tip_p) AS nr_proprietati
FROM proprietari, proprietati
WHERE cod=cod_proprietar
GROUP BY cod_proprietar;
3.2
SELECT nume FROM proprietari
WHERE cod NOT IN
(SELECT cod_proprietar FROM proprietati)
3.3.
SELECT cod_proprietar FROM proprietati
WHERE cod_proprietar NOT IN
(SELECT cod FROM proprietari);
3.4.
SELECT nume, SUM(valoare) AS valoare_proprietati
FROM proprietari, proprietati
WHERE cod=cod_proprietar
GROUP BY cod_proprietar
ORDER BY valoare_proprietati DESC;
Indicaţii / Rezolvări
4
4.1.
SELECT B.nume FROM
baieti AS A, fete AS B, prieteni AS L
WHERE
A.nume=”mihai’ AND
A.varsta=18 AND
A.cod=L.cod_b AND
L.cod_f=B.cod;
4.2.
SELECT nume FROM fete
WHERE
cod NOT IN (SELECT cod_f FROM prieteni);
4.3.
SELECT nume,
COUNT(cod_f) AS nr_prietene
FROM baieti, prieteni
WHERE cod=cod_b
GROUP BY cod_b;
4.4.
SELECT nume, COUNT(cod_b) AS nr_prieteni
FROM fete,prieteni
WHERE cod=cod_f
GROUP BY cod_f
ORDER BY nr_prieteni DESC
LIMIT 1;
4.5.
SELECT AVG(A.varsta) AS medie_varsta_baieti,
AVG (B.varsta) AS medie_varsta_fete
FROM baieti AS A, fete AS B;
Capitolul 3. PHP
Rezolvările problemelor propuse:
1. a) F, b) A, c) A, d) A. 3.b).
6. Fişierul PHP care afişează formularul este:
<html><head></head>
<body>
<form action="http://localhost:3388/testare.php"
method="post">
Introduceti valoarea <br>
<input type="text" name="valoarea"><br>
<input type="submit" value="GO">
</form></body></html>
157
158
Baze de date – curs introductiv
Script-ul este dat mai jos. Observaţi utilizarea lui require_once() care include în
corpul script-ului fişierul care conţine formularul:
<?
$v=$_POST["valoarea"];
if ($v>=1 && $v<=10 )
echo "OK";
else
{echo "Data introdusa este eronata";
require_once( "test_er.php");}
?>
9.
<form action="http://localhost:3388/testare.php"
method="post">
a11<input type="text" name="a11"><br>
a12<input type="text" name="a12"><br>
a21<input type="text" name="a21"><br>
a22<input type="text" name="a22"><br>
<input type="submit" value="GO">
</form>
<?
$a11=$_POST["a11"]; $a12=$_POST["a12"];
$a21=$_POST["a21"]; $a22=$_POST["a22"];
echo "<table border=5>";
echo " <tr> <td> $a11 </td><td> $a12 </td></tr>";
echo " <tr> <td> $a21 </td><td> $a22 </td></tr>";
echo "</table>";
?>
Indicaţii / Rezolvări
159
160
Baze de date – curs introductiv
Copyright 2022  Editura L&S SOFT
Toate drepturile asupra acestei lucrǎri aparţin editurii L&S SOFT.
Reproducerea integralǎ sau parţialǎ a textului din aceastǎ carte este
posibilǎ doar cu acordul în scris al editurii L&S SOFT.
ISBN: 978-606-95233-4-6
https://ebooks.infobits.ro
Download