Sunteți pe pagina 1din 16

III.

Bazele MySQL - Interogari din tabele multiple


Tabelul pet tine evidenta animalelor pe care le ai. Daca doresti sa inregistrezi alte informatii despre ele, cum ar fi evenimente din viata lor, precum vizitele la veterinar sau data la care li se nasc puii, foloseste un alt tabel. Cum ar trebui sa arate acest tabel? El va trebui sa: ?Contina numele animalului de casa caruia ii corespunde fiecare eveniment. ?O data, pentru a sti cand s-a petrecut evenimentul. ?Un camp pentru a descrie evenimentul. ?Un camp care sa desemneze tipul evenimentului, daca doresti sa poti clasifica evenimentele. Avand in vedere toate aceste considerente, instructiunea CREATE TABLE pentru tabelul event ar putea arata astfel:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, -> type VARCHAR(15), remark VARCHAR(255));

Ca si in cazul tabelului pet, cel mai convenabil este sa incarci datele initiale creand un fisier text tab-delimited care sa cuprinda urmatoarele informatii: name Fluffy Buffy Buffy Chirpy Slim Bowser Fang Fang Claws Whistler date 1995-05-15 1993-06-23 1994-06-19 1999-03-21 1997-08-03 1991-10-12 1991-10-12 1998-08-28 1998-03-17 1998-12-09 type litter litter litter vet vet kennel kennel birthday birthday birthday Gave him a new chew toy Gave him a new flea collar First birthday remark 4 kittens, 3 female, 1 male 5 puppies, 2 female, 3 male 3 puppies, 3 female needed beak straightened broken rib

Incarca inregistrarile astfel:


mysql> LOAD DATA LOCAL INFILE 'event.txt' INTO TABLE event;

Bazandu-te pe ceea ce ai invatat din interogarile pe care le-ai rulat pe tabelul pet, ar trebui sa fii capabil sa efectuezi extrageri de date din tabelul event; principiile de baza raman aceleasi. Dar care sunt cazurile in care tabelul event, de unul singur, este insuficient pentru a raspunde intrebarilor pe care i le-ai putea adresa? Sa presupunem ca doresti sa afli varstele la care fiecare animal de casa si-a fatat puii. Am vazut mai devreme modul in care se calculeaza varstele pornind de la data nasterii. Data la care mama si-a fatat puii se afla in tabelul event, insa, pentru a calcula varsta pe care o avea la acea data, ai nevoie de ziua ei de nastere, care este stocata in tabelul pet. Acest lucru inseamna ca interogarea necesita ambele tabele:
mysql> SELECT pet.name, -> (YEAR(date)-YEAR(birth)) - (RIGHT(date,5)<RIGHT(birth,5)) AS age, -> remark -> FROM pet INNER JOIN event -> ON pet.name = event.name -> WHERE event.type = 'litter'; +--------+------+-----------------------------+ | name | age | remark | +--------+------+-----------------------------+ | Fluffy | 2 | 4 kittens, 3 female, 1 male | | Buffy | 4 | 5 puppies, 2 female, 3 male | | Buffy | 5 | 3 puppies, 3 female | +--------+------+-----------------------------+

Ar fi mai multe lucruri care trebuie aduse in atentie in legatura cu acesta interogare: ?Clauza FROM uneste cele doua tabele, intrucat interogarea are nevoie sa isi extraga informatii din ambele. ?In momentul combinarii informatiilor apartinand mai multor tabele, trebuie sa specifici modul in care inregistrarile dintr-un tabel pot fi asociate inregistrarilor din celalalt. Acest lucru este simplu, deoarece ambele au cate o coloana name. Interogarea foloseste o clauza ON pentru a face o corespondenta intre inregistrarile din cele doua tabele care se bazeaza pe valorile name. Interogarea foloseste un INNER JOIN pentru a uni tabelele. Un INNER JOIN permite randurilor din oricare tabel sa apara in rezultat daca si numai daca ambele tabele intrunesc conditiile specificate in clauza ON. In exemplul de fata, clauza ON impune coloanei name din tabelul pet sa corespunda coloanei name din tabelul event. Daca un nume apare intr-un tabel dar nu si in celalalt, randul respectiv nu va aparea in rezultat, deoarece conditia din clauza ON esueaza. ?Intrucat coloana name apare in ambele tabele, trebuie sa precizezi cu exactitate la care tabel te raportezi atunci cand mentionezi coloana. Acest lucru se realizeaza antepunand numele tabelului numelui coloanei. Nu ai neaparat nevoie de doua tabele pentru a efectua o combinare. Uneori este util sa unesti un tabel cu el insusi, in cazul in care doresti sa compari inregistrarile dintr-un tabel cu alte inregistrari, din acelasi tabel. De exemplu, pentru a gasi perechi care sa dea nastere la pui printre animalele de casa, poti uni tabelul pet cu sine insusi pentru a returna perechi mascul-femela apartinand unor specii similare:

mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species -> FROM pet AS p1 INNER JOIN pet AS p2 -> ON p1.species = p2.species AND p1.sex = 'f' AND p2.sex = 'm'; +--------+------+--------+------+---------+ | name | sex | name | sex | species | +--------+------+--------+------+---------+ | Fluffy | f | Claws | m | cat | | Buffy | f | Fang | m | dog | | Buffy | f | Bowser | m | dog | +--------+------+--------+------+---------+

In aceasta interogare, vom specifica un alias pentru numele tabelului pentru a ne referi la coloane si pentru a afla exact carui element din tabel ii este asociata fiecare referinta din coloana.

Instructiunea SELECT se foloseste pentru a extrage informatii dintr-un tabel. Forma generala a instructiunii este: SELECT ce coloane selectam FROM din ce tabel WHERE in ce conditii; Ce coloane selectam iti indica ceea ce vrei sa vizualizezi. Acest lucru poate fi o lista de coloane, sau * pentru a indica ? toate coloanele.?Din ce tabel se refera la tabelul din care doresti sa extragi date. Clauza WHERE este optionala. In cazul in care apare, in ce conditii specifica una sau mai multe conditii pe care trebuie sa le intruneasca randurile pentru a fi extrase. Cea mai simpla forma de SELECT extrage toate informatiile dintr-un tabel:
mysql> SELECT * FROM pet; +----------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+--------+---------+------+------------+------------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Fang | Benny | dog | m | 1990-08-27 | NULL | | Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 | | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+--------+---------+------+------------+------------+

Aceasta forma de SELECT este utila daca doresti sa iti verifici intregul tabel, de exemplu, dupa ce tocmai l-ai incarcat cu primul set de date. De exemplu, se poate intampla sa constati ca data de nastere a lui Bowser nu este tocmai in regula. In clipa in care consulti documentele originale de descendenta, afli ca anul corect al nasterii ar trebui sa fie 1989, si nu 1979. Exista cel putin doua moduri de a rectifica aceasta eroare: ?Editeaza fisierul pet.txt pentru a corecta eroarea, iar apoi goleste tabelul si incarca-l din nou folosind DELETE si LOAD DATA:
mysql> DELETE FROM pet; mysql> LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE pet;

Totusi, procedand astfel, va trebui de asemenea sa introduci din nou si inregistrarea corespunzatoare lui Puffball.

?Rectifica doar inregistrarea eronata cu o instructiune UPDATE:


mysql> UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';

UPDATE va schimba numai inregistrarea in cauza si nu necesita reincarcarea tabelului. Dupa cum am aratat in sectiunea precedenta, este mai usor sa citim toate datele dintr-un tabel intreg. Este suficienta omiterea clauzei WHERE din instructiunea SELECT. Insa, de regula nu vei dori sa vizualizezi intregul tabel, in special cand acesta se extinde destul de mult. In schimb, vei fi de obicei mai interesat sa raspunzi unei anumite intrebari, caz in care vei mentiona niste conditii de restrangere a informatiei dorite. Sa urmarim cateva interogari ce vor raspunde la intrebari despre animalele de casa. Poti selecta doar anumite randuri din tabelul tau. De exemplu, daca doresti sa verifici modificarea pe care ai adus-o zilei de nastere a lui Bowser, selecteaza intregistrarea lui Bowser, astfel:
mysql> SELECT * FROM pet WHERE name = 'Bowser'; +--------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+-------+---------+------+------------+------------+ | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+-------+---------+------+------------+------------+

