Documente Academic
Documente Profesional
Documente Cultură
Mysql 050 p-2
Mysql 050 p-2
1999-10-01
T/P
CC
T JL
Figura 1.5 Tabelele puncte i eveniment, legate prin dat.
Este mult mai bine dect s ncercai a deduce tipul punctajului pe ghicite"; n schir obinem tipul direct din
datele nregistrate n mod explicit n baza noastr de date. asemenea, este o opiune de preferat fa de
nregistrarea tipurilor de punctaje n tabe puncte, deoarece trebuie s nregistrm fiecare tip o singur dat.
Totui, dac suntei ca mine, cnd auzii pentru prima dat de acest lucru (combir informaiilor din mai multe
tabele), v gndii: Mda, bun idee, dar e mult munc faci mereu toate cutrile alea; nu complicm lucrurile?"
ntr-un fel, avei dreptate. Folosirea a dou liste cu nregistrri este mai complicat i folosirea unei singure liste.
Dar s mai privim o dat la catalog (vezi figura l .2). Nu aii deja dou seturi de nregistrri? inei cont de
urmtoarele aspecte:
Pstrai evidena punctajelor folosind celulele din matricea tabelului puncte, ui fiecare celul este indexat de
numele elevului i dat (n jos pe lateral i de-a lur prii superioare a matricei). Acesta reprezint un set de
nregistrri; este analog coninutul tabelului punctaj.
Cum procedai pentru a ti tipul de eveniment pe care l reprezint fiecare dat? i scris un T sau un C mic
deasupra fiecrei date! Astfel, pstrai i evidena asocierii i dat si tipul punctajului, de-a lungul prii de sus a
matricei. Acesta reprezint doilea set de nregistrri; este analog cu coninutul tabelului eveniment.
Capitolul 1 Introducere n MySQL i SQL
53
i Cu alte cuvinte, chiar dac nu contientizai acest lucru, n realitate utilizai catalogul | ntr-un mod absolut
similar cu cel propus de mine, de pstrare a informaiilor n dou tabele. Singura diferen real este c acele
dou categorii de informaii nu sunt separate n mod att de explicit n catalog.
Pagina din catalog ilustreaz ntr-un fel modul n care noi gndim informaiile, precum i dificultatea
determinrii modului de a plasa informaiile ntr-o baz de date: noi tindem s integrm diferitele categorii de
informaii i s le interpretm ca pe un ntreg. Bazele de date procedeaz altfel, motiv pentru care par uneori
artificiale i nenaturale. Tendina noastr natural de a unifica informaiile ngreuneaz uneori pn si sesizarea
faptului ca avem mai multe tipuri de date, nu doar unul singur. Din aceast cauz, ncercarea de a gndi ca o
baz de date" n ceea ce privete modul de reprezentare a datelor poate fi o mare problem.
O cerin impus tabelului eveniment de macheta prezentat n figura 1.5 este aceea ca datele s fie unice,
deoarece data este folosit pentru a corela nregistrrile din tabelele puncte si eveniment. Cu alte cuvinte, nu
putei da dou chestionare n aceeai zi, respectiv un chestionar i un test. Dac o facei, vei avea dou seturi de
nregistrri n tabelul puncte si dou nregistrri n tabelul eveniment, toate cu aceeai dat, si nu vei mai putea
stabili o coresponden ntre nregistrrile din cele dou tabele.
Aceasta este o problem care nu va aprea niciodat dac ntr-o zi survine o singur examinare, dar putem
presupune n mod corect c acest lucru nu se va ntmpla? n aparen rspunsul este afirmativ; la urma urmelor,
nu suntei att de sadic nct s dai un chestionar i un test n aceeai zi. Dar sper c m vei ierta dac sunt
sceptic. Am auzit deseori oameni care spun despre datele lor: Acest caz ciudat nu se va ntmpla niciodat."
Apoi, se dovedete c acel caz ciudat chiar se produce cu o anumit ocazie si de regul este necesar s v re-
proiectai tabelele pentru a remedia problema pe care a cauzat-o acel caz ciudat.
Este mai bine s anticipai posibilele probleme i modul de a le rezolva. Deci, s presupunem c uneori suntei n
situaia de a nregistra dou seturi de punctaje pentru aceeai zi. Cum ne putem descurca? Aa cum se va vedea,
nu este o problem chiar att de dificil. Cu o mic modificare n modul de dispunere a datelor, apariia mai
multor evenimente la o anumit dat nu va provoca necazuri:
l- Adugai o coloan la tabelul eveniment si folosii-o pentru a-i atribui un numr unic fiecrei nregistrri din
tabel. Astfel, fiecare eveniment va avea propriul su numr de identificare, deci coloana va avea numele
eveniment_id. (Dac pare ciudat, catalogul din figura 1.2 are deja aceast proprietate: identificatorul de
eveniment este similar numrului coloanei din matricea cu punctaje din catalog. Se poate ca numrul s nu ne
scris n mod explicit i denumit identificator de eveniment", dar este chiar un identificator de evenimente.)
2. Cnd inserai punctaje n tabelul puncte, nregistrai identificatorul de eveniment n locul datei.
Rezultatul acestor modificri este prezentat n figura 1.6. Acum, coroborai tabelele puncte i eveniment folosind
identificatorul de eveniment n locul datei i utilizai tabelul eveniment pentru a determina nu numai tipul
fiecrui punctaj, dar si data la care a *ost obinut acesta. De asemenea, elementul unic din tabelul eveniment nu
mai trebuie
54
Partea l Utilizarea general a sistemului MySQL
s fie data, ci identificatorul de eveniment. Aceasta nseamn c putei avea zece teste i chestionare n aceeai
zi; putei pstra evidena lor corect n scriptele dumneavoastr. (Indiscutabil, elevii dumneavoastr vor fi extrem
de ncntai s afle acest lucru.) Din pcate, din punct de vedere al operatorului uman, macheta de tabel din
figura 1.6 pare mai puin satisfctoare dect cele anterioare. Tabelul puncte este mai abstract, deoarece conine
mai puine coloane cu o semnificaie evident. Macheta de tabel prezentat anterior n figura 1.4 era uor de
examinat si de neles, deoarece tabelul puncte avea coloane att pentru date, ct i pentru tipurile de punctaj.
Tabelul puncte actual, prezentat n figura 1.6, nu are coloane pentru nici una din aceste informaii, ceea ce pare
serios deplasat fa de normal. Cine vrea s citeasc un tabel puncte care conine identificatoare de eveniment"?
Pentru noi, aceast informaie nu are o semnificaie prea important.
Tabelul puncte
Tabelul eveniment
Nume eveniment id Puncte
Billy 5 15
Missy :5 ' 14
Johnny 556666 17 19
Jenny 67 73
Billy 82 79
Missy
Johnny
Jenny
eveniment id Data Tip
123 1999-09- C C
4 03 1999- T C
09-06
1999-09-
09 1999-
09-15
5 1999-09- C
23
6 1999-10- T
01
Figura 1.6 Tabelele puncte i eveniment, legate dup identificatorul de eveniment.
Acum ai ajuns la o rscruce. Suntei interesat de posibilitatea de a putea pstra evidena electronic a
rezultatelor colare i de a nu trebui s efectuai tot felul de calcule manuale obositoare atunci cnd atribuii
notele. Dar, dup ce v gndii la modul n care vei reprezenta informaiile despre punctaje ntr-o baz de date,
suntei descurajat de aspectul abstract i discontinuu al informaiei reprezentate n acel mod.
Natural, aceasta duce la o ntrebare: N-ar fi bine s nu folosesc deloc o baz de date? Poate c MySQL nu este
pentru mine." Aa cum putei intui, voi rspunde negativ la aceast ntrebare, deoarece altfel cartea de fa ar
ajunge rapid la final. Dar, atunci cnd v gndii cum s facei un lucru anume, este bine s avei n vedere
diferite alternative i s v ntrebai dac n-ar fi mai bine s folosii un sistem de baze de date, cum este SQL, sau
altceva, cum ar fi un program de calcul tabelar:
Catalogul are rnduri i coloane, ca i o foaie de calcul tabelar. De aceea, o foaie de calcul tabelar i un catalog
sunt foarte asemntoare att vizual, ct i conceptual.
Intr-o foaie de calcul tabelar se pot efectua calcule, deci putei nsuma punctajele fiecrui elev folosind un cmp
de calcul. Este puin mai greu s acordai o pondere diferit chestionarelor si testelor, dar nu imposibil.
Pe de alt parte, dac dorii s examinai numai o parte a datelor dumneavoastr (numai chestionarele sau numai
testele, de exemplu), s facei comparaii (ntre notele bieilor i cele ale fetelor) sau s afiai informaii de
sumar ntr-un mod flexibil, datele problemei se schimb. O foaie de calcul tabelar nu funcioneaz att de bine,
n timp ce sistemele de baze de date relaionale execut cu uurin aceste operaii.
Capitolul 1 Introducere n MySQL i SQL
55
LJn alt element care trebuie avut n vedere este aceea c natura abstract i discontinu a datelor reprezentate
ntr-o baz de date relaional nu este, la urma urmelor, o problem att de mare. Trebuie s v gndii la acea
reprezentare atunci cnd configurai baza de date, astfel nct s nu v dispunei datele ntr-un mod lipsit de sens
n raport cu felul n care dorii s le utilizai. Totui, dup ce ai determinat modul de reprezentare, vei conta pe
motorul de baze de date pentru adunarea i reprezentarea datelor dumneavoastr ntr-un mod semnificativ. Nu
vei mai privi datele ca pe o aduntur de componente fr legtur ntre ele.
De exemplu, cnd regsii punctaje din tabelul puncte, nu dorii s vedei identificatoare de eveniment; dorii s
vedei date. Aceasta nu este o problem. Baza de date va cuta datele din tabelul eveniment n funcie de
identificatorul de eveniment si vi le va prezenta. De asemenea, putei don s vedei dac punctajele au fost
obinute la chestionare sau teste. Nici aceasta nu este o problem. Baza de date va cuta tipurile de punctaje n
acelai mod: folosind identificatorul de eveniment. Nu uitai, acesta este punctul forte" al unui sistem de baze
de date relaionale ca MySQL: corelarea unui lucru cu altul pentru a extrage informaii din mai multe surse si de
a v prezenta datele pe care dorii s le vedei. In cazul datelor noastre de eviden a rezultatelor colare, MySQL
este cel care adun informaiile la un loc folosind identificatorii de eveniment, pentru ca dumneavoastr s nu
mai efectuai aceast operaie.
Acum, pentru a da o mic idee n avans" cu privire la modul n care cerei sistemului MySQL s execute aceast
corelaie ntre lucruri, s presupunem c dorii s vedei punctajele obinute la data de 23 septembrie 1999.
Interogarea pentru extragerea punctajelor aferente unui eveniment produs la o anumit dat se prezint astfel:
SELECT puncte.nume, eveniment.data, puncte.puncte, eveniment.tip
FROM puncte, eveniment
WHERE eveniment.data = "1999-09-23"
AND puncte.eveniment_id = eveniment.eveniment_id
Cam de speriat, este? Aceast interogare regsete numele elevului, data, punctajul i tipul punctajului prin
alturarea (corelarea) nregistrrilor din tabelul puncte cu nregistrrile din tabelul eveniment. Rezultatul arat
astfel:
Nume Data Puncte Tip
Billy 1999-09-2315 15 C
Missy 1999-09-2314 14 C
Johnny 1999-09-2317 17 C
Jenny 1999-09-2319 19 c
Formatul acestor informaii v sun" cunoscut? Ar fi i cazul; este acelai cu macheta tabelului prezentat n
figura 1.4! Nu trebuie s cunoatei identificatorul de eveniment pentru a obine acest rezultat. Specificai data
care v intereseaz si lsai sistemul MySQL s determine nregistrrile din tabelul puncte care corespund datelor
respective. Dac v-ai ntrebat n ce msur din cauza aspectului abstract i discontinuu se pierde" ceva n ceea
ce privete preluarea informaiilor dintr-o baz de date ntr-o form semnificativ pentru noi, rspunsul este: nu
se pierde nimic.
56 Partea l Utilizarea general a sistemului MySQL
Desigur, dup ce ai examinat aceast interogare, v mai putei pune i alt ntrebare. Instruciunea pare cam
lung i complicat; nu pare o cantitate cam mare de munc numai pentru regsirea punctajelor obinute la o
anumit dat? Ba da, este. Totui, exist metode de a evita tastarea mai multor rnduri de instruciuni SQL de
fiecare dat cnd dorii s emitei o interogare, n general, determinai o singur dat modul de a executa o
interogare ca aceea i apoi o stocai, pentru a o putea repeta cu uurin atunci cnd este necesar. Vom vedea cum
se procedeaz n seciunea Sugestii pentru interaciunea cu MySQL".
n realitate, am cam exagerat punnd pe tapet acea interogare. Si totui interogarea respectiv este, credei sau
nu, ceva mai simpl dect cea pe care o vom folosi efectiv pentru extragerea punctajelor. Motivul este c trebuie
s mai facem o modificare n structura tabelului, n loc de a nregistra numele elevului n tabelul puncte, vom
folosi un identificator de elev unic. (Adic vom folosi valoarea din coloana ID a catalogului n locul valorii din
coloana Nume.) Apoi vom crea un alt tabel, denumit elev, care conine coloanele nume si elev_id (Figura 1.7).
Tabelul elev Tabelul puncte
Tabelul eveniment
Nume Sex elev_id elev_id eveniment_id Puncte
Billy M 1 1 5 15
Missy F 2 H 2 <ysJSjSiSB! 14 L
B
"
Johnny M 3 34567 556666 17 19
Jenny F 4 8 67 73
82 79
eveniment id
Data
1999-09-03 1999-09-06 1999-09-09 1999-09-16
1999-09-23
1999-10-01
Tip
CC
TC
Figura 1.7 Tabelele elev, puncte i eveniment, legate prin identificatorul de elev i identificatorul de eveniment.
De ce s facem aceast modificare? n primul rnd pentru c pot fi doi elevi cu acelai nume. Utilizarea unui
numr unic de identificare a elevului v ajut s facei diferena dintre punctajele elevilor. (Este exact acelai
lucru ca i diferenierea ntre punctajele obinute la un test i la un chestionar date n aceeai zi prin utilizarea n
locul datei a unui identificator unic de eveniment.)
Dup aceast modificare a machetei tabelului, interogarea pe care o vom folosi efectiv pentru extragerea
punctajelor aferente unei anumite date devine puin mai complex:
SELECT elev.nume, eveniment.data, puncte.puncte, eveniment.tip
FROM eveniment, puncte, elev
WHERE eveniment.data = "1999-09-23"
AND eveniment.eveniment_id = puncte.eveniment_id
AND puncte.elev_id = elev.elev_id
Dac v ngrijoreaz faptul c nu putei determina imediat semnificaia acelei interogri, linitii-v. Majoritatea
oamenilor nu sunt n stare de aa ceva. Vom revedea interogarea dup ce vom continua parcurgerea acestui
manual, dar diferena ntre acum i mai trziu este c mai trziu o vei nelege. Nu, nu m in de bancuri.
Capitolul 1 Introducere n MySQL i SQL
57
Din figura 1.7, vei observa c am adugat ceva la tabelul elev care nu exista n catalog: o coloan pentru sex.
Aceasta va permite efectuarea unor operaii simple, precum numrarea bieilor i a fetelor din clas, respectiv
mai complexe, precum compararea punctajelor bieilor cu cele ale fetelor.
Suntem aproape gata cu tabelele pentru proiectul de eviden a rezultatelor colare. Mai avem nevoie de un
singur tabel, pentru nregistrarea absenelor n vederea determinrii prezenei la curs. Coninutul acestuia este
relativ simplu: un identificator numeric al elevului i o dat (vezi figura 1.8). Fiecare rnd din tabel arat c
elevul respectiv a fost absent la acea dat. La sfritul perioadei de notare, vom apela la caracteristicile de
numrare ale sistemului MySQL pentru a rezuma coninutul tabelului, astfel nct s tim de cte ori a fost
absent fiecare elev.
Tabelul absente
elev_id Data
"2 4 2 1999-09-02
1999-09-15
1999-09-20
Figura 1.8 Tabelul absente.
Suntem gata de a crea tabelele noastre de eviden a rezultatelor colare, acum cnd tim cum vor arta acestea.
Instruciunea CREATE TABLE pentru tabelul elev arat astfel: CREATE TABLE elev
nume VARCHAR(20) NOT NULL, sex ENUMCFVM1) NOT NULL,
elev_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ) Tastai aceast instruciune
n mysql sau executai urmtoarea comand de interpreter:
% mysql samp_db < creat e_student.sql
Instruciunea CREATE TABLE creeaz un tabel denumit elev cu trei coloane: nume, sex i elev_id.
nume este o coloan ir de lungime variabil, care poate conine maximum 20 de caractere. Aceast reprezentare
a numelor este mai simpl dect cea folosit pentru tabelele Ligii istorice, folosind o singur coloan n locul
unor coloane separate pentru nume i prenume. Aceasta deoarece tiu dinainte c nici un exemplu de interogare
privind evidena rezultatelor colare nu va trebui s efectueze vreo operaie care s-ar preta mai bine la dou
coloane. (Da, triez. Recunosc.)
sex determin dac un elev este biat sau fata. Este o coloan de tip ENUM (enumerare), ceea ce nseamn c
poate lua numai una din valorile enumerate explicit n specificaia coloanei, n spe M sau F, adic de sex
masculin sau feminin. ENUM este util cnd avei un set limitat de valori pe care le poate conine o coloan. Am
fi putut folosi n schimb CHAR(1 ), dar ENUM specific mai exact care pot fi valorile din coloan. Dac emitei
o instruciune DESCRIBE numejtabel pentru un tabel care conine o coloan ENUM, MySQL v va indica exact
care sunt valorile posibile.
58
Partea l Utilizarea general a sistemului MySQL
Apropo, valorile dintr-o coloan ENUM nu trebuie s fie neaprat compuse dintr-un singur caracter. Coloana tip
ar fi putut fi declarat astfel: ENUM (' feminin', ' masculin').
elev_id este o coloan de tip ntreg care va conine numere unice de identificare a elevilor, n mod normal, vei
primi numerele de identificare a elevilor de la o surs central, cum ar fi secretariatul scolii, dar noi vom folosi
valori inventate. Declaraia coloanei elev_id are numeroase pri, chiar dac nu conine dect numere:
I NT arat c n coloan sunt incluse numere ntregi (valori fr parte fracionar)
UNSIGNED interzice utilizarea numerelor negative.
NOT NULL nseamn c valoarea coloanei trebuie completat. (Nici un elev nu poate fi lipsit de un numr de
identificare.)
AUTO_INCREMENT este un atribut special n MySQL si funcioneaz astfel: dac valoarea din coloana
elev_id lipsete (sau este NULL), atunci cnd creai o nou nregistrare n tabelul elev, MySQL genereaz
automat un numr unic cu o unitate mai mare dect valoarea maxim care se afl n coloan la momentul
respectiv. Vom folosi acest fapt la ncrcarea tabelului elev, specificnd valori numai pentru coloanele nume i
sex si permind sistemului MySQL s genereze automat valoarea coloanei elev_id.
PRIMARY KEY arat c acea coloan este indexat pentru cutri rapide i c fiecare valoare din coloan
trebuie s fie unic. Aceasta ne mpiedic s folosim din greeal acelai identificator de dou ori, ceea ce este o
proprietate necesar a numerelor de identificare a elevilor. (Nu numai att; MySQL impune ca fiecare coloan
AUTO_INCREMENT s aib un indice unic.)
Dac nu nelegei toate chestiile astea despre AUTO_INCREMENT si PRIMARY_KEY, gndii-v c ele
reprezint o modalitate magic de a genera numere de identificare pentru fiecare elev. Nu conteaz valorile n
sine, atta vreme ct sunt unice.
Not: Dac aveai de gnd s luai identificatoarele numerice ale elevilor de la secretariat (fr s le generai
automat), putei declara coloana elev_id n acelai mod, cu deosebirea c vei omite atributul
AUTO_INCREMENT.
Tabelul eveniment se prezint astfel: CREATE TABLE eveniment
data DATE NOT NULL
tip ENUM('T','C1) NOT NULL,
eveniment_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
Tastai instruciunea de mai sus n mysql sau executai urmtoarea comand de interpreter:
% mysql samp_db < create_event.sql
Toate coloanele sunt declarate ca NOT NULL, deoarece nu poate lipsi valoarea nici uneia dintre ele.
Coloana data conine o valoare DATE standard MySQL, n format "AAAA-LL-ZZ" (cu anul scris primul).
tip reprezint tipul punctajului. Ca si sex din tabelul elev, tip este o coloan de tip enumerare. Valorile permise
sunt T si C, reprezentnd test", respectiv chestionar".
Capitolul 1 Introducere n MySQL i SQL
59
eveniment_id este o coloan AUTO_INCREMENT, similar coloanei elev_id din tabelul elev. Utilizarea opiunii
AUTO_INCREMENT ne permite s generm cu uurin valori unice ale identificatorilor de eveniment. Ca n
cazul coloanei elev_id din tabelul elev, valorile particulare sunt mai puin importante dect unicitatea lor.
Tabelul puncte arat astfel: CREATE TABEL puncte (
elev_id INT UNSIGNED NOT NULL, eveniment_id INT UNSIGNED NOT NULL, punctaj INT NOT
NULL, PRIMARY KEY (eveniment_id, elev_id) ) Tastai acea instruciune n mysql sau executai urmtoarea
comand de interpreter:
% mysql samp_db < creat e_score.sql
puncte este o coloan INT (ntreg). Cu alte cuvinte, se presupune c valorile punctajelor sunt ntotdeauna ntregi.
Dac dorii s permitei includerea unor punctaje precum 58 , 5, care conin o pane fracionar, vei folosi unul
din tipurile de coloan cu virgul mobil, precum FLOAT sau DECIMAL.
Coloanele elev_id i eveniment_id sunt ntregi care reprezint elevul i evenimentul pentru care a fost acordat
fiecare punctaj. Folosindu-le pentru a stabili legturi ntre tabelele elev si eveniment, vom putea determina
numele elevului si data evenimentului. De asemenea, am transformat combinaia dintre cele dou coloane ntr-o
cheie primar (PRIMARY KEY). Astfel, ne asigurm c nu vom avea punctaje repetate pentru un elev la un test
sau chestionar dat. De asemenea, modificarea ulterioar a unui punctaj este mai simpl. De exemplu, cnd un
punctaj a fost introdus incorect, putem elimina nregistrarea veche atunci cnd inserm nregistrrile noi,
folosind instruciunea MySQL REPLACE. Nu este necesar s folosim o instruciune DELETE combinat cu
INSERT; MySQL execut automat aceast operaie.
Reinei unicitatea combinaiei ntre coloanele eveniment_id si elev_id. n tabelul puncte, nici o valoare nu este
intrinsec unic. Vor exista mai multe nregistrri de punctaje pentru fiecare valoare eveniment_id (cte una
pentru fiecare elev), respectiv mai multe nregistrri pentru fiecare valoare elev_id (cte una pentru fiecare
chestionar i test).
Tabelul absente pentru determinarea prezenei la curs se prezint astfel: CREATE TABLE absente
elev_id INT UNSIGNED NOT NULL, data DATE NOT NULL, PRIMARY KEY (elev_id, data) )
Tastai instruciunea respectiv n mysql sau executai urmtoarea comand de interpreter: % mysql sarap_db <
create_absence.sql
60
Partea l Utilizarea general a sistemului MySQL
Coloanele elev_id i data sunt ambele declarate NOT NULL pentru a interzice absena valorilor. Vom transforma
combinaia dintre cele dou coloane ntr-o cheie primar, astfel nct s nu crem din greeal nregistrri
dublate. La urma urmelor, nu-i frumos s pui absen unui elev de dou ori ntr-o zi!
Adugarea de noi nregistrri
n acest moment, baza noastr de date si tabelele au fost create, iar n seciunea urmtoare, Regsirea
informaiilor", vei afla cum se pot extrage datele din baza de date. Mai nti ns, trebuie s inserm unele
nregistrri n tabele.
Exist numeroase modaliti de a aduga date ntr-o baz de date. Putei insera manual nregistrri ntr-un tabel
emind instruciuni INSERT. De asemenea, putei aduga nregistrri citindu-le dintr-un fiier, fie sub form de
valori de date brute pe care le ncrcai folosind instruciunea LOAD DATA sau utilitarul mysqlimport, fie n
form de instruciuni INSERT redactate anterior, pe care le introducei n mysql.
Aceast seciune ilustreaz fiecare metod de inserie a nregistrrilor n tabelele dumneavoastr. Ce avei
dumneavoastr de fcut este s v jucai cu diferitele metode, pentru a vedea cum funcioneaz. Apoi, deplasai-
v la sfritul seciunii i rulai comenzile pe care le gsii acolo pentru a terge coninutul tabelelor si pentru a le
rencrca. Astfel, v vei asigura c tabelele conin aceleai nregistrri la care am lucrat cnd am scris seciunea
urmtoare, iar dumneavoastr vei obine aceleai rezultate.
S ncepem s adugm rezultate folosind INSERT, o instruciune SQL pentru care specificai tabelul n care
dorii s inserai un rnd de date i valorile care vor fi plasate n rndul respectiv.
Instruciunea INSERT are mai multe forme:
Putei specifica valori pentru toate coloanele:
INSERT INTO nume_tabel VALUES(valoare1,valoare2,...) De exemplu:
mysql> INSERT INTO elev VALUES('Minai1,'M1,NULL);
mysql> INSERT INTO eveniment VALUESC11999-9-3","C",NULL); Cuvntul INTO este opional ncepnd de
la MySQL 3.22.5. (Acest lucru este valabil si pentru celelalte forme ale instruciunii INSERT.) Lista VALUES
trebuie s conin o valoare pentru fiecare coloan din tabel, n ordinea n care sunt stocate coloanele n tabel, (n
mod normal, aceasta este ordinea n care au fost specificate coloanele la crearea tabelului. Folosii DESCRIBE
nume_tabel pentru a afla ordinea, dac nu o cunoatei cu exactitate.)
Putei ncadra ntre ghilimele valorile de tip ir i dat n MySQL, folosind ghilimele simple sau duble. Valorile
NULL din exemplul precedent sunt destinate coloanelor AUTO_INCREMENT din tabelele elev si eveniment.
(Inseria unei valori lips" determin generarea urmtorului numr elev_id sau eveniment_id.)
Versiunile MySQL ncepnd de la 3.22.5 v permit s inserai mai multe rnduri ntr-un tabel cu o singur
instruciune INSERT, prin specificarea mai multor liste de valori: INSERT INTO nume_tabel VALUES(...),
(...),...
Capitolul 1 Introducere n MySQL i SQL
61
De exemplu: mysql> INSERT INTO elev VALUES('Ana1,'F1,NULL),("Mihai',"M",NULL);
Acest procedeu necesit introducerea de la tastatur a unei cantiti mai reduse de text dect cea impus de mai
multe instruciuni INSERT, iar execuia sa de ctre server este mai eficient.
Putei denumi coloanele crora dorii s le atribuii valori, apoi enumerai valorile. Acest procedeu este util
cnd dorii s creai o nregistrare pentru care numai cteva coloane trebuie configurate iniial.
INSERT INTO nume_tabel (nume_col1 ,nume_col2,...) VALUES(valoare7,valoare2,...) De exemplu:
mysql> INSERT INTO membru (nume,prenume) VALUES('Tache','tefan'); De la MySQL 3.22.5, aceast
form a instruciunii INSERT permite de asemenea mai multe liste cu valori:
mysql> INSERT INTO elev (nume,sex) VALUES('Ana1,'F'),("Mihai","M"); Coloanele care nu sunt specificate
n lista de coloane primesc o valoare prestabilit.
De la MySQL 3.22.10, putei denumi coloanele i valorile sub forma nume_coloana=valoare.
INSERT INTO nume_tabel SET nume_col1=valoare1, nume_co!2=valoare2,... De exemplu:
mysql> INSERT INTO membru SET nume='Tache',prenume='tefan'; Toate coloanele care nu sunt specificate n
clauza SET primesc o valoare prestabilit. Nu putei insera mai multe rnduri folosind aceast form a
instruciunii INSERT.
O alt metod pentru ncrcarea nregistrrilor ntr-un tabel este citirea valorilor datelor direct dintr-un fiier.
Putei ncrca nregistrri n acest mod cu ajutorul instruciunii LOAD DATA sau cu utilitarul mysqlimport.
Instruciunea LOAD DATA se comport ca un ncrctor de mare capacitate, care citete date dintr-un fiier.
Folosii aceast instruciune din interiorul programului mysql:
mysql> LOAD DATA LOCAL INFILE "membru.txt" INTO TABLE membru; Aceast instruciune citete
coninutul fiierului de date membru. txt localizat n catalogul dumneavoastr curent din gazda programului
client i o trimite serverului, pentru a fi ncrcat n tabelul membru.
LOAD DATA LOCAL nu va avea efect dac versiunea dumneavoastr de MySQL este anterioar versiunii
3.22.15, deoarece posibilitatea de citire a fiierelor de la client a fost adugat la instruciunea LOAD DATA
ncepnd de la versiunea respectiv. (Fr cuvntul cheie LOCAL, fiierul trebuie localizat pe gazda serverului si
dumneavoastr avei nevoie de un privilegiu de acces la server, de care majoritatea utilizatorilor MySQL nu
dispun.)
n mod prestabilit, instruciunea LOAD DATA presupune c valorile coloanelor sunt separate prin tabulator! i c
rndurile se ncheie cu un caracter linie nou. De asemenea, presupune c valorile exist n ordinea n care
coloanele sunt stocate n tabel. Este posibil citirea fiierelor n alte formate sau specificarea unei alte ordini a
coloanelor. Vezi rubrica aferent comenzii LOAD DATA din Anexa D, Referin de sintax SQL", pentru mai
multe detalii.
62 Partea l Utilizarea general a sistemului MySQL
Utilitarul mysqlimport este o interfa n linie de comand pentru instruciunea LOAD DATA. Acest utilitar se
invoc din interpretor i genereaz automat o instruciune LOAD DATA:
% mysqlimport --local sarap_db nembru.txt
mysqlimport genereaz automat o instruciune LOAD DATA, care determin ncrcarea fiierului membru. txt n
tabelul membru. Acest lucru nu este posibil dac programul dumneavoastr MySQL este anterior versiunii
3.22.15, deoarece opiunea --local necesit LOAD DATA LOCAL. Ca si n cazul programului mysql, dac
trebuie s specificai parametri de conexiune, indicai-i n linia de comand, anterior numelui bazei de date.
mysqlimport extrage numele tabelului din numele fiierului de date. (Ca nume al tabelului, se folosesc toate
caracterele, pn la primul punct din numele fiierului.) De exemplu, membru.txt va fi ncrcat n tabelul
membru, iar presedinte.txt va fi ncrcat n tabelul preedinte. Dac avei mai multe fiiere de ncrcat ntr-un
singur tabel, alegei numele fiierelor cu atenie; n caz contrar, mysqlimport nu va folosi numele corect de tabel.
Cu nume ca membrul .txt sau membru2.txt, mysqlimport va presupune c numele tabelelor sunt membrul,
respectiv membru2. Totui, putei folosi nume precum membru. 1 .txt i membru.2.txt, respectiv membru.txt! i
membru.txt2.
Dup ce ai testat aceste metode de adugare a nregistrrilor, trebuie s tergei coninutul tabelelor i apoi s le
rencrcai, astfel nct coninutul lor s fie cel presupus n seciunea urmtoare.
Din interpretorul dumneavoastr, executai urmtoarele comenzi:
% ntysql sarap_db < insert_president.sql
% mysql samp_db < insertjnember.sql
% mysql samp_db < insert_student.sql
% mysql samp_db < insert_score.sql
% mysql samp_db < insert_event.sql
% mysql samp_db < insert_absence.sql
Fiecare fiier conine o instruciune DELETE pentru tergerea tuturor nregistrrilor pe care le-ai inserat n tabel,
urmat de un set de comenzi INSERT pentru reiniializarea coninutului tabelului. Dac nu dorii s scriei
fiecare din aceste comenzi n parte, ncercai urmtoarea comand:
% cat insert_*.sql | mysql samp_db
Regsirea informaiilor
Acum, tabelele noastre au fost create i ncrcate cu date, deci haidei s vedem ce putem face cu acele date.
Instruciunea SELECT v permite s regsii si s afiai informaii din tabelele dumneavoastr, ntr-o manier
orict de general sau de specific dorii. Putei afia ntregul coninut al unui tabel:
SELECT * FROM preedinte Sau putei selecta o singur coloan a unui singur rnd:
SELECT data_nastere FROM preedinte WHERE nume = "Eisenhower"
Capitolul 1 Introducere n MySQL i SQL
63
Instruciunea SELECT are numeroase clauze (pri) pe care le combinai conform necesitilor pentru a regsi
informaia care v intereseaz. Fiecare dintre aceste clauze poate fi simpl sau complex, deci instruciunile
SELECT n totalitatea lor pot fi simple sau complexe. Totui, putei sta linitit; nu vei gsi n aceast carte
interogri lungi de o pagin, pentru care avei nevoie de o or pentru a le pricepe. (Cnd gsesc ntr-un material
interogri lungi de-un cot, n general le omit fr mustrri de contiin si bnuiesc c si dumneavoastr
procedai la fel.)
Forma general a instruciunii SELECT este:
SELECT ce se selecteaz
FROM tabel sau tabele
WHERE condiii pe care trebuie sa le satisfac datele
Nu uitai c SQL este un limbaj cu "format liber; deci, cnd v scriei propriile dumneavoastr interogri
SELECT, nu este necesar s inserai salturile la linie nou acolo unde le-am inserat eu.
Pentru a scrie o instruciune SELECT, specificai ce anume dorii s regsii i apoi unele clauze opionale.
Clauzele prezentate mai sus (FROM, WHERE) sunt cel mai frecvent folosite, dei mai pot fi specificate si altele,
cum sunt GROUP BY, ORDER BY si LIMIT.
Clauza FROM este de regul prezent, dar acest lucru nu este necesar dac nu selectai date din tabele. De
exemplu, interogarea urmtoare afieaz pur si simplu valorile unor expresii care pot fi calculate fr referire la
vreun tabel, deci nu este necesar nici o clauz FROM:
mysql> SELECT 2+2, "Salut, lume', VERSION();
2+2 i Salut, lume j VERSION()
4 j Salut, lume i 3.23.0'-alpha-log
Cnd folosii o clauz FROM pentru a specifica un tabel de unde vor fi regsite datele, forma cea mai generic"
a instruciunii SELECT este aceea prin care se regsesc toate datele. Pentru aceasta, folosii caracterul *, care
este o abreviere de la toate coloanele". Interogarea urmtoare regsete toate rndurile din tabelul elev si le
afieaz: mysql> SELECT * FROM elev;
nume sex elev_id
Megan F 1
Joseph M 2
Kyle M 3
Katie p 4
Coloanele sunt returnate n ordinea n care MySQL le-a stocat n tabel. Aceasta este ordinea n care coloanele
sunt afiate atunci cnd se emite o instruciune DESCRIBE elev. Punctele de suspensie de la sfritul exemplului
arat c interogarea returneaz mai multe rnduri dect cele prezentate.
Putei denumi n mod explicit coloana sau coloanele pe care dorii s le vedei. Pentru a selecta numai numele
elevilor, procedai astfel:
64 Partea l Utilizarea general a sistemului MySQL
mysql> SELECT nume FROM elev;
nume
Megan Joseph Kyle Katie
Dac precizai mai mult de o coloan, separai numele coloanelor prin virgule. Instruciunea urmtoare este
echivalent cu SELECT * FROM elev, dar fiecare coloan este specificat n mod explicit:
mysql> SELECT nume,sex,elev_id FROM elev;
nume sex elev_id
Megan F 1
Joseph M 2
Kyle M 3
Katie F 4
Putei specifica dac sortarea unei coloane se va face n ordine ascendent sau descendent folosind cuvintele
cheie ASG sau DESC dup numele coloanelor din clauza ORDER BY. De exemplu, pentru a sorta numele
preedinilor n ordine invers (descresctoare), folosii DESC astfel:
mysql> SELECT nune, prenume FROM preedinte -> ORDER BY nume DESC;
nume prenume
Wilson Wood row
Washington George
Van Buren Martin
Tyler John
Ordinea ascendent este cea prestabilit dac nu specificai ASC sau DESC pentru un nume de coloan ntr-o
clauz ORDER BY.
Dac sortai o coloan care poate conine valori NULL, toate valorile NULL apar la nceputul coloanei, respectiv
la sfrit, dac sortai n ordine descendent.
Rezultatele interogrii pot fi sortate pe mai multe coloane, iar fiecare coloan poate fi sortat n ordine
ascendent sau descendent, independent de celelalte coloane. Interogarea urmtoare regsete rnduri din
tabelul preedinte, le sorteaz n sens descendent n funcie de statul de natere i dup numele de familie n
cadrul fiecrui stat: mysql> SELECT nume, prenume, stat FROM preedinte -> ORDER BY stat DESC, nume
ASC;
nume prenume stat
Arthur Chester A. VT
Coolidge Calvin VT
Harrison William H. VA
Jefferson Thomas VA
Madison James VA
Monroe James VA
Taylor Zachary VA
Tyler John VA
Washington George VA
Wilson Woodrow VA
Eisenhower Dwight D. TX
Johnson Lyndon B. TX
Aceast interogare formateaz numele preedinilor sub forma unui singur ir, prin concatenarea numelui si a
prenumelui separate printr-un spaiu i formateaz locul naterii sub forma oraelor i statelor separate prin
virgul.
Cnd folosii o expresie pentru a calcula valoarea unei coloane, expresia este folosit pentru antetul coloanei.
Aceasta poate duce la o coloan foarte lat, dac expresia este lung (aa cum o arat interogarea precedent).
Pentru a rezolva problema, capului de coloan i se poate atribui un nume, folosind construcia AS nume.
Asemenea nume se numesc aliasuri de coloan. Rezultatul interogrii anterioare poate deveni astfel mai
semnificativ:
mysql> SELECT CONCAT(prenume," ",nuBe), AS Nume,
-> CONCAT(ora,', ",stat) As Loculnasterii
-> FROM preedinte;
Nume i Loculnasterii
n cazul n care aliasul coloanei conine spaii, acestea vor trebui inserate ntre ghilimele: mysql> SELECT
CONCAT(prenume," *,nune), AS 'Nunele preedintelui* -> CONCAT(oras,", ",stat) As "Locul naterii" ->
FROM preedinte;
72 Partea 1 Utilizarea general a sistemului MySQL
Aceeai form de interogare indic numrul de preedini nscui n fiecare stat: mysql> SELECT stat,
COUNT(*) FROM preedinte GROUP BY stat;
i stat COUNT(*)
i AR 1
i CA 1
i GA 1
;IA 1
L 1
!KY 1
i M 4
i MO 1
i NC 2
INE 1
;NH 1
IN j 1
iNY 4
i OH 7
i PA 1
jsc 1
;TX 2
i VA 8
iVT 2
Cnd numrau valorile n acest mod, clauza GROUP BY este necesar, deoarece indic programului MySQL
modul de grupare a valorilor nainte de a le numra. Dac omitei aceast clauz, vei primi un mesaj de eroare.
Utilizarea funciei COUNT(*) cu GROUP BY pentru numrarea valorilor are un numr de avantaje n raport cu
numrarea individual a apariiilor fiecrei valori distincte din coloan:
Nu trebuie s tii dinainte care sunt valorile prezente n coloana al crei coninut l rezumai.
Avei nevoie de o singur interogare, nu de mai multe interogri.
Obinei toate rezultatele ntr-o singur interogare, deci putei sorta datele de ieire.
Primele dou avantaje sunt importante pentru exprimarea cu mai mare uurin a interogrilor. Cel de-al treilea
avantaj este important deoarece v permite o flexibilitate n afiarea rezultatelor.
Capitolul 1 Introducere n MySQL i SQL
79
Cnd folosii o clauza GROUP BY, rezultatele sunt sortate n coloanele n funcie de care realizai gruparea, dar
putei folosi ORDER BY pentru a sorta ntr-o alt ordine. De exemplu, dac dorii ca numerele de preedini s
fie grupate n funcie de statul de natere, dar s fie i sortate n ordinea descresctoare a celor mai bine
reprezentate state, putei folosi o clauz ORDER BY dup cum urmeaz:
mysql> SELECT stat, COUNT(*) AS numr FROM preedinte -> GROUP BY stat ORDER BY numr DESC;
istat numr
!VA 8
;OH 7
M 4
;NY 4
INC 2
iVT O
;TX n
isc 1
;NH 1
i PA 1
;KY 1
!NJ 1
i IA 1
i MO 1
:CA 1
i NE 1
;GA 1
;IL 1
IAR 1
Cnd coloana dup care dorii s sortai este determinat prin calcul, putei da coloanei un alias i putei face
referire la alias n clauza ORDER BY. Interogarea anterioar demonstreaz acest fapt; coloana COUNT(*) este
denumit numr. O alt modalitate de a face referire la o asemenea coloan este prin poziia sa n datele de ieire.
Interogarea anterioar ar fi putut fi scris si astfel:
SELECT state, COUNT(*) FROM preedinte
GROUP BY stat ORDER BY 2 DESC
Nu cred c desemnarea unei coloane prin poziia acesteia este foarte sugestiv. Dac adugai, eliminai sau re-
ordonai coloanele cu datele de ieire, trebuie s v amintii s verificai clauza ORDER BY si s corectai
numrul coloanei, dac acesta s-a modificat. Aliasurile nu ridic aceast problem.
Dac dorii s folosii GROUP BY cu o coloan care conine valori calculate, trebuie s facei referire la acea
coloan folosind un alias sau poziia coloanei, aa cum se procedeaz n cazul clauzei ORDER BY. Urmtoarea
interogare determin numrul preedinilor care s-au nscut n fiecare lun a anului:
mysql> SELECT MONTH(data_nastere) as Luna,
-> MONTHNAME(datajiastere) AS Nume, COUNT(*) AS numr -> FROM preedinte GROUP BY Nume
ORDER BY Luna;
80
Partea l Utilizarea general a sistemului MySQL
Luna Nume numr
1 Ianuarie A
2 Februarie 4
3 Martie 4
4 Aprilie 4
5 Mai 2
/ Iunie 1
- Iulie 3
B August 4
9 Septembrie 1
10 Octombrie 6
11 Noiembrie 5
12 Decembrie 3
Folosind poziiile coloanelor, interogarea poate fi scris astfel:
SELECT MONTH(data_nastere), MONTHNAME(data_nastere), COUNT(*) FROM preedinte GROUP BY 2
ORDER BY 1;
COUNTQ poate fi combinat cu ORDER BY i LIMIT pentru a gsi, de exemplu, cele mai
bine reprezentate patru state din tabelul preedinte:
mysql> SELECT stat, COUNT(*) AS nuiar FROM preedinte -> GROUP BY stat ORDER BY numr DESC
LIMIT 4;
i stat numr
i VA i 8
OH 7 4 4
i M
JNY
Dac nu dorii s limitai datele de ieire ale interogrii folosind o clauz LIMIT, ci prin cutarea anumitor valori
ale funciei COUNT(), utilizai o clauz HAVING. Interogarea urmtoare v va indica numrul de state
reprezentate prin doi sau mai muli preedini: mysql> SELECT stat, COUNT(*) AS miiar FROM preedinte
-> GROUP BY stat HAVING nunar > 1 ORDER BY numr DESC;
istat numr
i VA 8
;OH 7
;MA 4
NY 4
;NC 2
iVT 2
TX 2
n general, acesta este tipul de interogare care trebuie executat atunci cnd dorii s gsii ntr-o coloan valori
care se repet.
HAVING este similar cu WHERE, dar se aplic dup ce au fost selectate rezultatele interogrii si este folosit
pentru a reduce domeniul rezultatelor trimise efectiv de server clientului.
Exist funcii de sumar altele dect COUNT (). Funciile MIN (), MAX (), SUM () si AVG () sunt utile pentru
determinarea valorii minime, maxime, totale i medii dintr-o coloan. Le putei chiar
Capitolul 1 Introducere n MySQL i SQL
81
folosi pe toate simultan. Urmtoarea interogare prezint diferite caracteristici numerice pentru fiecare chestionar
i test pe care l-ati dat. De asemenea, indic numrul de punctaje incluse n calculul fiecrei valori. (Unii elevi au
fost abseni i, ca atare, nu au fost numrai.) mysql> SELECT
-> eveniment_id,
-> MIN(puncte) AS minim,
-> MAX(puncte) AS maxim,
-> MAX(puncte)-MIN(puncte)+1 AS domeniu,
-> SUM(puncte) AS total,
-> AVG(puncte) AS medie,
-> COUNT(puncte) AS numr,
-> FROM puncte
-> GROUP BY eveniment_id;
eveniment_id minim maxim domeniu total medie numr
1 9 20 12 439 15.1379 29
2 8 19 12 425 14.1667 30
3 60 97 38 2425 78.2258 31
4 7 20 14 379 14.0370 27
5 8 20 13 383 14.1852 27
6 62 100 39 2325 80.1724 29
Aceste informaii pot deveni mai semnificative dac ai ti, desigur, dac valorile respective au fost obinute la
punctaje sau teste. Totui, pentru a obine acele informaii, trebuie s consultm i tabelul eveniment; vom reveni
la aceast interogare n seciunea Regsirea informaiilor din mai multe tabele".
Funciile de sumar sunt distractive, deoarece sunt foarte puternice, dar v putei lsa foarte uor dus de val".
Privii aceast interogare: mysql> SELECT
-> stat AS Stat,
-> AVG((TO_DAYS(data_deces)-TO_DAYS(data_nastere))/365) AS Vrsta
-> FROM preedinte WHERE data_deces IS NOT NULL
-> GROUP BY state ORDER BY Vrsta;
i stat ! vrsta j ; stat i vrsta i
iKY j 56. 20821 9! !TX 71. 476712
j
;VT ; 58. 852055! :MA ! 72.
642009;
; NC ; 60. 141096! ;VA ! 72.
822945;
;OH ! 62. 8661 !PA ' 77.
45 : 158904;
;NH ! 64. 91 7808! !SC i 78.
284932!
;NY i 69. 342466! ;CA ; 81.
336986!
:NJ ! 71. 31 5068; !MO j 88. 6931
51 !
!IA ! 90.
254795!
Interogarea selecteaz preedinii care au decedat, i grupeaz n funcie de data naterii, le calculeaz vrsta la
data decesului, calculeaz vrsta medie (per stat) i apoi sorteaz rezultatele dup vrsta medie. Cu aljte cuvinte,
interogarea determin, pentru preedinii care nu mai sunt n via, vrsta medie la data decesului n funcie de
statul de natere.
82 Partea l Utilizarea general a sistemului MySQL
i ce nseamn asta? nseamn numai c putei scrie interogarea. Evident, nu nseamn c interogarea merit
scris. Nu toate operaiile pe care le putei aplica unei baze de date sunt la fel de semnificative; totui, uneori
oamenii devin extrem de fericii cnd afl ce anume pot face cu baza lor de date. Astfel se poate explica apariia
unui numr tot mai mare de statistici din ce n ce mai ezoterice (i mai lipsite de sens) cu ocazia evenimentelor
sportive televizate din Statele Unite n ultimii ani. Statisticienii sportivi i pot folosi bazele de date pentru a
determina tot ce dorii s tii despre o echip, dar i tot ce nu dorii s tii. Chiar este att de important s tii
care funda din Divizia A (mutatis mutandis pentru realitatea romneasc - N.T.) are la activ cele mai multe
intercepii n careul de 16 metri atunci cnd echipa lui conduce cu mai mult de dou goluri diferen, cnd pn
la sfritul reprizei a doua sunt mai puin de 15 minute i antrenorul nc n-a fcut cele trei schimbri
regulamentare?
Regsirea informaiilor din mai multe tabele
Interogrile pe care le-am scris pn acum au extras date dintr-un singur tabel. Acum ajungem la partea
interesant. Am mai spus c puterea unui SGBD relaional rezid n capacitatea sa de a corela un aspect cu altul,
deoarece acest fapt v permite s combinai informaii din mai multe tabele pentru a gsi rspunsul la ntrebri la
care nu se poate rspunde consultnd un singur tabel. Aceast seciune v prezint modul de scriere a
interogrilor de regsire a informaiilor din mai multe tabele.
Cnd selectai informaii din mai multe tabele, efectuai o operaie denumit unire. Aceasta deoarece producei
un rezultat prin unirea informaiilor dintr-un tabel cu informaiile din cellalt tabel, operaie care are loc prin
coroborarea nregistrrilor din mai multe tabele care conin valori comune.
S parcurgem un exemplu. Anterior, n seciunea Tabele pentru proiectul de eviden a rezultatelor colare", a
fost prezentat, fr nici o explicaie, o interogare pentru regsirea punctajelor de la chestionare sau teste date la
o anumit dat. Acum este momentul s dm explicaia. De fapt, interogarea implic o unire pe trei ci, deci o
vom descrie n dou etape.
n prima etap, construim o interogare pentru selectarea punctajelor obinute la o anumit dat, dup cum se
poate vedea mai jos: mysql> SELECT elev_id, data, puncte, tip
-> FROM eveniment, puncte
-> WHERE data = '1999-09-23'
-> AND eveniment.eveniraent_id = puncte.eveniment_id;
elev_id data puncte tip
1 1999-09-23 15 c
f\ 1999-09-23 12 C
3 1999-09-23 11 C
5 1999-09-23 13 c
6 1999-09-23 18 c
Kyle Abby
3 5 10 17 Peter Will
20 Avery 1211
Not: Dei am furnizat un calificator n clauza GROUP BY, nu este absolut necesar pentru aceast interogare.
GROUP BY se refer la coloanele din lista de selecie (din,primele dou linii ale interogrii). Aici exist o
singur coloan denumit elev_id, deci MySQL cunoate coloana la care v referii. Acest fapt este de asemenea
valabil pentru coloanele specificate n clauzele ORDER BY.
Datele de ieire generate de interogare sunt acceptabile dac dorim s tim numai care sunt elevii cu absene.
Dar, dac trimitem aceast list la secretariatul colii, cei de acolo vor spune: Dar ceilali elevi? Vrem o valoare
pentru fiecare elev." Aceasta este;o problem uor diferit, nseamn c dorim s cunoatem numrul absenelor,
chiar i pen-
Capitolul 1 Introducere n MySQL i SQL
85
tru elevii care nu au avut nici o absen. Deoarece ntrebarea este diferit, i interogarea este diferit.
V ' . ' " -. . ' "
"()..'
Pentru a rspunde la ntrebare, putem folosi LEFT JOIN n loc de a asocia identificatorul de elev n clauza
WHERE. LEFT JOIN indic programului MySQL ;s genereze un rnd de date de ieire pentru fiecare rnd
selectat din tabelul denumit primul n cadrul unirii (adic tabelul precizat n stnga cuvintelor cheie LEFT JOIN).
Preciznd mai nti tabelul elev, vom primi date de ieire pentru fiecare elev, chiar i pentru cei care nu sunt
reprezentai n tabelul absente. Interogarea se prezint astfel: mysql> SELECT elev.elev_id, elev.nue,
-> COUNT(absente,date) A absente
-> FROM elev LEFT JOIN absente
-> ON elev.elev_id = absente.elevJLd
-> GROUP BY elevielevid; (
elev_id nume absente
.
WA.V.,.!- :
.:...
1 Megan 0
2 Joseph 0
3 Kyle 1
4 Katie 0
5 Abby 1
6 Nathan 0
7 Liesl 0
Anterior, n seciunea Generarea de sumare* am rulat a interogare care producea o caracterizare numerica a
datelor din tabelul puncte. Datele de ieire ale acelei interogri afiau identificatorul de eveniment, dar nu
includeau data la care a fost obinut punctajul sau tipul acestuia, deoarece atunci nu tiam cum s unim tabelul
puncte cu tabelul eveniment, pentru .a obine datele i tipurile punctajelor. Acum tim. Interogarea urmtoare
este similar celei pe care am executat-o anterior, dar prezint data i tipul punctajelor, nu numai identificatorul
numeric de eveniment:
mysql> SELECT :
, -> eveninent.data,eyeniseat.tip .
-> MIN(puncte.puncte) AS inia, -> MAX(puncte.puncte) AS MxiM,
-> MAX(puncte.puncte)-MIN(puncte.puncte)+1 AS doieniu, -> SQM(puncte.puncte) AS total,
,
-> AVG(puncte.puncte) AS edie,, -> COUNT(puncte.puncte) AS nimar, -> FROM puncte, eveniment
:j,',; .
-> HERE puncte.evenient_id = eveni*ent.eveniHent_14 -> GROUP BY evenUent.data;
86
Partea l Utilizarea general a.sistemului MySQL
data tip minim maxim domeniu total medie numr
1999-09-03 c 9 20 12 439 15.1379 29
1999-09-06 C 8 19 12 425 14.1667 30
1999-09-09 T 60 97 38 2425 78.2258 31
1999-09-16 r* 7 20 14 379 14.0370 27
1999-09-23 c Q 20 13 383 14.1852 27
1999-10-01 62 100 39 2325 80.1724 29
Putei folosi funcii precum COUNT () sau AVG() pentru a genera un sumar pe coloane multiple, chiar dac
aceste coloane provin de la tabele diferite. Interogarea urmtoare determin numrul de punctaje si punctajul
mediu pentru fiecare combinaie ntre data evenimentului i sexul elevului:
mysql> SELECT eveniment.data, elev.sex,
-> COUNT(puncte) AS numr, AVG(puncte) AS medie
-> FROM eveniment, puncte, elev
-> WHERE eveniment.eveninent_id = puncte.elev_id
-> AND puncte.elev_id = elev.elev_id
-> GROUP BY eveniment.data, elev.sex;
data sex numr medie
1999-09-03 F 14 14.6429
1999-09-03 M 15 15.6000
1999-09-06 F 14 14.7143
1999-09-06 M 16 13.6875
1999-09-09 F 15 77.4000
1999-09-09 M 16 79.0000
1999-09-16 F 13 15.3077
1999-09-16 M 14 12.8571
1999-09-23 F 12 14.0833
1999-09-23 M 15 14.2667
1999-10-01 F 14 77.7857
1999-10-01 M 15 82.4000
Putem folosi o interogare similar pentru a efectua una dintre sarcinile aferente proiectului de eviden a
rezultatelor colare: calculul punctajului total al fiecrui elev la sfritul semestrului. Interogarea se prezint
astfel:
SELECT elev.elev_id, elev.nume
SUM(puncte.puncte) AS total, COUNT(puncte.puncte) AS n
FROM eveniment, puncte, elev
WHERE eveniment.eveniment_id = puncte.eveniment_id
AND puncte.elev_id = elev.elev_id
GROUP BY puncte.elev_id
ORDER BY total
Nu exist nici o cerin conform creia o unire trebuie efectuat folosindu-se dou tabele diferite. La nceput
poate prea ciudat, dar putei uni un tabel cu el nsui. De exemplu, putei determina dac au existat preedini
nscui n acelai ora comparnd locul naterii fiecrui preedinte cu locul naterii tuturor celorlali preedini:
Capitolul 1 Introducere n MySQL i SQL
87
mysql> SELECT pl.nume, p1.prenume, pl.oras, pl.stat -> FROM preedinte AS p1, preedinte AS p2 ->
WHERE pl.oras = p2.oras AND pl.stat = p2.stat -> AND (pl.nume != p2.nume OR p1.prenume != p2.prenume)
-> ORDER stat, ora, nume;
nume prenume ora stat
Adams John Quincy John Braintree M
Adams Braintree M
Exist dou aspecte ciudate ale acestei interogri:
Trebuie s facem referire la dou instane ale aceluiai tabel, deci vom crea aliasuri ale tabelului (p1, p2) i le
vom folosi pentru a explicita referirile la coloanele tabelului.
nregistrarea fiecrui preedinte este echivalent cu ea nsi, dar nu dorim s vedem acest lucru n datele de
ieire. Cea de-a doua linie a clauzei WHERE interzice corespondena unei nregistrri cu ea nsi, asigurnd
faptul c nregistrrile comparate aparin unor preedini diferii.
O interogare similar gsete preedinii care s-au nscut n aceeai zi. Datele de natere nu pot fi comparate
direct, deoarece astfel s-ar pierde" preedinii care s-au nscut n ani diferii, n schimb, vom folosi MONTH ()
i DAYOFMONTH() pentru a compara ziua i luna datei de natere:
mysql> SELECT pl.nume, p1.prenume, p1.data_nastere
-> FROM preedinte AS p1, preedinte AS p2
-> WHERE MONTH(p1.data_nastere) = MONTH(p2.data_nastere)
-> AND DAYOFMONTH(p1.data_nastere) =
-> DAYOFMONTH(p2.data_nastere)
-> AND (pl.nume != p2.nume OR p1.prenume != p2.prenume)
-> ORDER BY pl.nume;
nume prenume data_nastere
Harding Polk Warren G. 1865-11-02
James K. 1795-11-02
Folosind funcia DAYOFYEAR () n locul combinaiei ntre funciile MONTH () i DAYOFMONTH () s-ar
obine o interogare mai simpl, dar s-ar produce rezultate incorecte atunci cnd se compar datele din anii biseci
cu datele din anii cu 365 de zile.
Unirile efectuate pn acum au combinat informaii din tabele ntre care exist o oarecare relaie logic
semnificativ, dar numai dumneavoastr cunoatei semnificaia acelei relaii. MySQL nu tie (sau nu-i pas)
dac tabelele unite au sau nu vreo legtur unul cu altul. De exemplu, putei uni tabelul eveniment cu tabelul
preedinte, pentru a afla dac ai dat sau nu chestionare sau teste de ziua de natere a unui preedinte: mysql>
SELECT preedinte.nume, preedinte.prenume,
-> preedinte.data_nastere, eveniment.tip
-> FROM preedinte, eveniment
-> WHERE MONTH(presedinte.data_nastere) =
88 Partea l Utilizarea general a sistemului MySQL
-> MONTH(eveniment.data)
-> ANO DAYOFMONTH(preedinte.data_nastere)
-> OAYOFMONTH(eveniment.data);
nume prenume data_nastere tip
Carter James E 1924-10-01 T
Se pare c ai dat un test de ziua de natere a unui preedinte. i ce dac? Aceasta nseamn c MySQL va fi
foarte bucuros s scoat la iveal rezultate, indiferent dac ele sunt logice sau nu. Numai pentru c folosii un
calculator nu nseamn obligatoriu c rezultatele unei interogri sunt utile sau c merit osteneala. Din fericire
sau din pcate, nu suntem scutii de a ti ce trebuie s facem.
tergerea sau actualizarea nregistrrilor existente
Uneori, dorii s v descotorosii de nregistrri sau dorii s le modificai coninutul. Instruciunile DELETE i
tlPDATE v permit aceste operaii.
Instruciunea DELETE are urmtoarea form:
DELETE FROM tabel_nume WHERE nregistrri care trebuie terse Clauza WHERE indic nregistrrile care
trebuie terse si este opional dar, dac o omitei, vor fi terse toate nregistrrile. Aceasta nseamn c
instruciunea DELETE cea mai simpl este i cea mai periculoas:
DELETE FROM nume_tabel
Aceast interogare terge n totalitate coninutul tabelului. Fii atent la interogarea respectiv!
Pentru a terge anumite nregistrri, folosii clauza WHERE pentru a selecta nregistrrile care v intereseaz.
Aceasta este similar clauzei WHERE dintr-o instruciune SELECT. De exemplu, pentru a terge din tabelul
preedinte pe toi preedinii nscui n statul Ohio, folosii aceast interogare:
mysql> DELETE FROM preedinte WHERE stat="OH";
Query OK, 7 rows affected (0.00 sec)
Un dezavantaj al clauzei WHERE pentru instruciunea DELETE este acela c putei face referire numai la
coloanele tabelului din care tergei nregistrrile.
nainte de a emite o instruciune DELETE, deseori este bine s testai clauza WHERE folosind-o cu o
instruciune SELECT, pentru a v asigura c vei terge nregistrrile pe care dorii s le tergei (si numai acele
nregistrri). S presupunem c dorii s tergei nregistrarea pentru Teddy Roosevelt. Ar fi bun urmtoarea
interogare?
DELETE FROM preedinte WHERE nume="Roosevelt"
Da, n sensul c ar terge nregistrarea pe care o avei n vedere. Nu, n sensul c ar terge i nregistrarea lui
Franklin Roosevelt. Cel mai bine este s verificai n prealabil clauza WHERE, astfel:
mysql> SELECT nume, prenume FROM preedinte -> WHERE nume="Roosevelt";
Capitolul 1 Introducere n MySQL i SQL
89
prenume nume
Roosevelt Theodore
Roosevelt Franklin D.
Din acest exemplu se deduce necesitatea de a fi mai concret: mysql> SELECT nume, prenume FROM
preedinte
-> WHERE nurae=nRoosevelt" AND prenume="Theodore";
prenume nume
Roosevelt Theodore
Acum tim care este clauza WHERE corect pentru selectarea nregistrrii dorite, deci interogarea DELETE
poate fi construit corect: mysql> DELETE FROM preedinte
-> WHERE nume="Roosevelt" AND prenume="Theodore"; Cam mult munc pentru a terge o nregistrare, nu-
i aa? Paza bun trece primejdia rea!
(Aceasta este una din situaiile n care vei dori s reducei la minimum numrul caracterelor introduse de la
tastatur, prin utilizarea tehnicilor de copiere si lipire, respectiv de editare a liniilor de intrare. Vezi seciunea
Sugestii pentru interaciunea cu mysql" pentru mai multe informaii.)
Pentru modificarea nregistrrilor existente, folosii UPDATE, care are urmtoarea form:
UPDATE nume_tabel SET coloane de modificat
WHERE nregistrri de actualizat
Clauza WHERE se folosete ca n cazul instruciunii DELETE i este opional deci, dac nu o specificai, v or fi
actualizate toate nregistrrile din tabel. Interogarea urmtoare transform numele tuturor elevilor dumneavoastr
n George":
mysql> UPDATE elev SET nume="George; Evident, trebuie s fii atent cu nregistrri de acest gen.
De obicei, vei fi mai concret n ceea ce privete nregistrrile pe care le actualizai. S presupunem c ai
adugat recent un membru al Ligii istorice, dar ai completat numai cteva coloane din rubrica sa:
mysql> INSERT membru (nume,prenume)
-> VALUES('lonescu'.'Vasile');
Apoi, v dai seama c ai uitat s menionai data plii cotizaiei. Putei remedia acest neajuns dup cum
urmeaz: mysql> UPDATE membru
-> SET data_expirare='2001-7-20'
-> WHERE nume='lonescu' AND prenume='Vasile'
Putei actualiza mai multe coloane simultan. Instruciunea urmtoare actualizeaz adresa potal i de e-mail a
lui Vasile: mysql> UPDATE membru
-> SET email ='ivasiledyahoo.corn',
-> strada='123 Str. Lunga',oras='Nicieri',
90 Partea l Utilizarea general a sistemului MySQL
-> stat='NY',cod_postal='01003l
-> WHERE nume='lonescu' AND prenume='Vasile';
De asemenea, putei anula" valoarea unei coloane atribuindu-i acesteia valoarea NULL (presupunnd c acea
coloan accept valori NULL). Dac la un anumit moment n viitor Vasile se decide s plteasc acea cotizaie
mare care i permite s devin membru pe via", i putei modifica nregistrarea n mod adecvat atribuind datei
de expirare valoarea NULL (n sensul c nu expir niciodat"): mysql> UPDATE membru
-> SET data_expirare=NULL
-> WHERE nume='lonescu1 AND prenune='Vasile';
n cazul instruciunii UPDATE, ca i pentru DELETE, este bine s testai o clauz WHERE folosind o
instruciune SELECT, pentru a v asigura c alegei nregistrrile corecte pentru actualizare, n cazul n care
criteriile dumneavoastr de selecie sunt prea nguste sau prea largi, vei actualiza prea puine, respectiv prea
multe nregistrri.
Dac ai ncercat interogrile din aceast seciune, vei fi ters i modificat nregistrri din tabelele bazei de date
samp_db. nainte de a trece la seciunea urmtoare, trebuie s anulai aceste modificri. Facei aceasta prin
rencrcarea tabelelor folosind instruciunile de la sfritul seciunii Adugarea de noi nregistrri".
Modificarea structurii tabelelor
V mai amintii cnd am creat tabelul membru al Ligii istorice fr o coloan a identificatorului numeric al
membrilor, ca pretext pentru a folosi instruciunea ALTER TABLE? Este momentul s folosim aceast
instruciune. Cu ajutorul instruciunii ALTER TABLE, putei redenumi tabele, aduga sau terge coloane,
modifica tipuri de coloane i altele. Singurul exemplu pe care l voi prezenta aici este modalitatea de a aduga o
coloan nou. Vezi capitolul 3 pentru mai multe detalii despre posibilitile instruciunii ALTER TABLE.
Considerentul principal la adugarea unei coloane cu identificatorul numeric al membrilor la tabelul membru
este acela c valorile trebuie s fie unice, pentru a se evita confuzia ntre rubrici. Aici este util o coloan
AUTO_INCREMENT, deoarece putem permite programului MySQL s genereze automat numere unice atunci
cnd adugm membri noi. ntr-o instruciune CREATE TABLE, specificaia pentru o asemenea coloan ar arta
astfel:
membru_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY Pentru instruciunea ALTER
TABLE, sintaxa este similar. Rulai aceast interogare pentru a aduga coloana:
mysql> ALTER TABLE membru
-> ADD membru_id INT UNSIGNED NOT NULL AUTO_INCREMENT -> PRIMARY KEY;
Acum, cnd avem o nou coloan pentru memorarea identificatorilor numerici ai membrilor, cum repartizm
numere nregistrrilor existente din tabelul membru? Simplu; MySQL s-a ocupat deja de asta! Cnd adugai o
coloan la un tabel, MySQL iniializeaz valorile coloanelor cu valoarea prestabilit, n cazul unei coloane
AUTO_INCREMENT, aceasta determin generarea unui nou numr din secven pentru fiecare rnd.
Capitolul 1 Introducere n MySQL i SQL
91
Sugestii pentru interaciunea cu mysql
Aceast seciune discut despre modul de a interaciona cu programul client mysql ntr-o manier mai eficient i
cu mai puin text introdus de la tastatur. Este descris un mod mai simplu de conectare la server i metode de
introducere a interogrilor fr a o tasta pe fiecare de la nceput pn la sfrit.
Simplificarea procesului de conexiune
Probabil c trebuie s specificai parametri de conexiune precum numele gazdei, numele de utilizator sau parola
atunci cnd invocai mysql. Pentru simpla rulare a unui program trebuie introdus o cantitate serioas de text,
lucru care devine foarte repede obositor. Exist numeroase metode pentru simplificarea procesului de conectare,
prin reducerea la minimum a textului introdus de la tastatur:
Utilizai un fiier cu opiuni pentru stocarea parametrilor de conectare.
Repetai comenzile beneficiind de caracteristicile interpretorului dumneavoastr de memorare a comenzilor
(istoric).
Definii o scurttur pentru linia de comand mysql folosind un alias sau un script de interpretor.
Utilizarea unui fiier cu opiuni
ncepnd de la versiunea 3.22, MySQL v permite s stocai parametri de conexiune ntr-un fiier cu opiuni.
Apoi, nu mai trebuie s tastai parametri de fiecare dat cnd rulai mysql; acetia sunt folosii ca i cum i-ai fi
introdus n linia de comand. Parametrii sunt de asemenea folosii i de ctre alte programe client MySQL,
precum mysqlimport. Aceasta nseamn c un fiier cu opiuni reduce cantitatea de text introdus atunci cnd
folosii i aceste programe.
Pentru a folosi fiierul cu opiuni n vederea specificrii parametrilor de conexiune, creai un fiier denumit
-/.my.cnf (adic un fiier denumit .my.cnf n catalogul dumneavoastr de baz). Un fiier cu opiuni este un fiier
cu text simplu, deci l putei crea folosind orice editor de texte. Coninutul fiierului se prezint astfel:
[client]
host=gaz(/a_serverului
user=numele_dumneavoastr
password=parola_dumneavoastr
Linia [client] indic nceputul grupului cu opiuni pentru programul client; toate liniile care urmeaz dup
aceasta sunt linii citite de ctre programele client MySQL pentru a obine valorile opiunilor, pn la sfritul
fiierului sau pn la nceputul unui grup de parametri diferit, nlocuii gazda_serverului, numele_dumneavoastra
si parola_dum-neavoastra cu numele gazdei, numele de utilizator i parola pe care le specificai cnd v conectai
la server. Pentru mine, fiierul . my. cnf se prezint astfel
[client]
host=pit-viper.snake.net
user=paul
password=secret
92 Partea l Utilizarea general a sistemului MySQL
Singura linie obligatorie este [client]. Liniile care definesc valorile parametrilor sunt opionale; le putei specifica
numai pe cele dorite. De exemplu, dac numele dumneavoastr de utilizator MySQL este acelai cu numele
UNIX de deschidere a sesiunii de lucru, atunci nu trebuie s includei o linie user.
Dup ce ai creat fiierul .my .cnf, stabilii pentru modul su de acces o valoare restrictiv, pentru a v asigura c
nimeni altcineva nu poate s-1 citeasc:
% chmod 600 .ray,cnf
Sub Windows, coninutul fiierului cu opiuni este acelai, dei numele este diferit (C: \my.cnf), iar
dumneavoastr nu invocai comanda chmod.
Deoarece fiierele cu opiuni au fost adugate la MySQL dect ncepnd cu versiunea 3.22, nu le putei folosi cu
versiunile anterioare, n particular, nu putei folosi un fiier cu opiuni sub Windows la clienii inclui n
distribuia shareware a sistemului MySQL, deoarece aceea se bazeaz pe MySQL 3.21. Fiierele cu opiuni sunt
compatibile cu versiunea Windows nregistrat a sistemului MySQL, sau v putei procura programe client mai
recente, compatibile cu fiierele cu opiuni, din situl Web MySQL.
Despre fiierele cu opiuni se pot obine mai multe informaii n Anexa E, Referin de program MySQL".
Utilizarea istoricului de comenzi al interpretorului
Interpretoare precum csh, tcsh si bash rein comenzile dumneavoastr ntr-o list istoric i v permit sa repetai
comenzi din lista respectiv. Dac folosii un asemenea interpreter, lista dumneavoastr istoric v poate ajuta s
evitai tastarea unor ntregi comenzi. De exemplu, daca ai invocat programul mysql recent, l putei reexecuta
dup cum urmeaz:
% l my
Caracterul ! indic interpretorului s caute n istoricul de comenzi pentru a gsi cea mai recent comand care
ncepe cu my i s o re-execute ca i cum dumneavoastr ai fi rein-trodus-o de la tastatur. De asemenea, unele
interpretoare v permit s v deplasai n sus si n jos n lista istoric folosind tastele cu sgei orientate n sus,
respectiv n jos (sau poate combinaiile de taste Ctrl-P i Ctrl-N). Putei selecta n acest mod comanda dorit i
apoi apsai pe Enter pentru a o executa, tcsh i bash au aceast caracteristic, posibil existent i la alte
interpretoare. Examinai documentaia interpretorului dumneavoastr pentru a afla mai multe detalii despre
utilizarea listei istoric.
Utilizarea aliasurilor i a scripturilor de interpreter
Dac interpretorul dumneavoastr permite atribuirea unui alias, putei configura scurtturi de comenzi care v
permit s invocai o comand lung prin tastarea unui nume scurt. De exemplu, n csh sau tcsh, putei folosi
comanda alias pentru a configura un alias denumit samp_db, cum este acesta:
alias samp_db 'mysql -h pit-viper.snake.net -u -paul -p samp_db' Sintaxa pentru bash este uor diferit:
alias samp_db='mysql -h pit-viper.snake.net -u -paul -p samp_db' Definirea unui alias face aceste dou
comenzi echivalente:
samp_db
mysql -h pit-viper.snake.net -u -paul -p samp_db
Capitolul 1 Introducere n MySQL i SQL 93
Evident, prima comand este mai uor de introdus dect a doua. Pentru ca aliasul s aib efect de fiecare dat
cnd deschidei sesiunea de lucru, plasai comanda alias ntr-unul din fiierele de pornire ale interpretorului
dumneavoastr (de exemplu .cshrc pentru csh sau .bash_profile pentru bash).
Un alt tip de scurttur este crearea unui script de interpreter care execut mysql automat, cu opiunile adecvate,
n UNIX, un fiier script echivalent cu aliasul samp_db prezentat anterior arat astfel:
#! /bin/sh
exec mysql -h pit-viper.snake.net -u -paul -p samp_db
Dac denumesc scriptul samp_db i l transform ntr-un executabil (folosind comanda chmod +x samp_db), pot
tasta samp_db pentru a rula mysql i pentru a m conecta la baza mea de date.
Sub Windows, n aceleai scopuri se poate folosi un fiier batch, avnd extensia .bat si coninnd comenzi
executabile fr intervenia utilizatorului. Denumii fiierul samp_db.bat i inserai n fiier o linie ca aceasta:
mysql -h pit-viper.snake.net -u -paul -p samp_db
Acest fiier batch poate fi rulat fie tastnd samp_db la promptul dintr-o consol DOS, fie executnd dublu clic pe
pictograma sa din Windows.
Dac obinei acces la mai multe baze de date sau v conectai la mai multe gazde, putei defini mai multe
aliasuri sau scripturi, fiecare din acestea invocnd mysql cu opiuni diferite.
Emiterea de interogri cu o cantitate mai mic de text introdus de la tastatur
mysql este un program extrem de util pentru interaciunea cu baza dumneavoastr de date, dar interfaa sa este
ideal pentru interogri scurte, de un rnd. mysql nu este interesat dac o interogare se extinde pe mai multe
rnduri, desigur, dar nu este prea amuzant s tastezi interogri lungi. Introducerea unei interogri, chiar i a uneia
scurte, nu este nici ea prea distractiv, dac descoperi c trebuie s o tastezi din nou datorit unei erori de
sintax.
Exist numeroase tehnici pe care le putei utiliza pentru evitarea unor introduceri i reintroduceri inutile de text:
Folosii caracteristica de editare a liniei de intrare din mysql.
Utilizai copierea i lipirea.
Rulai mysql n mod batch.
Evitai s introducei instruciuni INSERT, prin utilizarea datelor existente pentru crearea de noi nregistrri.
Utilizarea editorului liniilor de intrare din mysql
n mysql este ncorporat biblioteca GNU Readline, care permite editarea liniilor de intrare. Putei manipula linia
pe care o introducei la un moment dat sau putei relua liniile introduse anterior i le putei re-introduce, fie ca
atare, fie dup o modificare ulterioar. Acest lucru este convenabil cnd introducei o linie si observai o greeal
de
94
Partea l Utilizarea general a sistemului MySQL
introducere a textului; putei reveni n interiorul liniei pentru a corecta problema nainte de a apsa pe tasta Enter.
Dac introducei o interogare care conine o greeal, putei relua interogarea i o putei edita pentru a remedia
problema, dup care o retrimitei. (Acest lucru este cel mai uor de fcut dac tastai ntreaga interogare pe o
singur linie.)
Unele dintre secvenele de editare pe care le vei gsi utile sunt prezentate n tabelul 1.4, dar exist multe
comenzi de editare a liniei de intrare n afara celor prezentate n tabel. Putei gsi o versiune electronic a
manualului Readline prin consultarea motorului dumneavoastr preferat de cutare n Internet. Manualul este de
asemenea inclus n distribuia Readline, disponibil n situl Web al proiectului GNU, la adresa http: /
/www.gnu .org/.
Tabelul 1.4 Comenzi mysql de editare a liniei de intrare
Secven de taste
Sgeat sus, Ctrl-P
Sgeat jos, Ctrl-N
Sgeat stnga, Ctrl-B
Sgeat dreapta, Ctrt-F
Esc Ctrl-B
Esc Ctrl-F
Ctrl-A
Ctrl-E
Ctrl-D
Delete
Esc D
Esc Backspace
Ctrt-K
Ctrl-
Semnificaie
Reluarea liniei anterioare Reluarea liniei ulterioare Deplasarea cursorului la stnga (napoi) Deplasarea
cursorului la dreapta (nainte) Deplasare napoi cu un cuvnt Deplasare nainte cu un cuvnt Deplasarea
cursorului la nceputul liniei Deplasarea cursorului la sfritul liniei tergerea caracterului aflat sub cursor
tergerea caracterului din stnga cursorului tergerea cuvntului
tergerea cuvntului din stnga cursorului terge tot, de la cursor la sfritul liniei Anuleaz ultima modificare;
se poate repeta
Exemplul urmtor descrie o utilizare simpl pentru editarea liniei de intrare. S presupunem c ai introdus
aceast interogare n timp ce utilizai mysql:
mysql> SHOW COLUMNS FROM persedinte;
Dac observai c n loc de preedinte" ai scris peredinte", nainte de a apsa pe tasta Enter, apsai tasta
sgeat stnga sau combinaia de taste Ctrl-B de cteva ori pentru a deplasa cursorul la stnga, pn cnd ajunge
la litera s. Apoi apsai de dou ori pe tasta Delete pentru a terge caracterele e r, tastai re pentru a remedia
eroarea i apsai pe tasta Enter pentru a emite interogarea. Dac apsai pe tasta Enter nainte de a sesiza
eroarea, nu este nici o problem. Dup ce mysql i afieaz mesajul de eroare, apsai pe tasta sgeat sus sau pe
combinaia de taste Ctrl-P pentru a relua linia, dup care o editai aa cum am artat mai sus.
Editarea liniilor de intrare nu este disponibil n versiunea Windows a programului mysql, dar v putei procura
distribuia client gratuit cygwin_32 din situl Web MySQL. Programul mysqlc din acea distribuie este similar cu
mysql, dar nelege comenzile de editare a liniei de intrare.
Capitolul 1 Introducere n MySQL i SQL
95
Utilizarea copierii i a lipirii pentru emiterea de interogri
Dac lucrai ntr-un mediu cu ferestre, putei salva textul interogrilor care vi se par utile ntr-un fiier i putei
folosi operaiile de copiere i lipire pentru a emite cu uurin aceste interogri. Pur si simplu respectai
urmtoarea procedur:
1. Invocai mysql ntr-o fereastr Telnet sau ntr-o fereastr de consol DOS.
2. Deschidei fiierul care conine interogrile dumneavoastr ntr-o fereastr document. (De exemplu, eu
folosesc BBEdit sub Mac OS, respectiv vi ntr-o fereastr xterm sub X Window System n UNIX.)
3. Pentru a executa o interogare stocat n fiierul dumneavoastr, selectai-o i copiai-o. Apoi, comutai n
fereastra dumneavoastr Telnet sau n consola DOS i lipii interogarea n MySQL.
Procedura pare cam stngace descris pe hrtie, dar este o modalitate rapid de a introduce interogri rapid i
fr a mai scrie nimic atunci cnd o folosii efectiv.
De asemenea, aceast tehnic v permite s v editai interogrile n fereastra document, precum i s construii
interogri noi prin copierea si lipirea componentelor interogrilor existente. De exemplu, dac selectai frecvent
rnduri dintr-un anumit tabel, dar dorii s vedei datele de ieire sortate n diferite moduri, putei folosi o list cu
diferite clauze ORDER BY n fereastra dumneavoastr document, dup care o copiai i o lipii pe aceea pe care
dorii s o utilizai pentru orice interogare specific.
Putei folosi copierea i lipirea i n cealalt direcie (de la Telnet ctre fiierul dumneavoastr cu interogri).
Cnd introducei linii n mysql, acestea sunt salvate ntr-un fiier denumit .mysqljiistory din catalogul
dumneavoastr de baz. Dac introducei manual o interogare pe care dorii s o salvai pentru a o consulta
ulterior, prsii programul mysql, deschidei . mysql_history ntr-un editor, apoi copiai si lipii interogarea din
fiierul .mysql_history n fiierul care conine interogarea.
Rularea programului mysql n mod batch
Nu este necesar rularea interactiv a programului mysql; acest program poate citi un fiier n mod non-
interactiv (batch). Acest mod este util pentru interogri pe care le rulai periodic, deoarece nu dorii, evident, s
reintroducei de la tastatur o asemenea interogare de fiecare dat cnd o rulai. Este mai uor s inserai o dat
interogarea ntr-un fiier, dup care s cerei programului mysql s execute coninutul fiierului conform
necesitilor.
S presupunem c averi o interogare care gsete pe membrii Ligii istorice interesai de o anumit perioad din
istoria Statelor Unite, cutnd n coloana interese a tabelului membru. De exemplu, pentru a-i gsi pe membrii
interesai n perioada de criz a anilor '30, interogarea trebuie scris astfel (reinei caracterul punct si virgul de
la sfritul instruciunii, pentru ca mysql s poat sesiza locul unde se ncheie aceasta):
SELECT nume, prenume, email, interese FROM membru
WHERE interese LIKE "%criza%"
ORDER BY nume, prenume;
Plasai interogarea ntr-un fiier denumit interese. sql, apoi rulai interogarea furniznd fiierul programului
mysql, astfel:
% mysql samp_db < interese.sql
96 Partea l Utilizarea general a sistemului MySQL
n mod prestabilit, mysql genereaz date de ieire ntr-un format delimitat prin tabula-tori atunci cnd este rulat
n mod grup. Dac dorii s obinei acelai format tabular atunci cnd rulai mysql n mod interactiv, folosii
opiunea -t:
% mysql -t samp_db < interese.sql Dac dorii s salvai datele de ieire, redirecionai-le spre un fiier:
% mysql -t samp_db < interese.sql > fisier_iesire
Pentru a folosi interogarea n scopul de a gsi membri interesai de personalitatea lui Thomas Jefferson, putei
edita fiierul cu interogarea pentru a nlocui criza cu Jefferson, dup care rulai mysql din nou. Aceast metod
funcioneaz atta timp ct nu folosii interogarea foarte frecvent. Dac o folosii foarte frecvent, atunci este
necesar o alt metod. O modalitate de a spori flexibilitatea interogrii este de a o insera ntr-un script de
interpreter care preia un argument din linia de comand a scriptului i o folosete pentru a modifica textul
interogrii. Astfel, interogarea devine parametrizat i v permite s specificai cuvntul cheie care arat
domeniul de interes atunci cnd rulai scriptul. Pentru a vedea modul de funcionare al acestei metode, scriei un
mic script de interpreter, denumit interese.sh:
#1 /bin/sh
if [ $# -ne 1 J; then echo "Rog specificai un cuvnt cheie"; exit; fi
mysql -t samp_db QUERY_INPUT
SELECT nume, prenume, email, interese FROM membru
WHERE interese LIKE "%$1%"
ORDER BY nume, prenume;
QUERY_INPUT
Cea de-a doua linie se asigur c exist un cuvnt cheie n linia de comand; afieaz un scurt mesaj i ncheie
execuia programului n caz contrar, ntreg textul cuprins ntre QUERY_INPUT i linia QUERY_INPUT final
se transform n date de intrare pentru mysql. n cadrul textului interogrii, interpretorul nlocuiete referina la
$1 cu cuvntul cheie din linia de comand. (In scripturile de interpreter, $1, $2... se refer la argumentele
comenzii.) Acest fapt determin interogarea s reflecte cuvntul cheie pe care l specificai n linia de comand
cnd rulai scriptul.
nainte de a putea rula scriptul, trebuie s-1 facei executabil:
% chmod +x interese.sh
Acum, nu mai trebuie s editai scriptul de fiecare dat cnd l rulai. Pur si simplu indicai direct n linia de
comand ce anume cutai:
% interese.sh criza
% interese.sh Jefferson
Crearea de noi nregistrri folosind date existente
Se pot aduga noi nregistrri ntr-un tabel, rnd cu rnd, folosind instruciunea INSERT dar, dup crearea
ctorva nregistrri prin tastarea manual a instruciunilor INSERT, majoritatea dintre noi suntem convini c
trebuie s existe i o metod mai bun de a executa aceast operaie. O alternativ este utilizarea unui fiier care
conine numai valori de date si apoi ncrcarea de nregistrri din acel fiier folosind instruciunea LOAD DATA
sau utilitarul my sql import.
Capitolul 1 Introducere n MySQL i SQL
97
Deseori, creai fiierul de date folosind date care deja exist ntr-un alt format. Informaiile dumneavoastr pot fi
coninut ntr-un program de calcul tabelar sau poate c se afl ntr-o alt baz de date i dorii s le transferai
ctre MySQL. Pentru a nu complica aceast discuie, voi presupune c datele dumneavoastr se afl ntr-o foaie
de calcul tabelar din calculatorul dumneavoastr de birou.
Pentru a transfera datele din foaia de calcul din calculatorul dumneavoastr ntr-un fiier din contul
dumneavoastr UNIX, putei folosi tehnica de copiere i lipire, alturi de Telnet. Iat cum procedai:
1. Deschidei o conexiune Telnet spre contul dumneavoastr UNIX. Sub Mac OS, putei folosi o aplicaie
precum BetterTelnet sau NCSA Telnet. Sub Windows, putei folosi programul Telnet standard.
2. Deschidei foaia de calcul tabelar, selectai blocul de date pe care dorii s-1 transferai i copiai-1.
3. n fereastra Telnet, tastai urmtoarea comand pentru a ncepe capturarea datelor n fisieruldata.txt:
% cat > data.txt
Comanda cat ateapt datele de intrare.
4. Lipii datele pe care le-ai copiat din foaia de calcul n fereastra Telnet. Programul cat crede c introducei
personal informaiile si le scrie ndatoritor n fiierul data.txt.
5. Dup ce toate datele lipite au fost scrise n fiier, apsai pe tasta Enter n cazul n care cursorul ajunge la
sfritul unei linii de date, nu la nceputul unei linii noi. Apoi, apsai pe combinaia de taste Ctrl-D pentru a
indica sfritul fiierului". Programul cat nceteaz s mai atepte date de intrare i nchide fiierul.
n acest moment, avei un fiier data.txt care conine blocul de date pe care 1-ai selectat n foaia dumneavoastr
de calcul tabelar i care este gata de a fi ncrcat n baza dumneavoastr de date cu LOAD DATA sau
mysqlimport.
Copierea i lipirea reprezint o metod rapid si simpl de a transfera date ntr-un fiier UNIX, dar este mai
adecvat pentru seturi mai mici de date. Cantitile mai mari de date pot depi limitele bufferului de copiere al
sistemului dumneavoastr, n asemenea cazuri, se recomand salvarea foii de calcul tabelar n format text simplu
(delimitat prin tabulator!). Apoi, putei transfera fiierul din calculatorul dumneavoastr n contul UNIX folosind
FTP. Transferai fiierul n mod text (nu n mod binar sau imagine), astfel nct caracterele sfrit de rnd s fie
convertite n caractere UNIX de sfrit de rnd. (UNIX folosete caractere salt la linie nou, Mac OS folosete
caractere retur de car, iar Windows folosete perechea de caractere retur de car-salt la linie nou.) Putei indica
instruciunii LOAD DATA sau programului mysqlimport tipul caracterului sfrit de rnd pe care s-1 atepte,
dar n UNIX este mai uor de lucrat cu fiierul dac acesta conine caractere de salt la linie nou.
Dup transferul fiierului, este bine s verificai dac are sau nu rnduri vide la sfrit. Dac are, trebuie s le
tergei, deoarece altfel se vor transforma n nregistrri vide sau deformate atunci cnd ncrcai fiierul n baza
de date.
98 Partea l Utilizarea general a sistemului MySQL
n fiierele salvate n format text simplu dintr-o foaie de calcul tabelar, valorile care conin spaii pot fi delimitate
prin ghilimele. Pentru a elimina ghilimelele atunci cnd ncrcai fiierul n baza dumneavoastr de date, folosii
clauza FIELDS ENCLOSED BY pentru instruciunea LOAD DATA, respectiv opiunea --fields-enclosed-by
pentru mysqlimport. Vezi informaiile despre instruciunea LOAD DATA din Anexa D pentru a obine mai multe
detalii.
De aici, ncotro?
Acum tii destule despre MySQL. Putei configura o baz de date si crea tabele. Putei insera nregistrri n
aceste tabele, le putei regsi n diverse moduri, le putei modifica sau terge. Dar mai avei nc multe de nvat
despre MySQL; manualul din acest capitol a reprezentat numai o mic introducere. Putei vedea acest lucru
examinnd starea bazei noastre de date exemplu. Am creat baza de date i tabelele sale i am populat-o cu unele
date iniiale. Pe parcursul acestui proces am vzut modul de scriere al unora dintre interogrile de care avem
nevoie pentru a rspunde la ntrebri privind informaiile din baza de date. Mai sunt, ns, multe de fcut...
De exemplu, nu dispunem de nici o modalitate interactiv convenabil de a introduce noi nregistrri de punctaje
n cadrul proiectului de eviden a rezultatelor colare, respectiv nregistrri cu noii membri n catalogul Ligii
istorice. Nu avem nici o metod convenabil de a edita nregistrrile existente. i tot nu putem genera
formularele tiprite sau n format electronic pentru catalogul Ligii. Aceste sarcini, precum i altele, vor fi
abordate din nou n capitolele urmtoare, mai ales n capitolele 7, Interfaa API pentru Perl DBI", respectiv 8,
Interfaa API pentru PHP".
Drumul pe care vei merge n continuare printre paginile acestei cri depinde de domeniul dumneavoastr de
interes. Dac dorii s vedei modul n care am finalizat proiectele legate de Liga istoric i de evidena
rezultatelor colare, Partea a Il-a se refer la programarea n MySQL. Dac vei ndeplini funcia de
administrator MySQL pentru situl dumneavoastr, Partea a IlI-a a volumului de fa trateaz despre sarcinile
administrative. Totui, eu v recomand s acumulai mai nti cunotine suplimentare de ordin general despre
utilizarea sistemului MySQL, citind celelalte capitole din Partea I. Aceste capitole discut despre modul de
manipulare a datelor n MySQL, furnizeaz informaii suplimentare despre sintax i despre utilizarea
instruciunilor de interogare i v prezint modaliti de rulare mai rapid a interogrilor. O baz solid de
cunotine legate de aceste subiecte v va fi de folos indiferent de contextul n care folosii MySQL: rulai
programul mysql, v scriei propriile programe sau ndeplinii atribuiile unui adminir trator de baze de date.
CAPITOLUL 2
Lucrul cu date n MySQL i SQL
Practic, tot ceea ce facei n MySQL implic, ntr-un fel sau altul, date, deoarece rostul unui sistem de gestiune a
bazelor de date este, prin definiie, acela de gestiune a datelor. Chiar si o simpl instruciune SELECT 1 implic
o evaluare a unei expresii, cu scopul de a produce o valoare a unei date ntregi.
Fiecare valoare a unei date din MySQL are un tip. De exemplu, 37.4 este un numr, iar "abc" este un ir. Uneori,
tipurile de date sunt explicite, ca atunci cnd emitei o instruciune CREATE TABLE care specific tipul fiecrei
coloane pe care o declarai ca parte a tabelului:
CREATE TABLE tabelul meu
int_col INT, /"
sir_col CHAR(20), /' data col DATE /"
coloana cu valori ntregi */ coloana cu valori ir */ coloana cu valori date */
n alte situaii, tipurile de date sunt implicite, cum este atunci cnd facei referire la valori literale dintr-o
expresie, cnd transferai valori unei funcii sau cnd folosii valoarea retur-nat din acea funcie:
INSERT INTO tabeluljneu (int_col,sir_col,data_col)
VALUES(14,CONCAT("a","b"),19990115)
Aceast instruciune INSERT efectueaz urmtoarele operaii, din care toate implic tipuri de date:
Atribuie valoarea 14 coloanei ntregi1 int_col.
Transfer valorile ir "a" si "b" funciei CONCAT(). Aceast funcie returneaz valoarea ir "ab", care este
repartizat n coloana ir sir_col.
Atribuie valoarea ntreag 19990115 coloanei de tip dat data_col. Atribuirea implic o neconcordan ntre
tipuri, deci MySQL convertete irul 19990115 n data "1999-01-15"; acest fapt arat c MySQL execut
conversia automat a tipului.
Pentru a folosi MySQL n mod eficient, este esenial s nelegei modul de manipulare a datelor n MySQL.
Acest capitol descrie tipurile de date pe care le poate manipula MySQL i discut problemele implicate de lucrul
cu aceste tipuri:
1 Prin coloan ntreag se va nelege coloan care conine valori numere ntregi. S-a preferat n traducere prima
form, din motive de concizie. La fel de va proceda cu expresii gen coloan ir i altele. - N.T.