Documente Academic
Documente Profesional
Documente Cultură
1
Contents
Training .................................................................................................................................................. 1
SQL Querying pentru Business .............................................................................................................. 1
I. Notiuni Generale ................................................................................................................................. 3
II. Structura informatiei dintr-un DBMS relational .................................................................................. 5
III. SQL Data Types ............................................................................................................................... 7
IV. Setul de comenzi T-SQL: SELECT si FROM ..................................................................................... 13
V. Setul de comenzi T-SQL: Filtrare si Sortare Date ............................................................................... 24
VI. Setul de comenzi T-SQL: Grupare si Agregare date ....................................................................... 34
VII. Utilizare JOIN. Tipuri de JOIN ........................................................................................................ 39
VIII. Setul de comenzi T-SQL: CASE, COALESCE, ISNULL ....................................................................... 42
IX. Functii de data si ora: YEAR, MONTH, DAY, DATEDIFF, DATEADD................................................. 45
X. Functii de text: CHARINDEX, SUBSTRING, LEN. Operatorul de concatenare ..................................... 48
XI. Tabele temporare. CTE ................................................................................................................. 52
XII. Utilizare operatorilor pentru seturi de date: UNION ALL, UNION, INTERSECT, EXCEPT ................ 57
XIII. Creare baza de date. Creare tabele. Constrangeri tabele. Diagrama baza de date. ...................... 62
XIV. Setul de comenzi T-SQL: INSERT, UPDATE, DELETE, TRUNCATE .................................................... 74
XV. Creare VIEW-uri ............................................................................................................................ 82
2
I. Notiuni Generale
Pentru a putea defini structura unei baze de date si a stoca informatiile avem nevoie de un
software care sa realizeze toate functiile pe care aceste nevoi le implica. Un astfel de soft se
numeste sistem de gestiune a bazelor de date, prescurtat in romana SGBD si in engleza
DBMS (Database Management System).
Un DBMS implementeaza functiile necesare pentru diferitele aspecte ale lucrului cu bazele de
date:
Accesarea informatiilor dintr-o baza de date se poate realiza de catre un utilizator (un profesor
insereaza notele de la examen) sau de catre o aplicatie (o aplicatie de monitorizare a unui
server web insereaza intr-o baza de date paginile accesate, tipul de browser folosit).
Utilizatorul interfateaza cu DBMS prin intermediul unui client – o aplicatie (SQL Server
Management Studio).
Aplicatiile care acceseaza bazele de date o fac indirect, prin intermediul DBMS. Atunci cand
dorim, spre exemplu, sa cream o baza de date sau sa inseram informatii in baza de date , vom
solicita softului DBMS sa faca acest lucru, trimitand comenzile corespunzatoare. DBMS
cunoaste formatul in care a fost memorata informatia si are acces direct la datele in cauza.
Aplicatia client nu poate avea intotdeauna acces la date (deseori clientii ruland pe alta masina
3
decat DBMS. Clientul acceseaza datele independent de aspectele fizice ale stocarii datelor pe
HDD sau in RAM.
Avand in vedere ca DBMS ofera servicii clientilor in baza cererilor formulate de catre acestia, el
contine un modul care actioneaza ca server de baze de date.
Cererea trimisa de catre clienti serverului de baze de date poarta denumirea de interogare
(query).
Unul dintre beneficiile importante pe care le ofera un DBMS este decuplarea modalitatii fizice de
structurare a datelor (exemplu: organizarea, locatia si denumirea fisierelor) de modalitatea de
accesare si manipulare a lor. Utilizatorul care beneficiaza de serviciile unui DBMS nu vede (si
nici nu doreste sa stie) aspectele low-level ale stocarii informatiei, ci doreste o viziune logica a
datelor memorate care sa ii permita usoara lor introducere, extragere si prelucrare.
In acest scop, DBMS pune la dispozitia utilizatorului fie o interfata grafica, fie un limbaj care sa ii
permita acestuia interactiunea cu datele si facilitatile conexe acestora. Limbajul folosit in cazul
bazelor de date relationale este SQL (Sructured Query Language).
SQL este un limbaj ce contine intructiuni pentru definirea si modificarea structurii bazelor de
date, accesarea si manipularea datelor si controlul accesului la date. El a fost creat la inceputul
anilor ”70 la IBM si folosit initial ca baza intr-unul dintre produsele acestei firme. Ulterior, in
1986, el este standardizat de catre ANSI (American National Standards Institute) si apoi de
catre ISO (International Organization for Standardization).
Desi fiecare dintre aceste pachete software implementeaza limbajul SQL, fiecare dintre ele
prezinta abateri de la standard sau extensii ale limbajului, care, pe de o parte duc la
performante mai bune sau o mai mare usurinta de utilizare, dar pe de alta parte introduc
incompatibilitati intre diversele softuri DBMS.
4
II. Structura informatiei dintr-un DBMS relational
O baza de date relationala este un ansamblu de informatie compus dintr-unul sau mai multe
tabele. Modalitatea fizica de stocare a datelor tine de softul DBMS folosit (diferind de la un
DBMS la altul). Gratie limbajului SQL, clientul poate manipula datele independent de aspectele
fizice ale stocarii datelor.
Informatiile sunt stocate in tabele. O baza de date poate contine zero sau mai multe tabele.
Tabele (relatii)
Exemplu: Dorim sa cream o tabela in care sa stocam informatii despre facturi. Coloanele
necesare sunt: Id_Factura, Id_Client, Data_Factura, Valoare. Avem 4 coloane obligatorii si un
numar variabil de randuri. Vom impune pentru fiecare coloana tipul de date corespunzator.
Dupa crearea tabelei, se vor insera datele. Acestea respecta constrangerile de tip de data
impuse la crearea tabelei.
Coloane (atribute)
5
Desi in definitia unei tabele, coloanele sunt create intr-o anumita ordine, la extragerea datelor
din baza de date, ele pot fi reordonate.
Randuri (inregistrari)
Un rand al unei tabele reprezinta un ansamblu de valori (date), cate una corespunzatoare
fiecarei coloane. Fiecare valoare dintr-o tabela se afla la intersectia unei linii cu o coloana, o
valoare este unic identificata odata ce am specificat: serverul, baza de date, tabela, coloana
si randul.
Conceptul NULL
T-SQL este un dialect al standardului SQL. Toti furnizorii de baze de date, inclusiv Microsoft au
implementat dialect SQL ca principal limbaj in manipularea datelor in platformele lor de baze de
date. Pe de alta parte, nucleul limbajului este acelasi.
Utilizand standard SQL este best parctice. Codul este portabil si usor de implementat in alte
platforme.
Un exemplu cand alegem sa lucram in standard SQL folosim operatorul <> (diferit) fata de
operatorul nonstandard != (diferit).
6
III. SQL Data Types
Management Studio este un software lansat pentru prima data cu versiunea Microsoft SQL
Server 2005, utilizat pentru configurarea, organizarea si administrarea componentelor Microsoft
SQL Server. Tool-ul include atat partea de interactiune grafica, cat si editare de scripturi in
vederea lucrului cu obiectele serverului.
Cu ajutorul Object Explorer se ierarhizeaza obiectele fiecarei instante SQL Server: Databases,
Security etc.
7
Baza de date Training (diagrama)
Baza de date captureaza toate vanzarile realizate intr-o companie, clientii companiei, precum si
tranzactiile dintre companie si furnizorii sai.
8
Toate aceste informatii sunt stocate in diferite tabele. Tabelele au denumiri, in functie de ce
informatii detin. Scopul crearii mai multor tabele este de a da userului o imagine de ansamblu
asupra procesului de business si ce rapoarte sunt necesare si pot fi extrase. Relatiile dintre
tabele ne redau flow-ul de business.
Tabelele sunt organizate pe diferite scheme: dbo, HR, Production, Sales, Stats.
Tabele
Tabelele sunt obiectele in care stocam informatiile. Au un numar definit de coloane si un numar
variabil de randuri. Fiecare coloana are un nume, tip de date si constrangeri, daca este cazul.
Tipuri de date
Exact numeric:
- Bigint
- Int
- Smallint
- Tinyint
9
Data type Range Storage
p – reprezinta numarul total de digits stocati, la stanga si la dreapta de punctul zecimal. Prezicia
trebuie sa fie un numar intre 1 (minim) si 38 (maxim). Precizia default este 18.
s – reprezinta numarul de digits stocati la dreapta punctului zecimal. Scala poate fi un numar
intre 0 si p. Scala default este 0.
1-9 5
10-19 9
20-28 13
29-38 17
- Money
10
smallmoney - 214,748.3648 to 214,748.3647 4 bytes
- Date (yyyy-mm-dd)
Calendar Gregorian
- Datetime
- Smalldatetime
Calendar Gregorian
(Does not include the complete range of years.)
11
Character string:
- Char(n) – lungime fixa egala cu n (numarul de caractere permise). n poate lua valori
intre 1 si 8000. Dimensiunea este egala cu n bytes.
- Varchar(n) – lungime variabila egala cu n. Dimensiunea este egala cu n bytes plus 2
bytes.
- Varchar(max) – max indica maximul dimensiunii egal cu 2^31-1 byte (2GB).
- Nchar(n) – n poate lua o valoare intre 1 si 4000 (2 character set). Dimensiunea este de
doua ori n bytes. Este dimensiune fixa.
- Nvarchar(n) - n poate lua o valoare intre 1 si 4000 (2 character set). Dimensiunea este
de doua ori n bytes. Este dimensiune variabila.
- Nvarchar(max) - max indica maximul dimensiunii egal cu 2^31-1 byte (2GB).
12
IV. Setul de comenzi T-SQL: SELECT si FROM
Sintaxa unei interogari SQL este urmatoarea, precum si ordinea de scriere a clauzelor:
1. SELECT <<coloane>>
2. FROM <<tabele>>
3. WHERE <<conditii>>
4. GROUP BY <<agregari>>
5. HAVING <<conditii pe agregari>>
13
6. ORDER BY <<ordonarea datelor>>
1. FROM <<tabele>>
2. WHERE <<conditii>>
3. GROUP BY <<agregari>>
4. HAVING <<conditii pe agregari>>
5. SELECT <<coloane>>
6. ORDER BY <<ordonarea datelor>>
Exemplu:
SELECT Extragem
country Tara
, YEAR(hiredate) AS yearhired Anul angajarii
, COUNT(*) AS numemployees Numarul total de anagajati
FROM HR.Employees Din tabela Employees, schema HR
WHERE hiredate >= '20030101' Cu conditia ca data angajarii sa fie cel putin 1
ianuarie 2003
GROUP BY country Grupam datele dupa tara
, YEAR(hiredate) si anul angajarii pentru ca avem o functie de
agregare (COUNT)
HAVING COUNT(*) > 1 Consideram doar tarile si anii de angajare cu
mai mult de 1 angajat
ORDER BY country Ordonam datele dupa tara
, yearhired DESC; si anul angajarii
Rezultat:
14
Obs: Deoarece ORDER BY este evaluat dupa SELECT, atunci aliasul pentru extragerea anului
(yearhired) este recunoscut, ceea ce inseamna ca putem ordona dupa alias (redenumire
coloanei)
- Prima clauza evaluata este clauza FROM. In clauza FROM este (sunt) indicat(e) tabelul
(tabelele). Daca se extrag date din mai multe tabele, atunci apare si notiunea de JOIN si
fiecare tabel va primi un alias (un nume). JOIN-urile se vor discuta ulterior.
select * FROM HR.Employees afiseaza toate datele din tabela HR.Employees (9 randuri)
- Cea dea doua clauza evaluata este clauza WHERE, clauza care ne permite sa filtram
randurile din tabel(e). Randurile care sunt evaluate la False sau la Unknown nu sunt
afisate.
select *
FROM HR.Employees
WHERE hiredate >= '20030101'
(7 randuri)
Obs: Clauza WHERE nu recunoaste alias-urile pentru ca este evaluata inaintea clauzei
SELECT. In cadrul clauzei SELECT se stabilesc alias-urile pentru coloane.
SELECT country, YEAR(hiredate) AS yearhired FROM HR.Employees WHERE yearhired >= 2003
Msg 207, Level 16, State 1, Line 2
Invalid column name 'yearhired'.
- A treia clauza evaluata este clauza GROUP BY. Clauza GROUP BY permite gruparea
randurilor in functie de coloanele specificate (country si year(hiredate)).
15
SELECT country
, YEAR(hiredate) AS yearhired
, count(*) Nr_Angajati
FROM HR.Employees
WHERE hiredate >= '20030101'
GROUP BY country
, YEAR(hiredate)
- Cea de-a patra clauza evaluata este clauza HAVING. Clauza ne permite sa extragem
doar gruparile cu mai mult de un angajat. Sunt afisate doar randurile unde conditia este
True (nu sunt afisate randurile unde conditia este evaluata la False sau Unknown).
SELECT country
, YEAR(hiredate) AS yearhired
, count(*) Nr_Angajati
FROM HR.Employees
WHERE hiredate >= '20030101'
GROUP BY country
, YEAR(hiredate)
HAVING COUNT(*) > 1
- Cea de-a cincea clauza evaluata este clauza SELECT. In cadrul clauzei, mai intai se
evalueaza expresiile si atribuie alias-uri coloanelor rezultate. Dupa evaluarea expresiilor,
se evalueaza clauza DISTINCT, daca aceasta este specificata. DISTINCT extrage
inregistrarile unice.
- Clauza ORDER BY este ultima evaluata, implicit dupa clauza SELECT, ceea ce
inseamna ca in cadrul lui ORDER BY putem utiliza alias-uri sau numarul de coloane.
SELECT country
, YEAR(hiredate) AS yearhired
, count(*) Nr_Angajati
FROM HR.Employees
WHERE hiredate >= '20030101'
GROUP BY country
, YEAR(hiredate)
HAVING COUNT(*) > 1
16
ORDER BY 1 , 2 DESC;
Clauza FROM
Clauza FROM este prima clauza evaluata din cadrul unei interogari.
- Este clauza unde sunt indicate tabele din care se extrag informatiile
- Este clauza unde sunt aplicatii operatorii de tip JOIN.
Exemplu:
Unde:
- HR – schema
- Employees – tabela
Obs: In anumite cazuri, schema poate fi omisa, insa se va considera schema default: dbo
Exemplu:
In cadrul clauzei FROM se pot specifica si alias-uri pentru tabele. Alias-ul este un nume scurt
asociat tabelei, de obicei litera cu care incepe tabelul.
Obs: Daca un tabel primeste alias, atunci numele intreg al tabelului nu mai este recunoscut.
17
Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "Employees.lastname" could not be bound.
Clauza SELECT
Clauza SELECT este ultima clauza evaluata. Are doua roluri principale:
Exemple:
18
SELECT * FROM HR.Employees;
- Asterix (*) returneaza toate coloanele din tabela HR.Employees.
Obs: Returnarea tuturor coloanelor nu este best practice. Trimitand mai multe date decat este
nevoie, poate avea un impact negativ asupra performantei sistemului.
Exemplu:
Obs: Daca se omite virgula dintre firstname si lastname, atunci lastname devine alias pentru
coloana firstname.
Exemplu:
19
Exemplu: Sa se determine empid, si Numele (lastname concatenat cu firstname) angajatilor.
Clauza DISTINCT este utilizata pentru a elimina randurile duplicate din rezultatul unei
interogari.
20
- Fara clauza DISTINCT
- Clauza DISTINCT
Una dintre diferentele dintre standard SQL si T-SQL este faptul ca in standard SQL nu poate
exista doar clauza SELECT fara clauza FROM, pe cand in T-SQL poate fi de sine statatoare
clauza SELECT.
Exemplu:
Obs: Functia getdate() returneaza data si ora curente. ABC Company este intre apostrofuri
pentru ca este un text.
Delimitatori de identificare
Identificarea atributelor, schemelor, tabelelor sau a altor obiecte poate fi facuta cu ajutorul
delimitatorilor.
21
Delimitatori: T-SQL utilizeaza duble ghilimele (” ”) pentru identificarea obiectelor, precum si
paranteza dreapta dubla ([ ]).
Utilizarea acestora este optionala atunci cand identificatorii sunt regulari: tabela Orders, schema
Sales, coloana OrderDate. Regula pentru identifcatorii regulari este: primul caracter trebuie sa
fie o litera de la A la Z (mica sau mare). Nu pot fi utilizate cuvinte cheie din T-SQL, nu pot exista
spatii si nici caractere speciale.
Daca identificatorii nu urmeaza regula de mai sus, atunci delimitatorii devin obligatorii si
identificatorii se numeste iregulari: coloana [Order Data], tabela ”Orders 2016”.
22
Exercitii:
23
V. Setul de comenzi T-SQL: Filtrare si Sortare Date
Clauza WHERE este cea de-a doua clauza evaluata, dupa clauza FROM.
SELECT empid, firstname, lastname, country, region, city FROM HR.Employees WHERE region
='WA';
SELECT empid, firstname, lastname, country, region, city FROM HR.Employees WHERE region
<>'WA';
Obs: Daca selectam toti angajatii din tabela Employees fara sa filtram dupa regiune:
observam ca in coloana region aveam NULL si WA, iar cand interogarea a fost sa selectam toti
angajatii cu regiunea diferita de WA, rezultatul nu a fost cele 4 randuri cu NULL, ci 0 randuri.
24
NULL reprezinta „missing value”, nu o valoare NULL. Cand regiunea este NULL, operatorul
<> WA evalueaza predicatul la „unknown”, adica nu se cunoaste regiunea (nu a fost completata
in baza de date).
Pentru a returna toti angajatii care au regiunea diferita de WA, interogarea va fi construita astfel:
SELECT empid
, firstname
, lastname
, country
, region
, city
FROM HR.Employees
WHERE region <> 'WA'
OR region IS NULL;
Obs: Filtrarea datelor este un lucru foarte important pentru performanta interogarii. Filtrand
datele, inseamna ca tabela nu este scanata in intregime si astfel se reduce traficul in retea. O
alta metoda pentru a imbunatatii performanta unei interogarii este prin utilizarea indecsilor (se
va discuta mai tarziu).
SELECT custid
, companyname
, country
FROM [Training].[Sales].[Customers]
WHERE country='UK' or country='usa'
Exemplu: Sa se determine toti clientii din UK sau USA cu functia de Sales Representative.
SELECT custid
25
, companyname
, contacttitle
, country
FROM [Training].[Sales].[Customers]
WHERE (country='UK' or country='usa') and contacttitle='Sales Representative'
Obs: Intrucat clientii sunt fie din UK, fie din USA, dar indiferent de tara, au functia de Sales
Representative, atunci vom utiliza in filtrarea datelor si operatorul AND, pe langa operatorul OR.
Scrierea filtrelor se va face utilizand paranteze, pentru a reuni multimea clientilor din UK cu
multimea clientilor din USA, rezultand astfel o singura multime de clienti, asupra careia aplicam
urmatorul filtru, cel cu functia de Sales Representative, astfel restragem multimea rezultata.
Exemplu: Sa se determine toti clientii din UK cu functia de Sales Representative si clientii din
Canada cu functia de Accounting Manager.
SELECT custid
, companyname
, contacttitle
, country
FROM [Training].[Sales].[Customers]
WHERE (country='UK' and contacttitle='Sales Representative') or
(country='Canada' and contacttitle='Accounting Manager')
Exemplu: Sa se determine toti clientii care nu sunt din Spania, dar au functia fie de Marketing
Manager, fie de Sales Associate.
SELECT [custid]
,[companyname]
,[contacttitle]
,[country]
FROM [Training].[Sales].[Customers]
where country <> 'Spain'
and contacttitle in ('Marketing Manager','Sales Associate')
Rezultatul interogarii – 18 randuri.
26
SELECT [orderid]
,[custid]
,[empid]
,[orderdate]
FROM [Training].[Sales].[Orders]
where [orderdate]>='2008-01-01' and [orderdate]<='2008-12-31'
sau
SELECT [orderid]
,[custid]
,[empid]
,[orderdate]
FROM [Training].[Sales].[Orders]
where [orderdate] between '2008-01-01' and '2008-12-31'
Rezultatul interogarii – 270 de randuri
Exemplu: Sa se determine toate tranzactiile din 2006 de valoare cuprinsa intre 50 si 100.
SELECT [orderid]
,[custid]
,[empid]
,[orderdate]
,freight
FROM [Training].[Sales].[Orders]
where ([orderdate] between '2006-01-01' and '2006-12-31')
and freight between 50 and 100
Rezultatul interogarii – 32 de randuri
Obs: Scrierea filtrelor de tip date and time se va face in limbaj neutru. De exemplu, '20070212'
Intotdeauna este interpretat ymd. De asemenea, '2007-02-12' este scriere in limbaj neutru doar
daca coloana filtrata este tip: DATE, SMALLDATETIME, DATETIME, DATETIME2,
DATETIMEOFFSET.
SELECT empid, firstname, lastname FROM HR.Employees WHERE lastname LIKE 'D%';
27
SELECT empid, firstname, lastname FROM HR.Employees WHERE firstname LIKE '%A';
SELECT empid, firstname, lastname FROM HR.Employees WHERE firstname LIKE '%AR%';
Exemplu: Sa se determine toti clientii a caror regiune incepe cu W si numele regiunii are 2
caractere.
SELECT
custid
,companyname
,region
from [Sales].[Customers] where region like 'W_'
Clauza ORDER BY este ultima clauza evaluata, deci dupa clauza SELECT. Clauza ORDER BY
sorteaza datele ascendent (ASC) sau descendent (DESC).
Exemplu: Sa se determine toti angajatii din regiunea WA ordonati ascendent dupa oras.
28
ORDER BY city;
Obs: Daca nu se specifica tipul de sortare (ASC sau DESC), atunci sortarea implicita va fi
ascendenta.
Exemplu: Sa se determine toti angajatii din regiunea WA ordonati descendent dupa oras.
Obs: Observam ca avem doi angajati din acelasi oras. Cei doi angajati nu sunt sortati intr-o
anumite ordine.
Exemplu: Sa se determine toti angajatii din regiunea WA ordonati descendent dupa oras si id-ul
de angajat.
Obs: Tinand cont ca ORDER BY este evaluata dupa clauza SELECT, putem specifica in cadrul
interogarii numarul de coloana (coloane) dupa care se doreste sortarea.
29
Rezultatul este acelasi cu rezultatul interogarii anterioare.
Obs: De asemenea, din aceleasi considerente de evaluare a clauzei ORDER BY, putem sorta
datele si dupa alias-uri.
Exemplu: Sa se determine toti angajatii si anul nasterii lor, angajati din regiunea WA; angajatii
sa fie ordonati descendent dupa anul nasterii.
Obs: Pot fi sortate datele si in functie de coloane care nu sunt afisate in SELECT, dar sunt
prezente in tabele.
Exemplu: Sa se determine toti angajatii din regiunea WA. Angajatii vor fi sortati ascendent dupa
data nasterii.
Obs: Daca sortarea datelor se va face in functie de coloana ce contine NULL, atunci NULL-urile
vor fi afisate primele si apoi valorile non-null.
30
FROM Sales.Orders
WHERE custid = 20
ORDER BY shippeddate
- Numar de randuri
Cu ajutorul optiunii TOP putem filtra un numar specificat de randuri. Optiunea TOP se
mentioneaza imediat dupa clauza SELECT.
Exemplu: Sa se determine cele mai recente 3 tranzactii din tabela Orders in functie de data
tranzactiei.
Obs: Optiunea TOP se utilizeaza impreuna cu clauza ORDER BY. In caz contrar se extrag 3
randuri aleatorii din tabela mentionata.
- Procent
In mod similar se pot extrage primele 10% tranzactii in functie de valoarea tranzactiei.
Rezultatul interogarii – 83 de randuri (in total, in tabela Orders sunt 830 randuri).
31
- With Ties
In cazul in care ultimul rand rezultat are valoarea coloanei mentionata in clauza ORDER BY
egala cu a altor randuri, pentru a returna si celelalte randuri, se utilizeaza optiunea WITH TIES.
Exemplu: Sa se determine cele mai recente 3 tranzactii din tabela Orders in functie de data
tranzactiei. Daca ultimul ultima tranzactie are aceeasi data cu a altor tranzactii, sa se returneze
toate tranzactiile.
Exercitii:
1. Sa se ruleze scriptul 02. Create db Bank.sql (scriptul creeaza o baza de date cu mai
multe tabele relationate)
32
2. Sa se extraga urmatoarele informatii din baza de date Bank.
- Sa se determine lista de tranzactii care au valoarea peste 300. Sa se ordoneze
tranzactiile descendent dupa data tranzactiei.
- Sa se extraga top 7 tranzactii cele mai recente.
- Sa se modifice interogarea anterioara astfel incat, daca ultima tranzactiei are aceesi
datatranzactie cu alte tranzactii, acestea din urma sa fie afisate.
- Sa se determine lista de tranzactii care sunt efectuate pe conturile 999991 si 999995.
- Sa se determine lista de tranzactii care au valoarea intre 100 si 1000 si sunt efectuate in
2009.
- Sa se determine lista de tranzactii care sunt de tip Plata Salariu (se preia id-ul tipului de
tranzactie din tabela tiptranzactii).
- Sa se determine lista de tranzactii efectuate de Client 1 (se preia id-ul clientului din
tabela clienti, pentru acest id de client, identificam conturile lui si pentru conturile
identificate extragem tranzactiile). Sa se ordoneze datele crescator dupa nr de cont,
descrescator dupa valoarea tranzactiei.
33
VI. Setul de comenzi T-SQL: Grupare si Agregare date
Clauza GROUP BY
Clauza GROUP BY permite gruparea datelor in mai multe seturi de date, iar, ulterior aceste
seturi date pot fi prelucrate utilizand: functii de agregare si filtrari.
Functii de agregare
- COUNT (coloana) – numara cate valori not null exista in coloana mentionata
- COUNT (*) – numara toate randurile
- COUNT(distinct coloana) – numara cate valori distincte exista in coloana mentionata
- SUM(coloana) – insumeaza valorile din coloana mentionata
- MAX(coloana) – determina valoarea maxima din coloana mentionata
- MIN(coloana) – determina valoarea minima din coloana mentionata
- AVG(coloana) – determina media aritmetica a valorilor nenule din coloana mentionata
Exemplu:
SELECT
count([shipregion]) Nr_Valori_NOTNULL
,count(*) Nr_randuri
,count(distinct [shipregion]) Nr_Valori_Distinct
FROM [Training].[Sales].[Orders]
Obs: Datorita faptului ca nu a fost specificat un set de atribute de grupare, interogarea de mai
sus returneaza un singur set de date.
SELECT [shipregion]
,count(*) Nr_Tranzactii
FROM [Training].[Sales].[Orders]
group by [shipregion]
order by [shipregion]
34
Rezultatul interogarii – 20 randuri
Obs:
Setul de atribute de grupare este format dintr-un singur atribut: shipregion. Este utilizata functia
de agregare COUNT(*).
Daca nu se specifica functia de agreare, rezultatul interogarii este tot 20 rows, insa nu va mai fi
afisat numarul de randuri pentru fiecare regiune.
SELECT [shipregion]
--,count(*) Nr_Tranzactii
FROM [Training].[Sales].[Orders]
group by [shipregion]
order by [shipregion]
SELECT [shipregion]
,year(orderdate) An_tranzactie
,count(*) Nr_Tranzactii
FROM [Training].[Sales].[Orders]
group by [shipregion]
,year(orderdate)
order by [shipregion]
35
Exemplu: Sa se determine la nivel de shipregion si shipcity: numarul total de tranzactii, suma
valorilor, media aritmetica valorilor, cea mai mare valoare, cea mai mica valoare – freight.
select
shipregion
,shipcity
,count(*) Nr_Tranzactii
,sum(freight) Total_Val
,avg(freight) Media_Arit
,max(freight) Max_Val
,min(freight) Min_Val
from [Training].[Sales].[Orders]
group by
shipregion
,shipcity
select
shipcity
,year(orderdate) An_Tranzactie
,count(*) Nr_Tranzactii
,sum(freight) Total_Val
,avg(freight) Media_Arit
from [Training].[Sales].[Orders]
where freight>=50
group by
shipcity
,year(orderdate)
order by 2
36
Obs: year(orderdate) extrage anul din data tranzactiei (orderdate). Conditia de freight>=50
extrage doar randurile din tabel unde freight este de cel putin 50. Setul de atribute de grupare
este format din shipcity si se regaseste atat in clauza select, cat si in clauza group by. Order by
2 (este specificat numarul coloanei) este posibil deoarece clauza order by se evalueaza dupa
clauza select, deci se cunosc coloanele extrase.
Clauza HAVING
Clauza HAVING se utilizeaza atunci cand se filtreaza seturi de date. In cadrul clauzei having,
conditiile sunt la nivel de functii de agregare. Clauza WHERE este la nivel de randuri dintr-o
tabela, pe cand clauza HAVING este la nivel de set de date.
select
shipcity
,year(orderdate)
,sum(freight) Total_Val
from [Training].[Sales].[Orders]
group by
shipcity
,year(orderdate)
having sum(freight) between 3000 and 5000
order by 2
select
shipcity
,year(orderdate)
,sum(freight) Total_Val
from [Training].[Sales].[Orders]
where freight<=1000
group by
shipcity
,year(orderdate)
having sum(freight) between 3000 and 5000
order by 2
37
Exercitii:
38
VII. Utilizare JOIN. Tipuri de JOIN
Adesea, datele necesare in rapoarte fac parte din mai multe tabele. Un mediu de baze date cu
cat este mai mult normalizat (se va discuta ulterior), cu atat mai multe tabele avem. Tabelele
sunt relationate intre ele prin chei: in tabela principala avem PRIMARY KEY, in tabela de
legatura avem FOREIGN KEY.
PRIMARY KEY
Cheia primara a unei tabele reprezinta ansamblul minim de campuri (sau doar un singur camp)
care identifica in mod unic o inregistrare dintr-o tabela. Pe o tabela poate exista cel mult o cheie
primara.
Campul/ ansamblul de campuri pe care se defineste cheia primara nu admite NULL si trebuie
sa contina date unice (exemplu: numarul de factura, codul de client, codul de produs).
T-SQL suporta 3 tipuri de joinuri: cross, inner si outer pentru a extrage informatii din mai multe
tabele.
INNER JOIN
Inner join returneaza partea comuna din doua tabele. Legatura dintre cele doua tabele se
realizeaza prin campul/campurile comun/comune.
Exemplu: Sa se determine toate produsele din categoria Seafood cu pretul de cel putin 15.
select
*
from [Production].[Categories] c
inner join Production.Products p on c.categoryid=p.categoryid
where c.categoryname='Seafood' and p.unitprice>=15
39
- Cele doua tabele au alias-uri: Categories alias c, products alias p. Motivul adaugarii
alias-urilor este utilizarea coloanei comune categoryid, pentru a stii din ce tabela se
preia coloana categoryid.
OUTER JOINs
LEFT OUTER JOIN (LEFT JOIN) – returneaza toate randurile din tabela din stanga si doar
randurile din tabela din dreapta care se regasesc si in prima tabela.
Exemplu: Sa se determine toti clientii si facturile acestora. Anumiti clienti nu au inca facturi.
select
c.custid
, c.companyname
, o.orderid
, o.orderdate
from Training.sales.Customers c
left join Training.[Sales].[Orders] o on o.custid=c.custid
40
Exercitii:
1. Sa se determine clientii unici care au conturi cu balanta intre 1000 si 50000.
2. Sa se modifice interogarea anterioara astfel incat sa se afiseze si cate conturi sunt.
3. Sa se afiseze clientii si conturile de tip depozit (sunt doua inner join-uri)
4. Sa se determine clientii, conturile si tranzactiile de tip Plata Salariu.
5. Sa se determine toate conturile pe care nu exista tranzactii efectuate.
6. Sa se determine toate tipurile de tranzactii pentru care nu exista tranzactii.
7. Sa se determine la nivel de tip cont si tip tranzactie: cate tranzactii sunt, cati clienti distincti
au efectuate tranzactiile, cate conturi distincte exista pentru aceste tranzactii.
41
VIII. Setul de comenzi T-SQL: CASE, COALESCE, ISNULL
Expresia CASE are rolul de testa anumite conditii si de a afisa valoarea/coloana conditiei
adevarate.
select
productid
,productname
,case
when unitprice<=30 then 'intre 0 si 30'
when unitprice<=60 then 'intre 31 si 60'
else 'peste 61' end as Interval_Pret
from Training.Production.Products
Functia COALESCE – este o abreviere a expresiei CASE. Coalesce este o functie standard,
nu asociata T-SQL.
Functia COALESCE accepta o lista de expresii de intrare si returneaza prima expresie nenull
sau NULL, daca toate expresiile sunt NULL.
42
Exemplu: Sa se afiseze fax-ul pentru fiecare client. In cazul in care fax-ul nu este completat
(NULL), atunci sa se afiseze numarul de telefon.
select
custid
,companyname
,fax
,phone
,coalesce(fax,phone) as Contact
from Training.Sales.Customers
Functia ISNULL – este o abreviere a expresiei CASE. Functia ISNULL este nonstandard.
Functia ISNULL are doua argumente: expresia considerata pentru verificare daca este NULL si
expresia care va fi returnata in cazul in care prima expresie este NULL.
Exemplu: Sa se afiseze textul „nu are fax” pentru clientii care nu au faxul completat.
select
custid
,companyname
,fax
,phone
,isnull(fax,'nu are fax') as Contact
from Training.Sales.Customers
43
Obs: Rezultatul functiei COALESCE va avea data type-ul expresiei rezultat. Rezultatul functiei
ISNULL va avea data type-ul primei expresii.
44
IX. Functii de data si ora: YEAR, MONTH, DAY, DATEDIFF, DATEADD
select
year(hiredate) Anul_Anagajarii
,count(*) Nr_Angajati
from Training.hr.Employees
group by year(hiredate)
Exemplu: Sa se determine pentru fiecare comanda: anul, luna si ziua. Sa se filtreze infromatiile
doar pentru anul 2006. Sa se ordoneze datele ascendent dupa luna, ascendent dupa zi.
select
orderid
,year(orderdate) An_Comanda
,month(orderdate) Luna_Comanda
,day(orderdate) Zi_Comanda
from Training.Sales.Orders
where year(orderdate)=2006
order by month(orderdate), day(orderdate)
Functia DATEDIFF returneaza diferenta dintre doua date calendaristice. Unitatea de masura
pentru diferenta este data ca input de catre utilizator.
45
Sintaxa functiei DATEDIFF:
select
empid
,lastname
,firstname
,datediff(yyyy,birthdate,hiredate) Varsta
from Training.hr.Employees
46
- Datepart este unitatea de masura
- Interval reprezinta perioada
- Startdate este data de inceput
Exemplu: Sa se determine pentru fiecare angajat anul in care va primi un bonus de fidelitate
stiind ca acest bonus se primeste la 5 ani de la angajare.
select
empid
,lastname
,firstname
,hiredate
,dateadd(yyyy,5,hiredate) Data_Bonus
,year(dateadd(yyyy,5,hiredate)) An_Bonus
from Training.hr.Employees
47
X. Functii de text: CHARINDEX, SUBSTRING, LEN. Operatorul de
concatenare
SELECT
[custid]
,[companyname]
,[contactname]
,charindex(',',contactname,1) Pozitie_Virgula
FROM [Training].[Sales].[Customers]
Exemplu: Sa se extraga in doua coloane separate numele si prenumele clientilor, din coloana
contactname.
SELECT
[custid]
,[companyname]
,[contactname]
,charindex(',',contactname,1) Pozitie_Virgula
,substring(contactname,1,charindex(',',contactname,1)-1) LastName
,substring(contactname,charindex(',',contactname,1)+1,len(contactname)-
charindex(',',contactname,1)) FirstName
FROM [Training].[Sales].[Customers]
48
Rezultatul interogarii – 91 de randuri.
Obs: Primul pas a fost indetificarea pozitiei virgulei. Pentru a extrage LastName, se vor extrage
toate caracterele situate inaintea virgulei. Pentru a extrage FirstName, se vor extrage toate
caracterele situate dupa virgula.
Exercitii:
Rezultat interogare:
2. Sa se modifice interogarea anterioara astfel incat, pentru fiecare client sa fie afisate cate
conturi se regasesc in fiecare interval mentionat.
Rezultat interogare:
49
3. Sa se determine pentru fiecare client data de procesare a tranzactiei, stiind ca aceasta
va fi procesata la 5 zile de la data efectuarii tranzactiei.
Rezultat interogare:
50
Baza de date Training:
5. Sa extraga din tabela Shippers numele celor 3 companii: GVSUA, ETYNR, ZHISN.
Rezultatul interogarii:
Rezultat interogare:
51
XI. Tabele temporare. CTE
Tabele temporare
SQL Server utilizeaza doua tipuri de tabele temporare: locale si globale. Ambele tipuri de tabele
sunt stocate in baza de date tempdb.
Tabelele temporare locale sunt prefixate cu # (exemplu: #mytable), iar tabelele temporare
globale sunt prefixate cu ## (exemplu: ##mytable).
Tabelele temporare locale sunt vizibile doar pe parcursul sesiunii unui singur user. Dupa
incheierea sesiunii, acestea sunt sterse.
Tabelele temporare gloable sunt vizibile pentru toate sesiunile si pentru toti userii. Se sterg
automat dupa inchiderea ultimei sesiuni in care sunt folosite.
Tabelele temporare (atat locale, cat si globale) se comporta la fel ca orice tabel permanent din
baza de date, exceptand baza de date unde sunt stocate (tempdb) si faptul ca acestea sunt
sterse automat la inchiderea sesiunii.
Exemplu: Sa se determine intr-o tabela temporara toti clientii din Londra si pentru acestia prima
tranzactie efectuata. Pentru tranzactiile extrase, sa se determine total discount (discount *
cantitate * pret) si total incasari (cantitate * pret).
SELECT c.custid
,c.city
,min(o.orderid) Min_OrderId
into #minorder
FROM [Training].[Sales].[Customers] c
inner join Training.Sales.Orders o on o.custid=c.custid
where c.city='London'
group by
c.custid
,c.city
52
select
m.*
, sum(od.discount * od.qty * od.unitprice) Total_Discount
, sum(od.qty * od.unitprice) Total_Valoare
from #minorder m
inner join Training.Sales.OrderDetails od on od.orderid=m.Min_OrderId
group by
m.custid
,m.city
,m.Min_OrderId
Exemplu: Sa se determine acelasi lucru ca mai sus, dar sa se utilizeze tabela temporara globala
##minorder.
SELECT c.custid
,c.city
,min(o.orderid) Min_OrderId
into ##minorder
FROM [Training].[Sales].[Customers] c
inner join Training.Sales.Orders o on o.custid=c.custid
where c.city='London'
group by
c.custid
,c.city
select
m.*
, sum(od.discount * od.qty * od.unitprice) Total_Discount
, sum(od.qty * od.unitprice) Total_Valoare
from ##minorder m
inner join Training.Sales.OrderDetails od on od.orderid=m.Min_OrderId
group by
m.custid
,m.city
,m.Min_OrderId
53
Obs: Diferenta dintre cele doua tabele: #minorder, ##minorder este faptul ca cea dea doua
tabela poate fi vizualizata si intr-o alta sesiune.
Exercitii:
1. Sa se determine intr-o tabela temporara locala conturile cu balanta cea mai mica. Pentru
aceste conturi sa se extraga toate tranzactiile efectuate.
2. Sa se determine intr-o tabela temporara globala conturile de tip Credit. Pentru aceste
conturi sa se determine toate tranzactiile din 2010 si 2011.
3. Sa se determine intr-o tabela temporara locala prima tranzactie efectuata de catre
fiecare client. Pentru aceste tranzactii, sa se determine separat valoarea tranzactiilor si
tipul acestora.
CTE – Common Table Expression – este un concept similar cu tabelele derivate. Tabele CTE
sunt vizibile doar pe parcursul rularii statementului in care sunt definite. Un tabel de tip expresie
este format din 3 parti:
Sintaxa CTE:
WITH nume_CTE as
54
interogarea din exterior
Exemplu: Sa se determine pentru fiecare client, contul cu balanta cea mai mare.
with CTE_bal
as
nume
(select
idclient,
max(balanta) balanta
from bank.dbo.conturi
group by Interogrea din interior
idclient
)
select
c.cont,
c.idclient,
c.Balanta
from bank.dbo.conturi c Interogarea din exterior
inner join cte_bal cc on
c.Balanta=cc.balanta and
c.IdClient=cc.IdClient
Exercitii:
1. Sa se determine pentru toti clientii cu suma totala comandata de peste 1000, toate
comenzile.
Rezolvare:
with cte_cust
as
(
select
c.custid
,sum(od.qty*od.unitprice) Total_Comenzi
from Training.Sales.Customers c
inner join Training.Sales.Orders o on o.custid=c.custid
inner join Training.Sales.OrderDetails od on od.orderid=o.orderid
group by c.custid
having
sum(od.qty*od.unitprice)>1000
)
55
select
o.*
from cte_cust cc
inner join Training.Sales.Orders o on o.custid=cc.custid
56
XII. Utilizare operatorilor pentru seturi de date: UNION ALL, UNION,
INTERSECT, EXCEPT
UNION ALL: opereaza intre doua sau mai multe seturi de date. UNION ALL uneste rezultatele
mai multor seturi date si pastreaza inregistrarile multiplicate.
select
city
,region
,country
from Training.Sales.Customers
union all
select
city
,region
,country
from Training.hr.Employees
Obs: Structura celor doua interogari este identica. Rezultatul final al reuniunii rezultatelor celor
doua interogarii contine inregistrari care se multiplica.
UNION: opereaza intre doua sau mai multe seturi de date. UNION uneste rezultatele mai multor
seturi date si elimina inregistrarile multiplicate.
57
Exemplu: Sa se determine toate orasele, regiunile si tarile clientilor si ale angajatilor.
select
city
,region
,country
from Training.Sales.Customers
union
select
city
,region
,country
from Training.hr.Employees
INTERSECT – operatorul returneaza inregistrarile comune dintre doua sau mai multe seturi de
date.
Exemplu: Sa se determine toate orasele, regiunile si tarile comune ale clientilor si ale
angajatilor.
select
city
,region
,country
from Training.Sales.Customers
intersect
select
city
,region
,country
from Training.hr.Employees
58
EXCEPT – operatorul returneaza diferenta dintre doua seturi de date, inregistrarile continute de
primul set de date care nu se regasesc in al doilea set.
Exemplu: Sa se determine toate orasele, regiunile si tarile clientilor din care nu fac parte
angajatii.
select
city
,region
,country
from Training.Sales.Customers
except
select
city
,region
,country
from Training.hr.Employees
• Calcul comenzi livrate: in cazul in care shippeddate is not null, atunci se va afisa
orderid, altfel nu se va afisa nimic. Peste orderid-urile determinate, se va aplica
functia count. Atentie, fiind join cu orderdetails, se va calcula count (distinct de case-
ul implementat mai sus)
Rezultatul final:
59
country no_orders no_delivered_orders
Argentina 16 14
Austria 40 38
Belgium 19 19
Brazil 83 81
Canada 30 29
(nu sunt afisate toate tarile)
select
c.country as Customer_Country,
count(distinct o.orderid) as No_orders,
count(distinct case when o.shippeddate is not null then o.orderid
end) as No_delivered_orders,
sum(od.qty*od.unitprice) as sales
from sales.Customers as c
inner join sales.Orders as o on c.custid=o.custid
inner join sales.OrderDetails as od on o.orderid=od.orderid
group by
c.country
2. Sa se determine toate comenzile plasate pana la sfarsitului lunii anterioare si valoarea lor.
Rezultatul va avea urmatoarele coloane:
Orderid / orderdate / sales
Pornind de la rezultatul anterior, sa se determine cate comenzi si total sales pe urmatoarele
intervale:
Clasificare
1.<=1000
2.<=5000
3.<=10000
4.>10000
Hinturi:
Pas 1:
- Se va cauta functia care determina ultima zi din luna.
- Luna anterioara se va calcula dinamic, pornind de la azi, iar azi este data de o functie
- ! Atentie ca functia care da data curenta, arata si timpul si trebuie eliminat timpul, iar apoi
calculata ultima zi din luna anterioara
- Rezultatul extras (Sa se determine toate comenzile plasate pana la sfarsitului lunii anterioare
si valoarea lor) poate fi stocat intr-o tabela temporara locala sau globala (sau se poate folosi
un CTE)
60
Pas 2:
- Rezultatul anterior este folosit in urmatorul script pentru a extrage raportul final
Rezultatul final este:
3.<=10000 24 158,089
4.>10000 14 170,328
; with cte_comenzi as
(select
o.orderid,
o.orderdate,
sum(od.qty*od.unitprice) as sales
from sales.Orders as o
inner join sales.OrderDetails as od on o.orderid=od.orderid
where o.orderdate<=EOMONTH(getdate(),-1)
group by
o.orderid,
o.orderdate)
select
case
when sales<=1000 then '1.<=1000'
when sales<=5000 then '2.<=5000'
when sales<=10000 then '3.<=10000'
else '4.>10000' end as Clasificare,
count(orderid) as nr_comenzi,
sum(sales) as total_vanzari
from cte_comenzi
group by
case
when sales<=1000 then '1.<=1000'
when sales<=5000 then '2.<=5000'
when sales<=10000 then '3.<=10000'
else '4.>10000' end
order by Clasificare
61
XIII. Creare baza de date. Creare tabele. Constrangeri tabele.
Diagrama baza de date.
Flow de business:
- un client suna departamentul Call Center pentru a primi o oferta de concediu=> Clientul
este stocat in tabela Clienti
- Agentul din Call Center creeaza o rezervare pentru propunerea catre client=>
Rezervarea este creata si stocata in tabela Orders
- Clientul confirma sau nu rezervarea. Daca va confirma rezervarea => Rezervarea
confirmata este stocata in tabela Orders_details
- Daca se confirma rezervarea, atunci se stiu detaliile despre rezervare=> tabela Hotels,
tabela Cities, tabela Countries
Conform exemplului de business de mai sus, se pot identifica urmatorele tabele: Customers,
Countries , Cities, Hotels, Orders, Orders_details.
Creare tabele
62
o Nume tabel
o Coloanele din tabela: nume coloane, tipuri de date pentru fiecare coloana, daca
fiecare coloana admite sau nu NULL, primary key pentru fiecare tabela.
Obs: Coloanele idcustomer si idcountry nu accepta NULL. Cheia primara (PK) pentru tabela
Customers este idcustomer. Coloanele pentru care se va seta PK nu accepta NULL. Pentru o
tabela se poate defini cel mult o cheie primara.
USE Reservations
GO
GO
63
name nvarchar(50) NULL,
idcity int NOT NULL,
stars int NULL,
CONSTRAINT PK_hotels PRIMARY KEY (idhotel)
)
GO
GO
GO
Alterare tabele
Un tabel odata creat poate fi modificat utilizand comanda ALTER. In acest mod pot fi adaugate,
sterse, modificate coloane.
Exemple:
64
add Address varchar(100)
Constrangeri tabele
Exemple:
Obs: Daca tabela Customers contine deja date, iar coloana Name are deja null-uri, atunci
adaugarea constragerii NOT NULL nu va functiona. Mai intai se vor completa NULL-urile
65
existente si apoi se va aplica constrangerea de NOT NULL pentru viitorii clienti inserati in
tabela.
2) Sa se modifice tabela Hotels, astfel incat, campul idCity sa admita doar date unice.
OBS: Adaugarea constrangerii de UNIQUE pentru IdCity inseamna din punct de vedere
business ca 2 hoteluri nu pot fi din acelasi oras. De exemplu, un lant hotelier are un singur hotel
in fiecare oras, Ramada ar putea fi un exemplu in acest sens.
3) Sa se stearga primary key-ul din tabela Cities. Sa se adauge primary key pe tabela
Cities.
66
alter table Reservations.dbo.Hotels
add constraint Ch_stars CHECK (stars<=5)
Exemple:
67
enddate datetime NULL,
idhotel int NOT NULL,
rooms int NULL default 1,
idtyperoom int NOT NULL,
stars int NULL,
CONSTRAINT PK_orders_details1 PRIMARY KEY (idorder)
)
- Object Explorer / baza de date Reservations / click dreapta Database Diagrams / New
Database Diagram
Obs: Daca pentru fiecare tabela au fost adaugate FOREIGN KEYS, atunci digrama si
relatiile dintre tabele se creaza implicit.
68
Obs: Daca pentru fiecare tabela nu au fost adaugate FOREIGN KEYS, atunci digrama si
relatiile dintre tabele trebuie create de catre utilizator.
69
Obs: campurile conectate trebuie sa fie identice ca si: tip, contrangeri. Numele nu este
obligatoriu sa fie identic, insa best practice este sa se pastreze acelasi nume.
70
Exercitii:
Locatii
Clienti
Masini
Angajati
71
IdAngajat Int Nu admite NULL PK
Denumire Varchar(100)
Functie Varchar(50)
IdLocatie Int Nu admite NULL FK cu referinta catre tabela
IdLocatie
Contracte
- Minim 4 tabele
72
- Constrangeri adaugate asupra coloanelor
- Diagrama bazei de date
73
XIV. Setul de comenzi T-SQL: INSERT, UPDATE, DELETE, TRUNCATE
INSERT
- INSERT Values
- INSERT Select
- INSERT Exec – se va discuta la modulul SQL Programming For Developers, unde sunt
prezentate Procedurile Stocate si comanda „exec”
- SELECT Into
INSERT Values
Exemplu: Sa se insereze doi clienti noi in tabela Clienti din baza de date Bank. Primul client
inserat va avea id-ul 400 si se va numi Client 4. Cel de-al doilea client inserat va avea id-ul 500
si se va numi Client 5.
(1 row(s) affected)
(1 row(s) affected)
INSERT Select
Exemplu: Sa se creeze o tabela temporara cu numele ##clienti care va avea doua coloane:
IdClient int not null si Nume_Client varchar(20). Campul IdClient va avea constrangerea de PK.
Sa se insereze toti clientii din tabela Bank.dbo.Clienti in tabela ##clienti.
74
(5 row(s) affected)
SELECT Into
Exemplu: Sa se insereze toate conturile clientilor: Client 1 si Client 2 intr-o tabela temporara
locala. Odata cu conturile se va afisa si numele clientului.
select
c.Nume
,cc.IdClient
,cc.Cont
,cc.Balanta
into #conturi_clienti
from bank.dbo.clienti c
inner join bank.dbo.conturi cc on c.IdClient=cc.IdClient
where c.nume in ('Client 1','Client 2')
(6 row(s) affected)
75
UPDATE
Vom construi 3 tabele, copii ale tabelelor existente Customers, Orders si OrderDetails:
MyCustomers, MyOrders, MyOrderDetails
Construirea celor 3 tabele a fost realizata utilizand comanda SELECT Into.
Use Training;
GO
Sintaxa:
UPDATE tabela
SET Col1=expresia1,
Col2=expresia2
WHERE conditii
76
Randurile care vor fi evaluate la TRUE in ceea ce priveste clauza WHERE vor fi updatate. Daca
nu este specificata clauza WHERE, atunci vor fi updatate toate randurile din tabela specificata.
Exemplu: Sa se modifice discountul pentru factura cu numarul 10251 astfel incat, discountul va
fi crescut cu 5%.
select *
from Sales.MyOrderDetails
where orderid=10251
update sales.MyOrderDetails
set discount=discount+0.05
where orderid=10251
(3 row(s) affected)
Exemplu: Sa se modifice discountul adaugand 5% pentru toate facturile clientilor din Norway.
select
od.orderid
,od.productid
,od.discount
,c.custid
,c.companyname
77
,c.country
from Sales.MyOrderDetails od
inner join sales.MyOrders o on o.orderid=od.orderid
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
Obs: este un singur client cu mai multe comenzi, fiecare comanda avand un numar de produse
cu 0 discount.
update od
set od.discount=od.discount+0.05
from Sales.MyOrderDetails od
inner join sales.MyOrders o on o.orderid=od.orderid
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
select
od.orderid
,od.productid
,od.discount
,c.custid
,c.companyname
,c.country
from Sales.MyOrderDetails od
inner join sales.MyOrders o on o.orderid=od.orderid
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
78
DELETE si TRUNCATE
T-SQL detine doua comenzi pentru stergerea datelor dintr-o tabela: DELETE si TRUNCATE
DELETE
Comanda DELETE sterge fie datele dintr-o tabela in intregime, fie doar anumite randuri care
sunt evaluate la TRUE conform uneia sau mai multor conditii.
Exemplu: Sa se stearga toate randurile din tabela MyOrderDetails unde productid=11 (se
presupune ca acest produs a fost adaugat dintr-o eroare pe anumite facturi si trebuie sters).
delete
from Sales.MyOrderDetails
where productid=11
select *
from Sales.MyOrderDetails
where productid=11
79
Exemplu: Sa se stearga toate randurile din tabela MyOrderDetails
delete
from Sales.MyOrderDetails
delete o
from sales.MyOrders o
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
(6 row(s) affected)
Obs: Se verifica daca mai sunt comenzi pentru clientii din Norway.
select *
from sales.MyOrders o
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
Obs: Clientii din Norway nu au fost stersi, doar comenzile acestora au fost sterse.
select *
from sales.MyCustomers
where country='Norway'
Daca se doreste si stergerea clientilor din Norway, atunci, dupa stergerea comenzilor se poate
rula comanda de delete asupra tabelei MyCustomers cu conditia: country='Norway'
TRUNCATE
80
Comanda TRUNCATE sterge toate randurile dintr-o tabela. Nu permite conditii pentru a sterge
doar anumite randuri.
- DELETE permite stergerea anumitor randuri dintr-o tabela, TRUNCATE sterge toate
datele dintr-o tabela
- TRUNCATE este mai rapida decat DELETE, pentru ca scrierea in Transaction Log se
face doar pentru paginile dealocate, in timp ce DELETE scrie in Transaction Log datele
care sunt sterse
- DELETE nu reseteaza identity. TRUNCATE reseteaza identity
- DELETE sterge utilizand JOIN-uri, ceea ce inseamna ca tine cont de FK. TRUNCATE
nu este permisa daca o tabela refrentiaza catre alta tabela
- DELETE are nevoie pentru user de dreptul de DELETE. TRUNCATE are nevoie pentru
user de dreptul de ALTER
81
XV. Creare VIEW-uri
Creare VIEW
VIEW-urile sunt obiecte ale bazei de date similare tabelelor. Cu ajutorul unui VIEW se pot
prezenta date dintr-unul sau mai multe tabele. Intr-un view se poate pastra logica de extragere
a datelor, astfel incat utilizatorul view-ului sa nu fie nevoit sa o retina.
select
year(o.orderdate) Year_Order,
sum(od.qty) Total_Qty
from sales.Orders o
inner join sales.OrderDetails od on od.orderid=o.orderid
group by
year(o.orderdate)
Obs:
c) View-ul creat se comporta la fel cu un tabel: se pot filtra datele, se pot face join-uri cu
alte tabele:
82
select *
from Sales.Qty_Orders
where Year_Order<>2006
Modificare VIEW
Modificarea / alterarea unui view se realizeaza in mod similar cu tabelele, utilizand comanda
ALTER.
Exemplu: Sa se modifice view-ul creat anterior (Sales.Qty_Orders) astfel incat informatiile sa fie
si la nivel de client (companyname).
select
c.companyname,
year(o.orderdate) Year_Order,
sum(od.qty) Total_Qty
from sales.Orders o
inner join sales.OrderDetails od on od.orderid=o.orderid
inner join sales.Customers c on c.custid=o.custid
group by
c.companyname,
year(o.orderdate)
Verificare
83
Stergere VIEW
Comanda pentru a sterge un view din baza de date este: DROP view nume_view.
Exercitii:
Rezolvare:
1.
use bank;
go
as
select
c.Nume
,cc.Cont
,cc.Balanta
,t.IdTranzactie
,t.DataTranzactie
,t.Valoare
from dbo.clienti c
inner join dbo.conturi cc on c.IdClient=cc.IdClient
inner join dbo.tranzactii t on t.Cont=cc.Cont
where t.IdTipTranzactie<>1
2.
84
The object 'Conturi_Tranz_Clienti' is dependent on column 'Nume'.
Msg 4922, Level 16, State 9, Line 2
ALTER TABLE ALTER COLUMN Nume failed because one or more objects access this column.
Corect:
use bank;
go
as
select
c.Nume
,cc.Cont
,cc.Balanta
,t.IdTranzactie
,t.DataTranzactie
,t.Valoare
from dbo.clienti c
inner join dbo.conturi cc on c.IdClient=cc.IdClient
inner join dbo.tranzactii t on t.Cont=cc.Cont
where t.IdTipTranzactie<>1
85
- Sa se extraga din view doar informatiile pentru conturile de tip Credit.
6. Sa se modifice view-ul creat la punctul 5 astfel incat conturile de tip Debit sa nu fie
considerate. Sa se verifice view-ul.
86