Iesirea confirma faptul ca anul a fost intr-adevar inregistrat in forma lui corecta ca 1989, si nu ca 1979. Comparatiile intre siruri nu sunt in mod normal case-sensitive, asa ca te poti referi la nume ca 'bowser', 'BOWSER', si asa mai departe. Rezultatul interogarii va fi acelasi. Poti pune conditii asupra oricarei coloane, si nu numai asupra celei intitulate name. De exemplu, daca doresti sa stii ce animale s-au nascut in decursul anului 1998 sau dupa, testeaza coloana birth:
mysql> SELECT * FROM pet WHERE birth >= '1998-1-1'; +----------+-------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+-------+ | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+-------+---------+------+------------+-------+

Poti combina conditiile, de exemplu, pentru a localiza cainii-femela:


mysql> SELECT * FROM pet WHERE species = 'dog' AND sex = 'f'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+

Instructiunea anterioara foloseste operatorul logic AND. Exista de asemenea si un operator OR:
mysql> SELECT * FROM pet WHERE species = 'snake' OR species = 'bird'; +----------+-------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+-------+ | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | +----------+-------+---------+------+------------+-------+

AND si OR pot fi utilizati in orice ordine, cu toate ca AND are de obicei o mai mare prioritate decat OR. Daca folosesti ambii operatori, este indicat sa folosesti paranteze pentru a enunta in mod explicit modul in care trebuie grupate conditiile:
mysql> SELECT * FROM pet WHERE (species = 'cat' AND sex = 'm') -> OR (species = 'dog' AND sex = 'f'); +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+

Daca nu doresti sa vizualizezi randuri intregi din tabelul tau, este suficient sa numesti coloanele care te intereseaza, separandu-le prin virgula. De exemplu, daca doresti sa stii cand s-au nascut animalele tale, selecteaza coloanele name si birth:
mysql> SELECT name, birth FROM pet; +----------+------------+ | name | birth | +----------+------------+ | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Buffy | 1989-05-13 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Puffball | 1999-03-30 | +----------+------------+

Pentru a afla cine este stapanul animalelor de casa, foloseste aceasta interogare:
mysql> SELECT owner FROM pet; +--------+ | owner | +--------+ | Harold | | Gwen | | Harold | | Benny | | Diane | | Gwen | | Gwen | | Benny | | Diane | +--------+

De remarcat ca interogarea nu face altceva decat sa extraga coloana owner din fiecare inregistrare, si astfel unii dintre ei pot aparea de mai multe ori. Pentru a minimiza numarul de iesiri, extrage fiecare iesire desemnand o inregistrare unica, adaugand cuvantul-cheie DISTINCT:
mysql> SELECT DISTINCT owner FROM pet; +--------+ | owner | +--------+ | Benny | | Diane | | Gwen | | Harold |

+--------+

Poti folosi o clauza WHERE pentru a combina selectia de rand cu selectia de coloana. De exemplu, pentru a obtine datele de nastere doar pentru caini si pisici, foloseste aceasta interogare:
mysql> SELECT name, species, birth FROM pet -> WHERE species = 'dog' OR species = 'cat'; +--------+---------+------------+ | name | species | birth | +--------+---------+------------+ | Fluffy | cat | 1993-02-04 | | Claws | cat | 1994-03-17 | | Buffy | dog | 1989-05-13 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | +--------+---------+------------+

Probabil ai remarcat in exemplele anterioare faptul ca randurile rezultate sunt afisate fara a respecta o ordine anume. De obicei este mai usor sa examinezi iesirile interogarii atunci cand randurile sunt sortate intr-un mod semnificativ. Pentru a sorta un rezultat, foloseste clauza ORDER BY. Iata aici niste date de nastere ale animalelor, sortate dupa data:
mysql> SELECT name, birth FROM pet ORDER BY birth; +----------+------------+ | name | birth | +----------+------------+ | Buffy | 1989-05-13 | | Bowser | 1989-08-31 | | Fang | 1990-08-27 | | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Slim | 1996-04-29 | | Whistler | 1997-12-09 | | Chirpy | 1998-09-11 | | Puffball | 1999-03-30 | +----------+------------+

In cadrul coloanelor de tip character, sortarea?ca orice alte operatii de comparare ?se efectueaza in mod normal in maniera case-insensitive. Acest lucru inseamna ca ordinea este nedefinita in cazul coloanelor identice, cu exceptia tipului de caracter cu care sunt scrise. Poti forta o sortare casesensitive pentru o coloana, folosind BINARY, astfel: ORDER BY BINARY nume_coloana. Ordinea in urma sortarii automate va fi crescatoare, cele mai mici valori aparand primele. Pentru a sorta in ordine inversa (descrescator), adauga cuvantul-cheie DESC langa numele coloanei dupa care sortezi:
mysql> SELECT name, birth FROM pet ORDER BY birth DESC; +----------+------------+ | name | birth | +----------+------------+ | Puffball | 1999-03-30 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Claws | 1994-03-17 | | Fluffy | 1993-02-04 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Buffy | 1989-05-13 | +----------+------------+

Poti efectua sortari dupa mai multe coloane, si poti sorta diferite coloane dupa criterii variate. De exemplu, pentru a sorta dupa tipul de animal in ordine crescatoare, iar apoi dupa data nasterii, in cadrul fiecarui tip de animal - in ordine descrescatoare (cel mai tanar animal sa fie primul), foloseste urmatoarea interogare:
mysql> SELECT name, species, birth FROM pet -> ORDER BY species, birth DESC; +----------+---------+------------+ | name | species | birth | +----------+---------+------------+ | Chirpy | bird | 1998-09-11 | | Whistler | bird | 1997-12-09 | | Claws | cat | 1994-03-17 | | Fluffy | cat | 1993-02-04 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | | Buffy | dog | 1989-05-13 | | Puffball | hamster | 1999-03-30 | | Slim | snake | 1996-04-29 | +----------+---------+------------+

Nota bene: cuvantul-cheie DESC se aplica doar numelui coloanei care il precede imediat (birth); el nu afecteaza ordinea sortarii coloanei species. MySQL asigura mai multe functii pe care le poti folosi pentru a efectua calcule pe date, pentru a calcula, de exemplu, varstele, ori pentru a extrage parti din date. Pentru a stabili cati ani are fiecare dintre animalele de casa, calculeaza diferenta dintre anul datei curente si cel al datei de nastere, iar apoi mai scade unul in cazul in care data curenta se situeaza mai devreme in calendar decat data nasterii. Urmatoarea interogare arata, pentru fiecare animal de casa, data de nastere, data curenta, si varsta in ani.
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | +----------+------------+------------+------+

Aici, YEAR() extrage partea cuprinzand anul unei date si RIGHT() extrage cele 5 caractere care se afla imediat la dreapta, reprezentand partea MM-DD (an calendaristic) a datei. Partea expresiei care compara valorile MM-DD va ajunge, prin evaluare, la 1 sau 0, ceea ce va ajusta diferenta dintre ani cu un an in cazul in care CURDATE() se situeaza mai devreme in cadrul anului fata de birth. Intreaga expresie este oarecum incomoda, asa ca se foloseste un alias (age) pentru a asocia coloanei de iesiri o eticheta mai sugestiva.

Interogarea functioneaza, insa rezultatul ar putea fi urmarit mult mai usor daca randurile ar fi prezentate intr-o anumita ordine. Acest lucru poate fi obtinut adaugand o clauza ORDER BY name pentru a sorta iesirile dupa nume:
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet ORDER BY name; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | +----------+------------+------------+------+

In vederea sortarii iesirilor dupa varsta (age) mai degraba decat dupa nume, (name), este suficient sa folosesti o clauza ORDER BY diferita:
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet ORDER BY age; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | +----------+------------+------------+------+

O interogare similara poate fi folosita pentru a determina varsta decesului, in cazul animalelor care au murit. Vei determina care anume sunt aceste animale verificand daca valoarea pentru death este NULL. Apoi, pentru cele cu valori non-NULL, calculeaza diferenta dintre valorile aferente campurilor death si birth:
mysql> SELECT name, birth, death, -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5)) -> AS age -> FROM pet WHERE death IS NOT NULL ORDER BY age; +--------+------------+------------+------+ | name | birth | death | age | +--------+------------+------------+------+ | Bowser | 1989-08-31 | 1995-07-29 | 5 | +--------+------------+------------+------+

Interogarea va utiliza mai degraba death IS NOT NULL decat death <> NULL intrucat NULL este o

valoare aparte care nu poate fi comparata folosind operatorii obisnuiti de comparare. Acest aspect este discutat mai tarziu. Dar daca doresti sa afli ce animale au ziua de nastere in cursul lunii curente? Pentru acest tip de calcul, anul si ziua sunt irelevante; nu doresti decat sa extragi partea corespunzatoare lunii din coloana birth. MySQL asigura mai multe functii pentru extragerea partilor din date, cum ar fi YEAR(), MONTH(), si DAYOFMONTH(). MONTH() este functia adecvata acestui caz. Pentru a vedea cum functioneaza, ruleaza o interogare simpla ce afiseaza atat valoarea lui birth , cat si a lui MONTH(birth):
mysql> SELECT name, birth, MONTH(birth) FROM pet; +----------+------------+--------------+ | name | birth | MONTH(birth) | +----------+------------+--------------+ | Fluffy | 1993-02-04 | 2 | | Claws | 1994-03-17 | 3 | | Buffy | 1989-05-13 | 5 | | Fang | 1990-08-27 | 8 | | Bowser | 1989-08-31 | 8 | | Chirpy | 1998-09-11 | 9 | | Whistler | 1997-12-09 | 12 | | Slim | 1996-04-29 | 4 | | Puffball | 1999-03-30 | 3 | +----------+------------+--------------+

Detectarea animalelor cu zile de nastere in urmatoarea luna este la fel de simplu. Sa presupunem ca data curenta este aprilie. Atunci, valoarea lunii este 4 si poti cauta animalele nascute in mai (luna 5) astfel:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+ | name | birth | +-------+------------+ | Buffy | 1989-05-13 | +-------+------------+

Exista o oarecare complicatie daca data curenta este decembrie. Nu poti pur si simplu sa adaugi o unitate la numarul lunii (12) si sa cauti animale nascute in luna 13, deoarece nu exista o asemenea luna. In schimb, poti cauta animale nascute in ianuarie (luna 1). Poti scrie interogarea astfel incat sa functioneze indiferent de luna curenta, astfel incat sa nu ai nevoie sa folosesti numarul unei anumite luni. DATE_ADD() iti permite sa adaugi un interval de timp unei anumite date. Daca adaugi o luna valorii CURDATE(), iar apoi extragi partea lunii cu MONTH(), rezultatul va consta in luna in cadrul careia cauti zile de nastere:
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));

O alta modalitate de a indeplini aceeasi sarcina este sa adaugi 1 si sa obtii luna imediat urmatoare celei curente dupa ce ai folosit functia modul (MOD) pentru a reduce valoarea lunii la 0 daca aceasta este in mod curent 12:
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;

De remarcat ca MONTH() returneaza un numar cuprins intre 1 si 12. Iar MOD(something, 12) returneaza un numar cuprins intre 0 si 11. Astfel, adunarea trebuie efectuata dupa MOD(), caci altfel am trece de la noiembrie (11) la ianuarie (1).

MySQL furnizeaza un mecanism standard SQL de cautare de sabloane, precum si o forma de cautare de sabloane bazata pe expresii regulate extinse, similare celor utilizate de catre utilitarele Unix, cum ar fi vi, grep, si sed. Cautarea de sabloane SQL iti permite sa folosesti ? ?pentru a efectua corespondente cu orice _ caracter unic si ? ?pentru efectua corespondente cu un numar oarecare de caractere (inclusiv % caracterele nule). In MySQL, sabloanele SQL sunt predefinite in mod automat case-insensitive. Aici sunt prezentate niste exemple. De remarcat ca nu trebuie sa folosesti = sau <> atunci cand ai de-a face cu pattern-uri SQL; foloseste operatorii de comparatie LIKE sau NOT LIKE in loc. Pentru a gasi numai animalele al caror nume incepe cu ? ? b:
mysql> SELECT * FROM pet WHERE name LIKE 'b%'; +--------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+------+------------+------------+

Pentru a gasi animalele al caror nume se termina in ? ? fy :


mysql> SELECT * FROM pet WHERE name LIKE '%fy'; +--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+

Pentru a gasi numele ce contin un ? ? w:


mysql> SELECT * FROM pet WHERE name LIKE '%w%'; +----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+

mysql> SELECT * FROM pet WHERE name LIKE '_____'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+

Pentru a gasi nume formate din exact cinci caractere, foloseste de cinci ori caracterul-pattern ? ? _:

Celalalt tip de cautare de sabloane asigurat de catre MySQL foloseste expresii regulate extinse. Atunci cand efectuezi un test pentru a gasi un corespondent pentru acest tip de sablon, foloseste operatorii REGEXP si NOT REGEXP (sau RLIKE si NOT RLIKE, care le sunt sinonimi). Iata cateva caracteristici ale expresiilor regulate extinse: ???Corespunde oricarui caracter unic. . ?O clasa de caractere ? ?corespunde oricarui caracter cuprins intre parantezele patrate. De [...]

exemplu, ? [abc]?corespunde lui ? ? ? ? sau ? ? Pentru a numi un sir de caractere, foloseste o a, b, c. cratima. ? [a-z]? corespunde oricarei litere, pe cand? [0-9]?corespunde oricarei cifre. ?? ?inseamna zero sau mai multe aparitii ale elementului anterior. De exemplu, ? ?corespunde * x* oricarui numar de aparitii ale caracterului ? ?, ? x [0-9]*?corespunde oricarui numar de cifre, iar ? ? .* oricarui numar din oricare element. ?Un apel REGEXP se incheie cu succes daca sablonul se potriveste oriunde in cadrul valorii testate. (Acesta difera de o cautare LIKE , care se termina cu succes doar daca sablonul se potriveste intregii valori.) ?Pentru a ancora un sablon astfel incat sa se potriveasca inceputului sau sfarsitului valorii testate, foloseste ? ?la inceputul sau ? ?la sfarsitul sablonului. ^ $ Pentru a demonstra cum functioneaza expresiile regulate extinse, interogarile LIKE prezentate mai devreme vor fi scrise aici folosind REGEXP. Pentru a gasi nume care incep cu ? ? foloseste ? ?astfel incat sa il asociezi cu inceputul fiecarui b, ^ nume:
mysql> SELECT * FROM pet WHERE name REGEXP '^b'; +--------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+------+------------+------------+

Daca intr-adevar doresti sa fortezi o comparatie REGEXP astfel incat sa fie case-sensitive, foloseste cuvantul-cheie BINARY pentru a transforma unul dintre siruri intr-un sir binar. Aceasta interogare se va potrivi doar literei mici ? ?de la inceputul unui nume: b
mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b';

Pentru a gasi nume care se termina in ? ? foloseste ? ?pentru a-l asocia sfarsitului numelui: fy , $
mysql> SELECT * FROM pet WHERE name REGEXP 'fy$'; +--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+

Pentru a gasi nume care contin un ? ? foloseste aceasta interogare: w,


mysql> SELECT * FROM pet WHERE name REGEXP 'w'; +----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+

Deoarece sablonul dat de o expresie regulata va fi gasit indiferent de pozitia sa in cadrul unui sir de caractere, nu este necesar sa folosesti ? ?inainte si dupa sablon, cum ai fi procedat daca era vorba % despre un sablon SQL clasic.

Pentru a gasi nume care contin exact cinci caractere, foloseste ? ? si ? ?pentru a identifica inceputul ^ $ si sfarsitul numelui, si de cinci ori ?? intre: .,

mysql> SELECT * FROM pet WHERE name REGEXP '^.....$'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+

Ai putea de asemenea sa scrii interogarea precedenta folosind operatorul (? repeta-de-n-ori? ):


mysql> SELECT * FROM pet WHERE name REGEXP '^.$'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+

Bazele de date sunt adesea folosite pentru a raspunde la intrebarea, ? cate ori apare un anumit tip De de data intr-un tabel?? De exemplu, ai putea dori sa stii cate animale de casa ai, sau cate animale de . casa detine fiecare stapan, sau ai putea dori sa efectuezi diverse tipuri de statistici de recensamant in legatura cu animalele. Sa obtii numarul total de animale pe care il ai este un demers echivalent cu intrebarea ? Cate randuri exista in tabelul pet??, pentru ca exista cate o inregistrare pentru fiecare animal de casa. Functia COUNT(*) numara randurile, astfel incat interogarea privind numarul de animale arata dupa cum urmeaza:
mysql> SELECT COUNT(*) FROM pet; +----------+ | COUNT(*) | +----------+ | 9 | +----------+

Mai devreme, ai extras numele oamenilor care detin animale de casa. Poti utiliza COUNT() daca vrei sa afli cate animale are fiecare stapan:
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner; +--------+----------+ | owner | COUNT(*) | +--------+----------+ | Benny | 2 | | Diane | 2 | | Gwen | 3 | | Harold | 2 | +--------+----------+

Se remarca folosirea lui GROUP BY pentru gruparea tuturor inregistrarilor ce corespund fiecarui stapan (owner). In lipsa acestuia, nu vei obtine decat un mesaj de eroare:
mysql> SELECT owner, COUNT(*) FROM pet; ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause

COUNT() si GROUP BY sunt utile pentru caracterizarea datelor in diferite moduri. Urmatoarele exemple iti arata diverse cai de a efectua operatii de recensamant al animalelor.

Numarul de animale pe specii:


mysql> SELECT species, COUNT(*) FROM pet GROUP BY species; +---------+----------+ | species | COUNT(*) | +---------+----------+ | bird | 2 | | cat | 2 | | dog | 3 | | hamster | 1 | | snake | 1 | +---------+----------+

Numarul de animale pe sexe:


mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex; +------+----------+ | sex | COUNT(*) | +------+----------+ | NULL | 1 | | f | 4 | | m | 4 | +------+----------+

(In aceasta iesire, NULL indica faptul ca sexul nu este cunoscut) Numarul de animale pe combinatia dintre specie si sex:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | bird | NULL | 1 | | bird | f | 1 | | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | | hamster | f | 1 | | snake | m | 1 | +---------+------+----------+

Nu este nevoie sa extragi un tabel intreg atunci cand folosesti COUNT(). De exemplu, interogarea precedenta arata astfel cand este efectuata doar asupra cainilor si pisicilor:
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE species = 'dog' OR species = 'cat' -> GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2

Sau, daca doresti numarul de animale pe sexe, doar pentru acele cazuri in care sexul este cunoscut:

mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE sex IS NOT NULL -> GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | bird | f | 1 | | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | | hamster | f | 1 | | snake | m | 1 | +---------+------+----------+

Obtinerea informatiilor despre bazele de date si tabele Ce s-ar intampla daca ai uita numele unei baze de date sau al unui tabel, sau care e structura unui tabel anume ? (de exemplu, cum se numesc coloanele din el?). MySQL abordeaza aceste probleme prin intermediul catorva functii care ofera informatii despre bazele de date si tabelele pe care acesta le contine. Pana acum ai luat in calcul optiunea SHOW DATABASES, care listeaza bazele de date manageriate de server. Pentru a afla ce baza de date e selectata momentan foloseste functia DATABASE():
mysql> SELECT DATABASE(); +------------+ | DATABASE() | +------------+ | menagerie | +------------+

Daca inca nu ai selectat nici o baza de date, rezultatul e NULL. Pentru a afla ce tabele contine baza de date predefinita (de exemplu, cand nu esti sigur in legatura cu numele unui tabel) foloseste aceasta comanda:
mysql> SHOW TABLES; +---------------------+ | Tables_in_menagerie | +---------------------+ | event | | pet | +---------------------+

Numele coloanei din rezultatul produs de aceasta functie este intotdeauna Tables_in_db_name, unde db_name reprezinta numele bazei de date. Pentru mai multe informatii citeste Section 12.5.5.34, ? SHOW TABLES Syntax? Daca vrei sa cunosti mai multe despre structura unui tabel, comanda . DESCRIBE iti poate fi de ajutor; ea afiseaza informatii despre fiecare din coloanele unui tabel:
mysql> DESCRIBE pet; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | nume | varchar(20) | DA | | NULL | | | stapan | varchar(20) | DA | | NULL | | | specii | varchar(20) | DA | | NULL | | | sex | char(1) |DA | | NULL | | | nastere | data | DA | | NULL | | | moarte | data | DA | | NULL | | +---------+-------------+------+-----+---------+-------+

Field indica numele coloanei, Type reprezinta tipul de date pentru coloana, NULL indica daca o coloana poate contine valori NULL, key semnaleaza daca o coloana e indexata, iar Default specifica valoarea predefinita a coloanei. Casuta Extra afiseaza informatii speciale despre coloane: daca o coloana a fost creata cu optiunea AUTO_INCREMENT, valoarea va fi auto_increment si nu empty. DESC e prescurtarea pentru DESCRIBE. Pentru mai multe informatii citeste Section 12.3.1, ? DESCRIBE Syntax? . Poti obtine functia CREATE TABLE necesara pentru a crea un tabel existent folosind functia SHOW CREATE TABLE.Vezi Section 12.5.5.9, ? SHOW CREATE TABLE Syntax? Daca ai . indexuri intr-un tabel, functia SHOW INDEX FROM tbl_name produce informatiile despre ele. Vezi Section 12.5.5.18, ? SHOW INDEX Syntax? .

Folosirea MySQL in Batch Mode In tutorialele precedente ai folosit mysql intr-o maniera interactiva pentru a ridica anumite probleme si a le afla raspunsul. De asemenea, poti rula mysql si in batch mode prin plasarea comenzilor pe care vrei sa le rulezi intr-un dosar, apoi ? spune-i?programului mysql sa citeasca datele introduse din dosar.:
shell> mysql < batch-file

Daca rulezi mysql din Windows si exista anumite caractere speciale in dosar care creeaza probleme, poti sa faci urmatorul lucru:
C:\> mysql -e "source batch-file"

Daca trebuie sa specifici parametrii de conexiune in linia de comanda, respectiva comanda poate arata astfel:
shell> mysql -h host -u user -p < batch-file Enter password: ********

Cand folosesti mysql in aceasta maniera, creezi un script file pe care il vei executa apoi. Daca vrei ca script-ul sa continue, chiar daca unele functii din el produc erori, poti folosi optiunea linie de comanda -force. Iata cateva motive pentru care sa folosesti un script: Daca rulezi o interogare in mod repetat (de exemplu, in fiecare zi sau saptamana), transformarea ei intr-un script iti permite sa eviti tastarea de fiecare data cand o executi. Poti genera noi interogari din cele deja existente, care sunt similare, prin copierea si editarea script file-urilor. Optiunea Batch mode poate fi utila atunci cand dezvolti o interogare, in special pentru comenzi pe mai multe linii sau pentru secvente de comenzi cu functii multiple. Daca faci o greseala, nu trebuie sa tastezi din nou totul, doar editeaza script-ul pentru a corecta eroarea si fa ca mysql sa o execute din nou. Daca ai de a face cu o interogare care produce o cantitate mare de rezultate finale, poti rula aceste rezultate cu ajutorul unui pager, in loc sa le vezi cum se deruleaza in partea de sus a ecranului:
shell> mysql < batch-file | more

Poti sa integrezi rezultatele finale intr-un dosar pentru a fi procesate ulterior:


shell> mysql < batch-file > mysql.out

Poti sa distribui script-ul si altor persoane, astfel incat sa poata rula si ele comenzile la randul lor. Unele situatii nu permit o folosire interactiva, de exemplu atunci cand rulezi o interogare dintr-o functie cron. In acest caz trebuie sa utilizezi batch mode. Formatul de output setat initial este diferit (mai concis) atunci cand rulezi mysql in batch mode decat atunci cand il folosesti interactiv. De exemplu, rezultatul final al functiei SELECT DISTINCT species FROM pet arata astfel cand mysql este rulat interactiv:
+---------+ | specii | +---------+ | pasare | | pisica | | caine | | hamster | | sarpe | +---------+ In batch mode, output-ul arata astfel: specii pasare pisica caine hamster sarpe

Daca vrei sa transformi formatul output interactiv in batch mode, foloseste mysql -t. Pentru a transmite output-ului comenzile ce sunt executate foloseste comanda mysql -vvv. De asemenea, poti folosi script-uri din prompt-ul mysql prin utilizarea comenzii source sau a comenzii:
mysql> source filename; mysql> \. Filename

Pagina: 12345678 9

S-ar putea să vă placă și