Sei sulla pagina 1di 105

Chapter 2.

Single-Table Queries
In this chapter: Elements of the SELECT Statement Pre icates an !perators 25 5" 5% 5( )2 ). /5 (2 22 22 2)

C#SE E$pressions &'LLs #ll-#t-!nce !perations *or+ing ,ith Character -ata *or+ing ,ith -ate an -ata Quer0ing 1eta ata Conclusion E$ercises Solutions Time

This chapter intro uces 0ou to the fun amentals of the SELECT statement3 focusing for no, on 4ueries against a single table. The chapter starts b0 escribing logical 4uer0 processingnamel03 the series of logical phases in5ol5e in pro ucing the correct result set of a gi5en SELECT 4uer0. The chapter then co5ers other aspects of single-table 4ueries3 inclu ing operators3 &'LLs3 manipulation of character an temporal ata3 ran+ing3 C#SE e$pressions3 an 4uer0ing meta ata. 1an0 of the co e samples an e$ercises in this boo+ use a sample atabase calle TSQL6un amentals277(. 8ou can fin the instructions for o,nloa ing an installing this sample atabase in #ppen i$ #3 9:etting Starte .9

Elements of the SELECT Statement


The purpose of a SELECT statement is to 4uer0 tables3 appl0 some logical manipulation3 an return a result. In this section3 I tal+ about the phases in5ol5e in logical 4uer0 processing. I escribe the logical

or er in ,hich the ifferent 4uer0 clauses are processe 3 an happens in each phase.

,hat

&ote that b0 9logical 4uer0 processing39 I;m referring to the conceptual ,a0 #&SI SQL efines that a 4uer0 shoul be processe an the final result achie5e . -on;t be alarme if some logical processing phases that I;ll escribe here seem inefficient. The 1icrosoft SQL Ser5er engine oesn;t ha5e to follo, logical 4uer0 processing to the letter< rather3 it is free to ph0sicall0 process a 4uer0 ifferentl0 b0 rearranging processing phases3 as long as the final result ,oul be the same as ictate b0 logical 4uer0 processing. SQL Ser5er canan in fact often oesma+e man0 shortcuts in the ph0sical processing of a 4uer0. To escribe logical 4uer0 processing an the 5arious SELECT 4uer0 clauses3 I use the 4uer0 in Listing 2-" as an e$ample. 6or no,3 on;t ,orr0 about un erstan ing ,hat this 4uer0 oes< I;ll e$plain the 4uer0 clauses one at a time3 an gra uall0 buil this 4uer0.
Listing 2-". Sample Quer0

'SE TSQL6un amentals277(< SELECT empi 3 8E#=>or er ate? #S or er0ear3 C!'&T>@? #S numor ers 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate? A#DI&: C!'&T>@? E " !=-E= C8 empi 3 or er0ear<

The co e starts ,ith a 'SE statement that sets the atabase conte$t of 0our session to the TSQL6un amentals277( sample atabase. If 0our session is alrea 0 in the conte$t of the atabase 0ou nee to 4uer03 the 'SE statement is not re4uire . Cefore getting into the etails of each phase of the SELECT statement3 notice the or er in ,hich the 4uer0 clauses are logicall0 processe . In most programming languages the lines of co e are processe in the or er that the0 are ,ritten. In SQL things are ifferent. E5en though the SELECT clause appears first in the

4uer03 it is logicall0 processe almost last. The clauses are logicall0 processe in the follo,ing or er: ". 2. .. %. 5. ). 6=!1 *AE=E :=!'P C8 A#DI&: SELECT !=-E= C8

So e5en though s0ntacticall0 our sample 4uer0 in Listing 2-" starts ,ith a SELECT clause3 logicall0 its clauses are processe in the follo,ing or er: 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate? A#DI&: C!'&T>@? E " SELECT empi 3 8E#=>or er ate? #S or er0ear3 C!'&T>@? #S numor ers !=-E= C8 empi 3 or er0ear

!r to present it in a more rea able manner3 here;s ,hat our statement oes: ". 2. .. %. Queries the ro,s from the Sales.!r ers table 6ilters onl0 or ers ,here the customer I- is e4ual to /" :roups the or ers b0 emplo0ee I- an or er 0ear 6ilters onl0 groups >emplo0ee I- an or er 0ear? ha5ing more than one or er 5. Selects >returns? for each group the emplo0ee I-3 or er 0ear3 an number of or ers ). !r ers >sorts? the ro,s in the output b0 emplo0ee I- an or er 0ear 'nfortunatel03 ,e cannot ,rite the 4uer0 in correct logical or er. *e ha5e to start ,ith the SELECT clause as sho,n in Listing 2-". &o, that 0ou un erstan the or er in ,hich the 4uer0 clauses are logicall0 processe 3 the ne$t sections e$plain the etails of each phase.

*hen iscussing logical 4uer0 processing3 I refer to 4uer0 clauses an 4uer0 phases3 >the *AE=E clause an the *AE=E phase3 for e$ample?. # 4uer0 clause is a s0ntactical component of a 4uer03 so ,hen iscussing the s0nta$ of a 4uer0 element I usuall0 use the term clause >for e$ample3 9In the *AE=E clause 0ou specif0 a pre icate.9?. *hen iscussing the logical manipulation ta+ing place as part of logical 4uer0 processing3 I usuall0 use the term phase >for e$ample3 9The *AE=E phase returns ro,s for ,hich the pre icate e5aluates to T='E9?. =ecall m0 recommen ation from the pre5ious chapter regar ing the use of a semicolon to terminate statements. SQL Ser5er oesn;t re4uire 0ou to terminate all statements ,ith a semicolon. This is a re4uirement onl0 in particular cases ,here the meaning of the co e might other,ise be ambiguous. Ao,e5er3 I recommen that 0ou terminate all statements ,ith a semicolon because it is stan ar 3 it impro5es the co e rea abilit03 an it is li+el0 that SQL Ser5er ,ill re4uire this in more cases in the future. Currentl03 ,hen a semicolon is not re4uire 3 a ing one oesn;t interfere. Therefore I recommen that 0ou ma+e it a practice to terminate all statements ,ith a semicolon. The 6=!1 Clause The 6=!1 clause is the 5er0 first 4uer0 clause that is logicall0 processe . In this clause 0ou specif0 the names of the tables that 0ou ,ant to 4uer0 an table operators that operate on those tables. This chapter oesn;t get into table operators< I escribe those in Chapter 53 9Table E$pressions9. 6or no,3 the 6=!1 clause is simpl0 ,here 0ou specif0 the name of the table 0ou ,ant to 4uer0. The sample 4uer0 in Listing 2-" 4ueries the !r ers table in the Sales schema3 fin ing (.7 ro,s sho,n in the output belo,: 6=!1 Sales.!r ers

=ecall the recommen ation I ga5e in the pre5ious chapter to al,a0s schema-4ualif0 obFect names in 0our co e. *hen 0ou on;t specif0 the schema name e$plicitl03 SQL Ser5er must resol5e it implicitl0. This creates some minor cost3 an also lea5es it to SQL Ser5er to eci e ,hich obFect to use in case of ambiguit0. C0 being e$plicit3 0ou ensure that 0ou get the obFect that 0ou inten e to get3 an that 0ou on;t pa0 an0 unnecessar0 penalties.

To return all ro,s from a table ,ith no special manipulation3 all 0ou nee is a 4uer0 ,ith a 6=!1 clause ,here 0ou specif0 the table 0ou ,ant to 4uer03 an a SELECT clause ,here 0ou specif0 the attributes 0ou ,ant to return. 6or e$ample3 the follo,ing statement 4ueries all ro,s from the !r ers table in the Sales schema3 selecting the attributes or eri 3 custi 3 empi 3 or er ate3 an freight: SELECT or eri 3 custi 3 empi 3 or er ate3 freight 6=!1 Sales.!r ers<

The output of this statement is sho,n here in abbre5iate

form:

Co e Die,: Scroll G Sho, #ll or eri custi empi or er ate freight ----------- ----------- ----------------------------------------------------"72%( (5 5 277)-7/-7% 77:77:77.777 .2..( "72%2 /2 ) 277)-7/-75 77:77:77.777 "".)" "7257 .% % 277)-7/-7( 77:77:77.777 )5.(. "725" (% . 277)-7/-7( 77:77:77.777 %"..% "7252 /) % 277)-7/-72 77:77:77.777 5"..7 "725. .% . 277)-7/-"7 77:77:77.777 5(."/ "725% "% 5 277)-7/-"" 77:77:77.777 22.2( "7255 )( 2 277)-7/-"2 77:77:77.777 "%(... "725) (( . 277)-7/-"5 77:77:77.777 "..2/ "725/ .5 % 277)-7/-") 77:77:77.777 (".2" ... >(.7 ro,>s? affecte ?

#lthough it might seem that the output of the 4uer0 is returne in a particular or er3 this is not guarantee . I;ll elaborate on this point later in the chapter in the sections 9The SELECT Clause9 an 9The !=-E= C8 Clause.9

-elimiting I entifier &ames


#s long as i entifiers in 0our 4uer0 compl0 ,ith rules for the format of regular i entifiers3 0ou on;t nee to elimit the i entifier names use for schemas3 tables3 an columns. The rules for the format of regular i entifiers can be foun in SQL Ser5er Coo+s !nline un er 9I entifiers.9 If an i entifier is irregularfor e$ample3 has embe e spaces or special characters3 starts ,ith a igit3 or is a reser5e +e0,or 0ou ha5e to elimit it. 8ou can elimit i entifiers in SQL Ser5er in a couple of ,a0s. The #&SI SQL form is to use ouble 4uotesfor e$ample3 9!r er -etails9. The SQL Ser5er specific form is to use s4uare brac+etsfor e$ample3 H!r er -etailsI3 but it also supports the stan ar form. *ith i entifiers that o compl0 ,ith the rules for the format of regular i entifiers3 elimiting is optional. 6or e$ample3 a table calle !r er -etails resi ing in the Sales schema can be referre to as Sales. 9!r er -etails9 or 9Sales9. 9!r er -etails9. 10 personal preference is not to use elimiters ,hen the0 are not re4uire because the0 ten to clutter the co e. #lso3 ,hen 0ou;re in charge of assigning i entifiers3 I recommen al,a0s using regular ones3 for e$ample3 !r er-etails instea of !r er -etails.

The *AE=E Clause In the *AE=E clause3 0ou specif0 a pre icate or logical e$pression to filter the ro,s returne b0 the 6=!1 phase. !nl0 ro,s for ,hich the logical e$pression e5aluates to T='E are returne b0 the *AE=E phase to the subse4uent logical 4uer0 processing phase. In

the sample 4uer0 in Listing 2-"3 the *AE=E phase filters onl0 or ers place b0 customer /": 6=!1 Sales.!r ers *AE=E custi B /"

!ut of the (.7 ro,s returne b0 the 6=!1 phase3 the *AE=E phase filters onl0 the ." ro,s ,here the customer I- is e4ual to /". To see ,hich ro,s 0ou get bac+ after appl0ing the filter custi B /"3 run the follo,ing 4uer0: SELECT or eri 3 empi 3 or er ate3 freight 6=!1 Sales.!r ers *AE=E custi B /"<

This 4uer0 generates the follo,ing output: Co e Die,: Scroll G Sho, #ll or eri empi or er ate ----------- ----------------------------------------------------"7.2% 2 277)-"7-7( 77:77:77.777 "7.2. " 277)-"2-25 77:77:77.777 "7.2( 2 277)-"2-.7 77:77:77.777 "7%%7 % 277/-72-"7 77:77:77.777 "7%52 ( 277/-72-27 77:77:77.777 "75"7 ) 277/-7%-"( 77:77:77.777 "7555 ) 277/-7)-72 77:77:77.777 "7)7. ( 277/-7/-"( 77:77:77.777 "7)7/ 5 277/-7/-22 77:77:77.777 "7)"2 " 277/-7/-2( 77:77:77.777 "7)2/ ( 277/-7(-"" 77:77:77.777 "7)5/ 2 277/-72-7% 77:77:77.777 "7)/( / 277/-72-2. 77:77:77.777 "7/77 . 277/-"7-"7 77:77:77.777 "7/"" 5 277/-"7-2" 77:77:77.777 "7/". " 277/-"7-22 77:77:77.777 "7/"% 5 277/-"7-22 77:77:77.777 "7/22 ( 277/-"7-22 77:77:77.777 "7/%( . 277/-""-27 77:77:77.777 "7/5/ ) 277/-""-2/ 77:77:77.777

freight

2"%.2/ "2).5) (2.") ().5. "%7.2) .)/.). 252.%2 %(.// 277.2% 5%%.7( "7/.%) .52.)2 .((.2( )5."7 52.%" ")/.75 2%.%2 /%.5( 2.2.55 (."2

"7("5 "7(%/ "7((2 "7(2% "72%" "72(. "72(% ""772 ""7.7 ""7." ""7)%

2 % % " / 2 " % / ) "

277(-7"-75 277(-7"-22 277(-72-"" 277(-72-"( 277(-7.-"" 277(-7.-2/ 277(-7.-.7 277(-7%-7) 277(-7%-"/ 277(-7%-"/ 277(-75-7"

77:77:77.777 77:77:77.777 77:77:77.777 77:77:77.777 77:77:77.777 77:77:77.777 77:77:77.777 77:77:77.777 77:77:77.777 77:77:77.777 77:77:77.777

"%.)2 %(/.5/ 2.."7 "").". %77.(" )5/.5% 2"".22 "%".") (.7./5 22/.22 .7.72

>." ro,>s? affecte ?

The *AE=E clause has significance ,hen it comes to 4uer0 performance. Case on ,hat 0ou ha5e in the filter e$pression3 SQL Ser5er e5aluates the use of in e$es to access the re4uire ata. C0 using in e$es3 SQL Ser5er can sometimes get the re4uire ata ,ith much less ,or+ compare to appl0ing full table scans. Quer0 filters also re uce the net,or+ traffic create b0 returning all possible ro,s to the caller an filtering on the client si e. Earlier I mentione that onl0 ro,s for ,hich the logical e$pression e5aluates to T='E are returne b0 the *AE=E phase. #l,a0s +eep in min that T-SQL uses three-5alue pre icate logic3 ,here logical e$pressions can e5aluate to T='E3 6#LSE3 or '&J&!*&. *ith three-5alue logic3 sa0ing 9returns T='E9 is not the same as sa0ing 9 oes not return 6#LSE.9 The *AE=E phase returns ro,s for ,hich the logical e$pression e5aluates to T='E3 an oesn;t return ro,s for ,hich the logical e$pression e5aluates to 6#LSE or '&J&!*&. I elaborate on this point later in this chapter in the section 9&'LLs.9 The :=!'P C8 Clause The :=!'P C8 phase allo,s 0ou to arrange the ro,s returne b0 the pre5ious logical 4uer0 processing phase in groups. The groups are etermine b0 the elements 0ou specif0 in the :=!'P C8 clause. 6or e$ample3 the :=!'P C8 clause in the 4uer0 in Listing 2-" has the elements empi an 8E#=>or er ate?:

6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate?

This means that the :=!'P C8 phase pro uces a group for each uni4ue combination of emplo0ee I- an or er 0ear 5alues that appears in the ata returne b0 the *AE=E phase. The e$pression 8E#=>or er ate? in5o+es the 8E#= function to return onl0 the 0ear part from the or er ate column. The *AE=E phase returne ." ro,s3 ,ithin ,hich there are ") uni4ue combinations of emplo0ee I- an or er 0ear 5alues3 as sho,n here: empi 8E#=>or er ate? ----------- --------------" 277) " 277/ " 277( 2 277) 2 277/ 2 277( . 277/ % 277/ % 277( 5 277/ ) 277/ ) 277( / 277/ / 277( ( 277/ 2 277)

Thus the :=!'P C8 phase creates ") groups3 an associates each of the ." ro,s returne from the *AE=E phase ,ith the rele5ant group. If the 4uer0 in5ol5es grouping3 all phases subse4uent to the :=!'P C8 phaseinclu ing A#DI&:3 SELECT3 an !=-E= C8must operate on groups as oppose to operating on in i5i ual ro,s. Each group is ultimatel0 represente b0 a single ro, in the final result of the 4uer0. This implies that all e$pressions that 0ou specif0 in clauses

that are processe in subse4uent phases to the :=!'P C8 phase are re4uire to guarantee returning a scalar >single 5alue? per group. E$pressions base on elements that participate in the :=!'P C8 list meet the re4uirement because b0 efinition each group has onl0 one uni4ue occurrence of each :=!'P C8 element. 6or e$ample3 in the group for emplo0ee I- ( an or er 0ear 277/3 there;s onl0 one uni4ue emplo0ee I- 5alue an onl0 one uni4ue or er 0ear 5alue. Therefore3 0ou;re allo,e to refer to the e$pressions empi an 8E#=>or er ate? in clauses that are processe in phases subse4uent to the :=!'P C8 phase3 such as the SELECT clause. The follo,ing 4uer03 for e$ample3 returns ") ro,s for the ") groups of emplo0ee I- an or er 0ear 5alues: SELECT empi 3 8E#=>or er ate? #S or er0ear 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate?<

This 4uer0 returns the follo,ing output: empi or er0ear ----------- ----------" 277) " 277/ " 277( 2 277) 2 277/ 2 277( . 277/ % 277/ % 277( 5 277/ ) 277/ ) 277( / 277/ / 277( ( 277/ 2 277) >") ro,>s? affecte ?

Cecause an aggregate function returns a single 5alue per group3 elements that o not participate in the :=!'P C8 list are onl0 allo,e as inputs to an aggregate function such as C!'&T3 S'13 #D:3 1I&3 or 1#K. 6or e$ample3 the follo,ing 4uer0 returns the total freight an number of or ers per each emplo0ee an or er 0ear: SELECT empi 3 8E#=>or er ate? #S or er0ear3 S'1>freight? #S totalfreight3 C!'&T>@? #S numor ers 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate?<

This 4uer0 generates the follo,ing output: empi or er0ear totalfreight numor ers ----------- ------------------------------- ----------" 277) "2).5) " 2 277) (2.") " 2 277) 2"%.2/ " " 277/ /"".". 2 2 277/ .52.)2 " . 277/ 22/.)5 2 % 277/ ().5. " 5 277/ 2//."% . ) 277/ )2(.." . / 277/ .((.2( " ( 277/ ./".7/ % " 277( .5/.%% . 2 277( )/2.") 2 % 277( )5".(. . ) 277( 22/.22 " / 277( "2.".5) 2 >") ro,>s? affecte ?

The e$pression S'1>freight? returns the sum of all freight 5alues in each group3 an the function C!'&T>@? returns the count of ro,s

in each group,hich in our case means number of or ers. If 0ou tr0 to refer to an attribute that oes not participate in the :=!'P C8 list >such as freight? an not as an input to an aggregate function in an0 clause that is processe after the :=!'P C8 clause3 0ou get an errorin such a case there;s no guarantee that the e$pression ,ill return a single 5alue per group. 6or e$ample3 the follo,ing 4uer0 ,ill fail: SELECT empi 3 8E#=>or er ate? #S or er0ear3 freight 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate?<

SQL Ser5er pro uces the follo,ing error: Co e Die,: Scroll G Sho, #ll 1sg ("273 Le5el ")3 State "3 Line " Column ;Sales.!r ers.freight; is in5ali in the select list because it is not containe in either an aggregate function or the :=!'P C8 clause.

&ote that all aggregate functions ignore &'LLs ,ith one e$ception C!'&T>@?. 6or e$ample3 consi er a group of fi5e ro,s ,ith the 5alues .73 "73 &'LL3 "73 "7 in a column calle 4t0. The e$pression C!'&T>@? ,oul return 5 because there are fi5e ro,s in the group3 ,hile C!'&T>4t0? ,oul return % because there are four +no,n 5alues. If 0ou ,ant to han le onl0 istinct occurrences of +no,n 5alues3 specif0 the -ISTI&CT +e0,or in the parentheses of the aggregate function. 6or e$ample3 the e$pression C!'&T>-ISTI&CT 4t0? ,oul return 2 since there are t,o istinct +no,n 5alues. The -ISTI&CT +e0,or can be use ,ith other functions as ,ell. 6or e$ample3 ,hile the e$pression S'1>4t0? ,oul return )73 the e$pression S'1>-ISTI&CT 4t0? ,oul return %7. The e$pression #D:>4t0? ,oul return "5 ,hile the e$pression #D:>-ISTI&CT 4t0? ,oul return 27. #s an e$ample of using the -ISTI&CT option ,ith an aggregate function in a complete 4uer03 the follo,ing co e returns the number of istinct > ifferent? customers han le b0 each emplo0ee in each or er 0ear: SELECT

empi 3 8E#=>or er ate? #S or er0ear3 C!'&T>-ISTI&CT custi ? #S numcusts 6=!1 Sales.!r ers :=!'P C8 empi 3 8E#=>or er ate?<

This 4uer0 generates the follo,ing output: Co e Die,: Scroll G Sho, #ll empi or er0ear numcusts ----------- ----------- ----------" 277) 22 2 277) "5 . 277) ") % 277) 2) 5 277) "7 ) 277) "5 / 277) "" ( 277) "2 2 277) 5 " 277/ %7 2 277/ .5 . 277/ %) % 277/ 5/ 5 277/ ". ) 277/ 2% / 277/ .7 ( 277/ .) 2 277/ ") " 277( .2 2 277( .% . 277( .7 % 277( .. 5 277( "" ) 277( "/ / 277( 2" ( 277( 2. 2 277( ") >2/ ro,>s? affecte ?

The A#DI&: Clause *ith the A#DI&: clause 0ou can specif0 a pre icateGlogical e$pression to filter groups as oppose to filtering in i5i ual ro,s3 ,hich happens in the *AE=E phase. !nl0 groups for ,hich the logical e$pression in the A#DI&: clause e5aluates to T='E are returne b0 the A#DI&: phase to the ne$t logical 4uer0 processing phase. :roups for ,hich the logical e$pression e5aluates to 6#LSE or '&J&!*& are filtere out. Cecause the A#DI&: clause is processe after the ro,s ha5e been groupe 3 0ou can refer to aggregate functions in the logical e$pression. 6or e$ample3 in the 4uer0 from Listing 2-" the A#DI&: clause has the logical e$pression C!'&T>@? E "3 meaning that the A#DI&: phase filters onl0 groups >emplo0ee an or er 0ear? ,ith more than one ro,. The follo,ing fragment of the Listing 2-" 4uer0 sho,s ,hat steps ha5e been processe so far: 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate? A#DI&: C!'&T>@? E "

=ecall that the :=!'P C8 phase create ") groups of emplo0ee Ian or er 0ear. Se5en of those groups ha5e onl0 one ro,3 so after the A#DI&: clause is processe 3 nine groups remain. =un the follo,ing 4uer0 to return those nine groups: SELECT empi 3 8E#=>or er ate? #S or er0ear 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate? A#DI&: C!'&T>@? E "<

This 4uer0 returns the follo,ing output: empi or er0ear ----------- ----------" 277/ . 277/ 5 277/ ) 277/

( " 2 % /

277/ 277( 277( 277( 277(

>2 ro,>s? affecte ?

The SELECT Clause The SELECT clause is ,here 0ou specif0 the attributes >columns? that 0ou ,ant to return in the result table of the 4uer0. 8ou can base the e$pressions in the SELECT list on attributes from the 4uerie tables3 ,ith or ,ithout further manipulation. 6or e$ample3 the SELECT list in Listing 2-" has the follo,ing e$pressions: empi 3 8E#=>or er ate?3 an C!'&T>@?. If an e$pression refers to an attribute ,ith no manipulation3 such as empi 3 the name of the target attribute is the same as the name of the source attribute. 8ou can optionall0 assign 0our o,n name to the target attribute b0 using the #S clausefor e$ample3 empi #S emplo0eeLi . E$pressions that o appl0 manipulation3 such as 8E#=>or er ate?3 or are not base on a source attribute3 such as a call for the function C'==E&TLTI1EST#1P3 on;t ha5e a name in the result of the 4uer0 if 0ou on;t alias them. T-SQL allo,s a 4uer0 to return result columns ,ith no names in certain cases3 but the relational mo el oesn;t. It;s strongl0 recommen e that 0ou alias such e$pressions as 8E#=>or er ate? #S or er0ear so that all result attributes ha5e names. In this respect3 the result table returne from the 4uer0 ,oul be consi ere relational. T-SQL supports3 in a ition to the #S clause3 a couple of other forms ,ith ,hich 0ou can alias e$pressions3 but to me3 the #S clause seems the most rea able an intuiti5e form an therefore I recommen using it. I ,ill co5er the other forms for the sa+e of completeness an also in or er to escribe an elusi5e bug relate to one of them. Cesi es the form Me$pressionE #S MaliasE3 T-SQL also supports the forms MaliasE B Me$pressionE >alias e4uals e$pression?3 an Me$pressionE MaliasE >e$pression space alias?. #n e$ample of the former is or er0ear B 8E#=>or er ate?3 an an e$ample of the latter is 8E#=>or er ate? or er0ear. I fin the latter form in ,hich 0ou specif0 the e$pression follo,e b0 a space

an the alias3 particularl0 unclear3 an 0ou a5oi using it.

I strongl0 recommen

that

It is interesting to note that if b0 mista+e 0ou on;t specif0 a comma bet,een t,o column names in the SELECT list3 0our co e ,on;t fail. =ather SQL Ser5er ,ill assume that the secon name is an alias for the first column name. #s an e$ample3 suppose that 0ou ,ante to ,rite a 4uer0 that selects the or eri an or er ate columns from the Sales.!r ers table3 an b0 mista+e i n;t specif0 the comma bet,een the column names3 as follo,s: SELECT or eri or er ate 6=!1 Sales.!r ers<

This 4uer0 is consi ere s0ntacticall0 5ali 3 as if 0ou inten e to alias the or eri column as or er ate. In the output 0ou ,ill get onl0 one column hol ing the or er I-s3 ,ith the alias or er ate: or er ate ----------"72%( "72%2 "7257 "725" "7252 ... >(.7 ro,>s? affecte ?

It can be har to etect such a bug3 so the best 0ou can be alert ,hen ,riting co e.

o is to

*ith the a ition of the SELECT phase3 the follo,ing 4uer0 clauses from the 4uer0 in Listing 2-" ha5e been processe so far: SELECT empi 3 8E#=>or er ate? #S or er0ear3 C!'&T>@? #S numor ers 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate? A#DI&: C!'&T>@? E "

The SELECT clause pro uces the result table of the 4uer0. In the case of the 4uer0 in Listing 2-"3 the hea ing of the result table has the attributes empi 3 or er0ear3 an numor ers3 an the bo 0 has nine ro,s >one for each group?. =un the follo,ing 4uer0 to return those nine ro,s: SELECT empi 3 8E#=>or er ate? #S or er0ear3 C!'&T>@? #S numor ers 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate? A#DI&: C!'&T>@? E "<

This 4uer0 generates the follo,ing output: empi or er0ear numor ers ----------- ----------- ----------" 277/ 2 . 277/ 2 5 277/ . ) 277/ . ( 277/ % " 277( . 2 277( 2 % 277( . / 277( 2 >2 ro,>s? affecte ?

=emember that the SELECT clause is processe after the 6=!13 *AE=E3 :=!'P C83 an A#DI&: clauses. This means that aliases assigne to e$pressions in the SELECT clause o not e$ist as far as clauses that are processe before the SELECT clause are concerne . # 5er0 t0pical mista+e ma e b0 programmers ,ho are not familiar ,ith the correct logical processing or er of 4uer0 clauses is to refer to e$pression aliases in clauses that are processe prior to the SELECT clause. Aere;s an e$ample of such an in5ali attempt in the *AE=E clause: SELECT or eri 3 8E#=>or er ate? #S or er0ear 6=!1 Sales.!r ers *AE=E or er0ear E 277)<

!n the surface this 4uer0 might seem 5ali 3 but if 0ou consi er the fact that the column aliases are create in the SELECT phase ,hich is processe after the *AE=E phase0ou can see that the reference to the or er0ear alias in the *AE=E clause is in5ali . #n in fact3 SQL Ser5er pro uces the follo,ing error: 1sg 27/3 Le5el ")3 State "3 Line . In5ali column name ;or er0ear;.

!ne ,a0 aroun this problem is to repeat the e$pression 8E#=>or er ate? in both the *AE=E an the SELECT clauses: SELECT or eri 3 8E#=>or er ate? #S or er0ear 6=!1 Sales.!r ers *AE=E 8E#=>or er ate? E 277)<

It;s interesting to note that SQL Ser5er is capable of i entif0ing the repeate use of the same e$pression8E#=>or er ate?in the 4uer0. It onl0 nee s to be e5aluate or calculate once. The follo,ing 4uer0 is another e$ample of an in5ali reference to a column alias. The 4uer0 attempts to refer to a column alias in the A#DI&: clause3 ,hich is also processe before the SELECT clause: SELECT empi 3 8E#=>or er ate? #S or er0ear3 C!'&T>@? #S numor ers 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate? A#DI&: numor ers E "<

This 4uer0 fails ,ith an error sa0ing that the column name numor ers is in5ali . 8ou ,oul also nee to repeat the e$pression C!'&T>@? in both clauses: SELECT empi 3 8E#=>or er ate? #S or er0ear3 C!'&T>@? #S numor ers 6=!1 Sales.!r ers *AE=E custi B /"

:=!'P C8 empi 3 8E#=>or er ate? A#DI&: C!'&T>@? E "<

In the relational mo el3 operations on relations are base on relational algebra an result in a relation >a set?. In SQL3 things are a bit ifferent in the sense that a SELECT 4uer0 is not guarantee to return a true setnamel03 uni4ue ro,s ,ith no guarantee or er. To begin ,ith3 SQL oesn;t re4uire a table to 4ualif0 as a set. *ithout a +e03 uni4ueness of ro,s is not guarantee 3 in ,hich case the table isn;t a set< it;s a multiset or a bag. Cut e5en if the tables 0ou 4uer0 ha5e +e0s an 4ualif0 as sets3 a SELECT 4uer0 against the tables can still return a result ,ith uplicate ro,s. The term result set is often use to escribe the output of a SELECT 4uer03 but a result set oesn;t necessaril0 4ualif0 as a set in the mathematical sense. 6or e$ample3 e5en though the !r ers table is a set because uni4ueness is enforce ,ith a +e03 a 4uer0 against the !r ers table returns uplicate ro,s3 as sho,n in Listing 2-2:
Listing 2-2. Quer0 =eturning -uplicate =o,s

SELECT empi 3 8E#=>or er ate? #S or er0ear 6=!1 Sales.!r ers *AE=E custi B /"<

This 4uer0 generates the follo,ing output: Co e Die,: Scroll G Sho, #ll empi or er0ear ----------- ----------2 277) " 277) 2 277) % 277/ ( 277/ ) 277/ ) 277/ ( 277/ 5 277/ " 277/ ( 277/

2 / . 5 " 5 ( . ) 2 % % " / 2 " % / ) "

277/ 277/ 277/ 277/ 277/ 277/ 277/ 277/ 277/ 277( 277( 277( 277( 277( 277( 277( 277( 277( 277( 277(

>." ro,>s? affecte ?

SQL pro5i es the means to guarantee uni4ueness in the result of a SELECT statement in the form of a -ISTI&CT clause that remo5es uplicate ro,s3 as sho,n in Listing 2-.:
Listing 2-.. Quer0 ,ith a -ISTI&CT Clause

SELECT -ISTI&CT empi 3 8E#=>or er ate? #S or er0ear 6=!1 Sales.!r ers *AE=E custi B /"<

This 4uer0 generates the follo,ing output: empi or er0ear ----------- ----------" 277)

" " 2 2 2 . % % 5 ) ) / / ( 2

277/ 277( 277) 277/ 277( 277/ 277/ 277( 277/ 277/ 277( 277/ 277( 277/ 277)

>") ro,>s? affecte ?

!f the ." ro,s in the multiset returne b0 the 4uer0 in Listing 223 ") ro,s are in the set returne b0 the 4uer0 in Listing 2-. after remo5al of uplicates. SQL supports the use of an asteris+ >@? in the SELECT list to re4uest all attributes from the 4uerie tables instea of listing them e$plicitl03 as in the follo,ing e$ample: SELECT @ 6=!1 Sales.Shippers<

Such use of an asteris+ is a ba programming practice in most cases3 ,ith 5er0 fe, e$ceptions. It is recommen e that 0ou e$plicitl0 specif0 the list of attributes that 0ou nee e5en if 0ou nee all of the attributes from the 4uerie table. There are man0 reasons for this recommen ation. 'nli+e the relational mo el3 SQL +eeps or inal positions for columns base on the or er in ,hich the columns ,ere specifie in the C=E#TE T#CLE statement. C0 specif0ing SELECT @3 0ou;re guarantee to get the columns bac+ in or er base on their or inal positions. Client applications can refer to columns in the result b0 their or inal positions >a ba practice in its o,n right? instea of b0 name. #n0 schema changes applie to the tablesuch as a ing or remo5ing columns3 rearranging their or er3 an so onmight result in failures in the client application3 or

e5en ,orse3 logical bugs that ,ill go unnotice . C0 specif0ing the attributes that 0ou nee e$plicitl03 0ou al,a0s get the right ones3 as long as the columns e$ist in the table. If a column reference b0 the 4uer0 ,as roppe from the table3 0ou get an error an can fi$ 0our co e accor ingl0. Some people ,on er ,hether there;s an0 performance ifference bet,een specif0ing an asteris+ an e$plicitl0 listing column names. Some e$tra ,or+ ma0 be re4uire in resol5ing column names ,hen using the asteris+3 but it is usuall0 so negligible compare to other costs in5ol5e in the 4uer0 that it is unli+el0 to be notice . If there is an0 performance ifference3 as minor as it ma0 be3 it is most probabl0 in the fa5or of e$plicitl0 listing column names. Cecause that;s the recommen e practice an0,a03 it;s a ,in-,in situation. *ithin the SELECT clause 0ou are still not allo,e to refer to a column alias that ,as create in the same SELECT clause3 regar less of ,hether the e$pression that assigns the alias appears to the left or right of the e$pression that attempts to refer to it. 6or e$ample3 the follo,ing attempt is in5ali : SELECT or eri 3 8E#=>or er ate? #S or er0ear3 or er0ear N " #S ne$t0ear 6=!1 Sales.!r ers<

#s e$plaine earlier in this section3 one of the ,a0s aroun problem is to repeat the e$pression: SELECT or eri 3 8E#=>or er ate? #S or er0ear3 8E#=>or er ate? N " #S ne$t0ear 6=!1 Sales.!r ers<

this

The !=-E= C8 Clause The !=-E= C8 clause allo,s 0ou to sort the ro,s in the output for presentation purposes. In terms of logical 4uer0 processing3 !=-E= C8 is the 5er0 last clause to be processe . The sample 4uer0 sho,n in Listing 2-% sorts the ro,s in the output b0 emplo0ee I- an or er 0ear:

Listing 2-%. Quer0 -emonstrating the !=-E= C8 Clause

SELECT empi 3 8E#=>or er ate? #S or er0ear3 C!'&T>@? #S numor ers 6=!1 Sales.!r ers *AE=E custi B /" :=!'P C8 empi 3 8E#=>or er ate? A#DI&: C!'&T>@? E " !=-E= C8 empi 3 or er0ear<

This 4uer0 generates the follo,ing output: empi or er0ear numor ers ----------- ----------- ----------" 277/ 2 " 277( . 2 277( 2 . 277/ 2 % 277( . 5 277/ . ) 277/ . / 277( 2 ( 277/ % >2 ro,>s? affecte ?

!ne of the most important points to un erstan about SQL is that a table has no guarantee or er3 because a table is suppose to represent a set >or multiset if it has uplicates?3 an a set has no or er. This means that ,hen 0ou 4uer0 a table ,ithout specif0ing an !=-E= C8 clause3 the 4uer0 returns a table result3 an SQL Ser5er is free to return the ro,s in the output in an0 or er. The onl0 ,a0 for 0ou to guarantee that the ro,s in the result are sorte is to e$plicitl0 specif0 an !=-E= C8 clause. Ao,e5er3 if 0ou o specif0 an !=-E= C8 clause3 the result cannot 4ualif0 as a table because the or er of the ro,s in the result is guarantee . # 4uer0 ,ith an !=-E= C8 clause results in ,hat #&SI calls a cursor a nonrelational result ,ith or er guarantee among ro,s. 8ou;re probabl0 ,on ering ,h0 it matters ,hether a 4uer0 returns a table result or a cursor. Some language elements an operations in SQL e$pect to ,or+ ,ith table results of 4ueries an not ,ith cursors<

e$amples inclu e table e$pressions an co5er in etail later in the boo+.

set operations3 ,hich I

&otice that the !=-E= C8 clause refers to the column alias or er0ear3 ,hich ,as create in the SELECT phase. The !=-E= C8 phase is in fact the onl0 phase in ,hich 0ou can refer to column aliases create in the SELECT phase3 because it is the onl0 phase that is processe after the SELECT phase. *hen 0ou ,ant to sort b0 an e$pression in ascen ing or er3 0ou either specif0 #SC right after the e$pression3 such as or er0ear #SC3 or on;t specif0 an0thing after the e$pression because #SC is the efault. If 0ou ,ant to sort in escen ing or er3 0ou nee to specif0 -ESC after the e$pression3 such as or er0ear -ESC. SQL an T-SQL both allo, 0ou to specif0 in the !=-E= C8 clause or inal positions of columns base on the or er in ,hich the columns appear in the SELECT list. 6or e$ample3 in the 4uer0 in Listing 2-%3 instea of using: !=-E= C8 empi 3 or er0ear

8ou coul

use:

!=-E= C8 "3 2

Ao,e5er3 this is consi ere ba programming practice for a couple of reasons. 6irst3 in the relational mo el attributes on;t ha5e or inal positions an nee to be referre to b0 name. Secon 3 ,hen 0ou ma+e re5isions to the SELECT clause3 0ou might forget to ma+e the correspon ing re5isions in the !=-E= C8 clause. *hen 0ou use column names3 0our co e is safe from this t0pe of mista+e. T-SQL allo,s 0ou to specif0 elements in the !=-E= C8 clause that o not appear in the SELECT clause3 meaning that 0ou can sort b0 something that 0ou on;t necessaril0 ,ant to return in the output. 6or e$ample3 the follo,ing 4uer0 sorts the emplo0ee ro,s b0 hire ate ,ithout returning the hire ate attribute: SELECT empi 3 firstname3 lastname3 countr0 6=!1 A=.Emplo0ees !=-E= C8 hire ate<

Ao,e5er3 ,hen -ISTI&CT is specifie 3 0ou are restricte in the !=-E= C8 list onl0 to elements that appear in the SELECT list. The reasoning behin this restriction is that ,hen -ISTI&CT is specifie 3 a single result ro, might represent multiple source ro,s< therefore3 it might not be clear ,hich of the multiple possible 5alues in the !=-E= C8 e$pression shoul be use . Consi er the follo,ing in5ali 4uer0: SELECT -ISTI&CT countr0 6=!1 A=.Emplo0ees !=-E= C8 empi <

There are nine emplo0ees in the Emplo0ees table fi5e from the 'S# an four from the 'J. If 0ou omit the in5ali !=-E= C8 clause from this 4uer03 0ou get t,o ro,s bac+one for each istinct countr0. Cecause each countr0 appears in multiple ro,s in the source table3 an each such ro, has a ifferent emplo0ee I-3 the meaning of !=-E= C8 empi is not reall0 efine . The T!P !ption The T!P option is a proprietar0 T-SQL feature that allo,s 0ou to limit the number or percentage of ro,s that 0our 4uer0 returns. *hen an !=-E= C8 clause is specifie in the 4uer03 the T!P option relies on it to efine the logical prece ence among ro,s. 6or e$ample3 to return from the !r ers table the fi5e most recent or ers3 0ou ,oul specif0 T!P >5? in the SELECT clause an or er ate -ESC in the !=-E= C8 clause3 as sho,n in Listing 2-5:
Listing 2-5. Quer0 -emonstrating the T!P !ption

SELECT T!P >5? or eri 3 or er ate3 custi 3 empi 6=!1 Sales.!r ers !=-E= C8 or er ate -ESC<

This 4uer0 returns the follo,ing output: or eri or er ate custi empi

----------- -------------------------------------- ----------""7// 277(-75-7) 77:77:77.777 )5 " ""7/) 277(-75-7) 77:77:77.777 2 % ""7/5 277(-75-7) 77:77:77.777 )( ( ""7/% 277(-75-7) 77:77:77.777 /. / ""7/. 277(-75-75 77:77:77.777 5( 2 >5 ro,>s? affecte ?

In terms of logical 4uer0 processing3 the T!P option is processe as part of the SELECT phase3 right after the -ISTI&CT clause is processe >if one e$ists?. &ote that ,hen T!P is specifie in a 4uer0 the !=-E= C8 clause ser5es a ual purpose. That is3 as part of the SELECT phase the T!P option relies on the !=-E= C8 clause to etermine logical prece ence among ro,s3 an base on this prece ence filters as man0 as ,ere re4ueste . Later3 as part of the !=-E= C8 phase that follo,s the SELECT phase3 the 5er0 same !=-E= C8 clause is use to sort the ro,s in the output for presentation purposes. 6or e$ample3 the 4uer0 in Listing 2-5 returns the fi5e ro,s ,ith the highest or er ate 5alues3 an sorts the ro,s in the output b0 or er ate -ESC for presentation purposes. If 0ou;re confuse about ,hether a T!P 4uer0 returns a table result or a cursor3 0ou ha5e e5er0 reason to be. *hen T!P is use 3 the same !=-E= C8 clause ser5es both the purpose of etermining logical prece ence for T!P3 an the normal meaning presentationthat changes the nature of the result from a table to a cursor ,ith guarantee or er. 6or e$ample3 0ou can;t specif0 in the same 4uer0 that 0ou ,ant the logical prece ence among ro,s to be etermine b0 one !=-E= C8 list for the T!P option3 ,hile 0ou ,ant to sort the ro,s in the output for presentation purposes b0 another3 or not at all. To achie5e this3 0ou ha5e to use a table e$pression3 but I;ll sa5e the iscussion of table e$pressions for Chapter 5. #ll I ,ant to sa0 for no, is that if the esign of the T!P option seems confusing3 there;s a goo reason. In other ,or s3 it;s not 0ouit;s the feature;s esign. 8ou can use the T!P option ,ith the PE=CE&T +e0,or 3 in ,hich case SQL Ser5er calculates the number of ro,s to return base on a percentage of the number of 4ualif0ing ro,s3 roun e up. 6or

e$ample3 the follo,ing 4uer0 re4uests the top one percent of the most recent or ers: SELECT T!P >"? PE=CE&T or eri 3 or er ate3 custi 3 empi 6=!1 Sales.!r ers !=-E= C8 or er ate -ESC<

This 4uer0 generates the follo,ing output: or eri or er ate custi empi ----------- -------------------------------------- ----------""7/% 277(-75-7) 77:77:77.777 /. / ""7/5 277(-75-7) 77:77:77.777 )( ( ""7/) 277(-75-7) 77:77:77.777 2 % ""7// 277(-75-7) 77:77:77.777 )5 " ""7/7 277(-75-75 77:77:77.777 %% 2 ""7/" 277(-75-75 77:77:77.777 %) " ""7/2 277(-75-75 77:77:77.777 27 % ""7/. 277(-75-75 77:77:77.777 5( 2 ""7)/ 277(-75-7% 77:77:77.777 "/ " >2 ro,>s? affecte ?

The 4uer0 returns 2 ro,s because the !r ers table has (.7 ro,s3 an " percent of (.73 roun e up3 is 2. In the 4uer0 in Listing 2-53 0ou might ha5e notice that the !=-E= C8 list is not uni4ue because no primar0 +e0 or uni4ue constraint is efine on the or er ate column. 1ultiple ro,s can ha5e the same or er ate. In a case ,here no tiebrea+er is specifie 3 prece ence among ro,s in case of ties >ro,s ,ith the same or er ate? is un efine . This fact ma+es the 4uer0 non eterministic more than one result can be consi ere correct. In case of ties3 SQL Ser5er chooses ro,s base on ,hiche5er ro, it ph0sicall0 happens to access first. &otice in the output for the 4uer0 in Listing 2-5 that the minimum or er ate out of the ro,s returne is 1a0 53 277(3 an one ro, in the output has that ate. !ther ro,s in the table ma0 ha5e the same or er ate3 an ,ith the e$isting non-uni4ue !=-E= C8 list3 there is no guarantee ,hich of those ,ill be returne .

If 0ou ,ant the 4uer0 to be eterministic3 0ou nee to ma+e the !=-E= C8 list uni4ue< in other ,or s3 a a tiebrea+er. 6or e$ample3 0ou can a or eri -ESC to the !=-E= C8 list as sho,n in Listing 2-) so that in case of ties3 prece ence is etermine b0 or er I- escen ing:
Listing 2-). Quer0 -emonstrating T!P ,ith 'ni4ue !=-E= C8 List

SELECT T!P >5? or eri 3 or er ate3 custi 3 empi 6=!1 Sales.!r ers !=-E= C8 or er ate -ESC3 or eri -ESC<

This 4uer0 returns the follo,ing output: or eri or er ate custi empi ----------- --------------------------------------- ----------""7// 277(-75-7) 77:77:77.777 )5 " ""7/) 277(-75-7) 77:77:77.777 2 % ""7/5 277(-75-7) 77:77:77.777 )( ( ""7/% 277(-75-7) 77:77:77.777 /. / ""7/. 277(-75-75 77:77:77.777 5( 2 >5 ro,>s? affecte ?

If 0ou e$amine the results of the 4ueries from Listing 2-5 an Listing 2-)3 0ou;ll notice that the0 seem to be the same. The important ifference is that the result sho,n in the 4uer0 output for Listing 2-5 is one of se5eral possible 5ali results for this 4uer03 ,hile the result sho,n in the 4uer0 output for Listing 2-) is the onl0 possible 5ali result. Instea of a ing a tiebrea+er to the !=-E= C8 list3 0ou can re4uest to return all ties. 6or e$ample3 besi es the fi5e ro,s that 0ou get bac+ from the 4uer0 in Listing 2-53 0ou can as+ to return all other ro,s from the table that ha5e the same sort 5alue >or er ate in our case? as the last one foun >1a0 53 277( in our case?. 8ou achie5e this b0 a ing the *ITA TIES option as sho,n in the follo,ing 4uer0:

SELECT T!P >5? *ITA TIES or eri 3 or er ate3 custi 3 empi 6=!1 Sales.!r ers !=-E= C8 or er ate -ESC<

This 4uer0 returns the follo,ing output: or eri or er ate custi empi ----------- -------------------------------------- ----------""7// 277(-75-7) 77:77:77.777 )5 " ""7/) 277(-75-7) 77:77:77.777 2 % ""7/5 277(-75-7) 77:77:77.777 )( ( ""7/% 277(-75-7) 77:77:77.777 /. / ""7/. 277(-75-75 77:77:77.777 5( 2 ""7/2 277(-75-75 77:77:77.777 27 % ""7/" 277(-75-75 77:77:77.777 %) " ""7/7 277(-75-75 77:77:77.777 %% 2 >( ro,>s? affecte ?

&otice that the output has eight ro,s e5en though 0ou specifie T!P >5?. SQL Ser5er first returne the T!P >5? ro,s base on or er ate -ESC prece ence3 an also all other ro,s from the table that ha the same or er ate 5alue as in the last of the fi5e ro,s that ,as accesse . The !DE= Clause The !DE= clause e$poses a ,in o, of ro,s to certain +in s of calculations. Thin+ of a ,in o, of ro,s simpl0 as a certain set of ro,s that the calculation operates on. #ggregate an ran+ing functions3 for e$ample3 are the t0pes of calculations that support the !DE= clause. Cecause the !DE= clause e$poses a ,in o, of ro,s to those functions3 the0 are +no,n as ,in o, functions. Cecause the ,hole point of an aggregate function is to aggregate a set of 5alues3 aggregate functions tra itionall0 operate in the conte$t of :=!'P C8 4ueries. =ecall from earlier iscussions in the section 9The :=!'P C8 Clause9 that once 0ou group ata3 the 4uer0 returns onl0 one ro, for each group< therefore3 all 0our e$pressions are restricte to returning a single 5alue per group.

#n aggregate ,in o, function operates against a set of 5alues in a ,in o, of ro,s that 0ou e$pose to it using the !DE= clause3 an not in the conte$t of a :=!'P C8 4uer0. Therefore3 0ou on;t ha5e to group the ata3 an 0ou can return base ro, attributes an aggregates in the same ro,. To un erstan the !DE= clause3 thin+ of the Sales.!r erDalues 5ie,. I ,ill iscuss 5ie,s in Chapter "73 9Programmable !bFects39 but for no,3 simpl0 thin+ of a 5ie, as if it ,ere a table. The Sales.!r erDalues 5ie, has a ro, for each or er3 ,ith the or er I>or eri ?3 customer I- >custi ?3 emplo0ee I- >empi ?3 shipper I>shipperi ?3 or er ate >or er ate? an or er 5alue >5al?. #n !DE= clause ,ith empt0 parentheses e$poses all ro,s to the calculation. The phrase 9all ro,s9 oesn;t necessaril0 mean all ro,s from the table that appears in the 6=!1 clause< rather the ro,s e$pose are those a5ailable after the 6=!13 *AE=E3 :=!'P C8 an A#DI&: phases are complete . &ote that the !DE= clause is allo,e onl0 in the SELECT an !=-E= C8 phases. In or er not to o5er,helm 0ou ,ith too much information at this earl0 stage3 I;ll focus on using the !DE= clause in the SELECT phase. So3 for e$ample3 if 0ou specif0 the e$pression S'1>5al? !DE=>? in the SELECT clause of a 4uer0 against the !r erDalues 5ie,3 the function calculates the total 5alue out of all ro,s that the SELECT phase operates on. If the 4uer0 oesn;t filter ata or appl0 an0 other logical phases before the SELECT phase3 the e$pression returns the total 5alue out of all !r erDalues ro,s. If 0ou ,ant to restrict or partition the ro,s3 0ou can use the P#=TITI!& C8 clause. 6or e$ample3 if instea of returning the total 5alue of all !r erDalues ro,s3 0ou ,ant to return the total 5alue of the current customer >out of all ro,s ,ith the same custi as in the current ro,?3 specif0 S'1>5al? !DE=>P#=TITI!& C8 custi ?. To emonstrate both nonpartitione an partitione e$pressions3 the follo,ing 4uer0 returns all !r erDalues ro,s. # itionall03 in each ro, e$cept for the base attributes3 the 4uer0 returns the gran total 5alue an the customer total 5alue: SELECT or eri 3 custi 3 5al3 S'1>5al? !DE=>? #S total5alue3 S'1>5al? !DE=>P#=TITI!& C8 custi ? #S custtotal5alue 6=!1 Sales.!r erDalues<

This 4uer0 returns the follo,ing output: or eri custi 5al total5alue custtotal5alue ----------- ----------- --------------------------- --------------"7)%. " ("%.57 "2)5/2..22 %2/..77 "7)22 " (/(.77 "2)5/2..22 %2/..77 "7/72 " ..7.77 "2)5/2..22 %2/..77 "7(.5 " (%5.(7 "2)5/2..22 %2/..77 "7252 " %/".27 "2)5/2..22 %2/..77 ""7"" " 2...57 "2)5/2..22 %2/..77 "722) 2 5"%.%7 "2)5/2..22 "%72.25 "7/52 2 .27.77 "2)5/2..22 "%72.25 "7)25 2 %/2./5 "2)5/2..22 "%72.25 "7.7( 2 ((.(7 "2)5/2..22 "%72.25 "7.)5 . %7..27 "2)5/2..22 /72..2( ... >(.7 ro,>s? affecte ?

The total5alue column has3 in all result ro,s3 the total 5alue out of all ro,s. The custtotal5alue column has the total 5alue out of all ro,s that ha5e the same custi 5alue as in the current ro,. !ne benefit of the !DE= clause is that b0 enabling 0ou to return base ro, attributes an aggregate them in the same ro,3 it also enables 0ou to ,rite e$pressions that mi$ the t,o. 6or e$ample3 the follo,ing 4uer0 calculates for each !r erDalues ro, the percentage of the current 5alue out of the gran total3 an also the percentage of the current 5alue out of the customer total: SELECT or eri 3 custi 3 5al3 "77. @ 5al G S'1>5al? !DE=>? #S pctall3 "77. @ 5al G S'1>5al? !DE=>P#=TITI!& C8 custi ? #S pctcust 6=!1 Sales.!r erDalues<

&ote that the reason that I specifie the ecimal 5alue "77. >one hun re ot? in the e$pressions instea of the integer "77 is in or er to cause implicit con5ersion of the integer 5alues 5al an S'1>5al? to ecimal 5alues. !ther,ise3 the i5ision ,oul ha5e been an integer i5ision an the fractional part ,oul ha5e been truncate .

This 4uer0 returns the follo,ing output: Co e Die,: Scroll G Sho, #ll or eri custi 5al pctall pctcust ------------ ------ ------------------------------------------------------------------"7)%. " ("%.57 7.7)%.%/77227"%)2")/22%" "2.7)"5%22)2(".7""2.5%7(. "7)22 " (/(.77 7.7)2.).)277/75(.722552( 27.5%/)2%)"2/75"2527%//%" "7/72 " ..7.77 7.72)7/7)7(2"7.55(.2752( /./222"".7.5..(")227%7%( "7(.5 " (%5.(7 7.7))("2/)7)55)2.(2)5")" "2./2%755)2(5/2%."5%)2225 "7252 " %/".27 7.7./225))2%57"(7("2.".7 "".72/.("2.72(525)2)72.(/ ""7"" " 2...57 7.7/./%(222%/(2..(%)"25. 2".(%)%//((%.27.5(7)225". "722) 2 5"%.%7 7.7%7).(5%2")27("2.2%"(" .).))552/%2"77""7%("%(5%% "7/52 2 .27.77 7.7252(7527%5(52)()/%%52 22.(727(7()5."2575.2(75(/ "7)25 2 %/2./5 7.7./27"".522)%2%5//752) .%."25(7"/7.55.22/"2(5575 "7.7( 2 ((.(7 7.77/7"5.).(522%"275/")7 )..225"22%7"2)")2/2(5.)2 "7.)5 . %7..27 7.7."(5.5%.2///%.(522(72 5./%7..525"52%7)%/7%75)) ... >(.7 ro,>s? affecte ?

The !DE= clause is also supporte ,ith four ran+ing functions: =!*L&'1CE=3 =#&J3 -E&SEL=#&J3 an &TILE. The follo,ing 4uer0 emonstrates the use of these functions: SELECT or eri 3 custi 3 5al3 =!*L&'1CE=>? !DE=>!=-E= C8 5al? #S ro,num3 =#&J>? !DE=>!=-E= C8 5al? #S ran+3 -E&SEL=#&J>? !DE=>!=-E= C8 5al? #S enseLran+3

&TILE>"77? !DE=>!=-E= C8 5al? #S ntile 6=!1 Sales.!r erDalues !=-E= C8 5al<

This 4uer0 generates the follo,ing output: Co e Die,: Scroll G Sho, #ll or eri custi 5al ro,num ran+ enseLran+ ntile ----------- ----------- --------- ------------- ---------- ----"7/(2 "2 "2.57 " " " " "7(7/ 2/ "(.%7 2 2 2 " "75() )) 2..(7 . . . " "7/)/ /) 2(.77 % % % " "7(2( 5% .7.77 5 5 5 " "7277 (( .../5 ) ) ) " "7((. %( .).77 / / / " ""75" %" .).77 ( / / " "7("5 /" %7.77 2 2 ( " "7)/% .( %5.77 "7 "7 2 " ... "7)2" ). "7")%.(7 (2" (2" /() "7 "75%7 ). "7"2"./7 (22 (22 /(/ "7 "7%/2 )5 "7%25.)7 (2. (2. /(( "7 "7(2/ ./ "7(.5.2% (2% (2% /(2 "7 "7("/ .2 "7252.(5 (25 (25 /27 "7 "7%"/ /. """((.%7 (2) (2) /2" "7 "7((2 )5 "".(7.77 (2/ (2/ /22 "7 ""7.7 /" "2)"5.75 (2( (2( /2. "7 "72(" .% "5("7.77 (22 (22 /2% "7 "7()5 ). ").(/.57 (.7 (.7 /25 "7 >(.7 ro,>s? affecte ?

The =!*L&'1CE= function assigns incrementing se4uential integers to the ro,s in the result set of a 4uer03 base on logical or er that is specifie in the !=-E= C8 subclause of the !DE= clause. In our sample 4uer03 the logical or er is base on the 5al column< therefore3 0ou can see in the output that ,hen the 5alue increases the ro, number increases as ,ell. Ao,e5er3 e5en ,hen the or ering

5alue oesn;t increase3 the ro, number still must increase. Therefore3 if the =!*L&'1CE= function;s !=-E= C8 list is nonuni4ue3 as in the prece ing e$ample3 the 4uer0 is non eterministic. That is3 more than one correct result is possible. 6or e$ample3 obser5e that t,o ro,s ,ith the 5alue .).77 got the ro, numbers / an (. #n0 arrangement of these ro, numbers ,oul ha5e been consi ere correct. If 0ou ,ant to ma+e a ro, number calculation eterministic3 0ou nee to a elements to the !=-E= C8 list to ma+e it uni4ue< meaning that the list of elements in the !=-E= C8 clause ,oul uni4uel0 i entif0 ro,s. 6or e$ample3 0ou can a the or eri column as a tiebrea+er to the !=-E= C8 list to ma+e the ro, number calculation eterministic. #s I mentione earlier3 the =!*L&'1CE= function must pro uce uni4ue 5alues e5en ,hen there are ties in the or ering 5alues. If 0ou ,ant to treat ties in the or ering 5alues the same ,a03 0ou ,ill probabl0 ,ant to use the =#&J or -E&SEL=#&J function instea . Coth are similar to the =!*L&'1CE= function3 but the0 pro uce the same ran+ing 5alue in all ro,s that ha5e the same logical or ering 5alue. The ifference bet,een =#&J an -E&SEL=#&J is that =#&J in icates ho, man0 ro,s ha5e a lo,er or ering 5alue3 ,hile -E&SEL=#&J in icates ho, man0 istinct or ering 5alues are lo,er. 6or e$ample3 in our sample 4uer03 a ran+ 2 in icates ( ro,s ,ith lo,er 5alues. # ense ran+ 2 in icates ( istinct lo,er 5alues. The &TILE function allo,s 0ou to associate the ro,s in the result ,ith tiles >e4uall0 siOe groups of ro,s? b0 assigning a tile number to each ro,. 8ou specif0 as input to the function ho, man0 tiles 0ou are after3 an in the !DE= clause 0ou specif0 the logical or ering. !ur sample 4uer0 has (.7 ro,s an the re4uest ,as for "7 tiles< therefore3 the tile siOe is (. >(.7 i5i e b0 "7?. Logical or ering is base on the 5al column. This means that the (. ro,s ,ith the lo,est 5alues are assigne ,ith tile number "3 the ne$t (. ,ith tile number 23 the ne$t (. ,ith tile number .3 an so on. The &TILE function is logicall0 relate to the =!*L&'1CE= function. It;s as if 0ou assigne ro, numbers to the ro,s base on 5al or ering3 an base on the calculate tile siOe (. assigne tile number " to ro,s " through (.3 tile number 2 to ro,s (% through "))3 an so on. If the number of ro,s oesn;t i5i e e5enl0 b0 the number of tiles3 from the remain er an e$tra ro, is a e to each of the first tiles. 6or e$ample3 if there ha been "72 ro,s an 5 tiles ,ere re4ueste 3 the first t,o tiles ,oul ha5e ha 2" ro,s instea of 27.

Li+e aggregate ,in o, functions3 ran+ing functions also support a P#=TITI!& C8 clause in the !DE= clause. It;s probabl0 eas0 to un erstan the meaning of the P#=TITI!& C8 clause in the conte$t of ran+ing calculations< thin+ of it as ma+ing the calculation in epen ent for each partition3 or ,in o,. 6or e$ample3 the e$pression =!*L&'1CE=>? !DE=>P#=TITI!& C8 custi !=-E= C8 5al? assigns ro, numbers for each subset of ro,s ,ith the same custi in epen entl03 as oppose to assigning those across the ,hole set. Aere;s the e$pression in a 4uer0: SELECT or eri 3 custi 3 5al3 =!*L&'1CE=>? !DE=>P#=TITI!& C8 custi !=-E= C8 5al? #S ro,num 6=!1 Sales.!r erDalues !=-E= C8 custi 3 5al<

This 4uer0 generates the follo,ing output: or eri custi 5al ro,num ----------- ----------- -----------------"7/72 " ..7.77 " "7252 " %/".27 2 "7)%. " ("%.57 . "7(.5 " (%5.(7 % "7)22 " (/(.77 5 ""7"" " 2...57 ) "7.7( 2 ((.(7 " "7/52 2 .27.77 2 "7)25 2 %/2./5 . "722) 2 5"%.%7 % "7)(2 . ./5.57 " ... >(.7 ro,>s? affecte ?

#s 0ou can see in the output3 the ro, numbers are calculate in epen entl0 for each customer3 as though the calculation ,ere reset for each customer. &ote that the logical !=-E= C8 specifie in the !DE= clause has nothing to o ,ith presentation3 an oes not change the nature of

the result from being a table. If 0ou o not specif0 a presentation !=-E= C8 in the 4uer03 as e$plaine earlier3 0ou on;t ha5e an0 guarantees in terms of the or er of the ro,s in the output. If 0ou nee to guarantee presentation or er3 0ou ha5e to a a presentation !=-E= C8 clause3 as I i in the last t,o 4ueries emonstrating the use of ran+ing functions. If specifie in the SELECT phase3 ,in o, calculations are processe before the -ISTI&CT clause >if one e$ists?. To put it all together3 the follo,ing list presents the logical or er in ,hich all clauses iscusse so far are processe :

6=!1 *AE=E :=!'P C8 A#DI&: SELECT o !DE= o -ISTI&CT o T!P !=-E= C8

#re 0ou ,on ering ,h0 it matters that the -ISTI&CT clause is processe after ,in o, calculations that appear in the SELECT clause are processe 3 an not beforeP I;ll e$plain ,ith an e$ample. Currentl0 the !r erDalues 5ie, has (.7 ro,s ,ith /25 istinct 5alues. Consi er the follo,ing 4uer0 an its output: SELECT -ISTI&CT 5al3 =!*L&'1CE=>? !DE=>!=-E= C8 5al? #S ro,num 6=!1 Sales.!r erDalues< 5al ro,num ---------- ------"2.57 " "(.%7 2 2..(7 . 2(.77 % .7.77 5 .../5 ) .).77 / .).77 ( %7.77 2

%5.77 ... "2)"5.75 "5("7.77 ").(/.57

"7 (2( (22 (.7

>(.7 ro,>s? affecte ?

The =!*L&'1CE= function is processe before the -ISTI&CT clause. 6irst3 uni4ue ro, numbers are assigne to the (.7 ro,s from the !r erDalues 5ie,. Then the -ISTI&CT clause is processe therefore3 no uplicate ro,s to remo5e. 8ou can consi er it a best practice not to specif0 both -ISTI&CT an =!*L&'1CE= in the same SELECT clause as the -ISTI&CT clause has no effect in such a case. If 0ou ,ant to assign ro, numbers to the /25 uni4ue 5alues3 0ou nee to come up ,ith a ifferent solution. 6or e$ample3 because the :=!'P C8 phase is processe before the SELECT phase3 0ou coul use the follo,ing 4uer0: SELECT 5al3 =!*L&'1CE=>? !DE=>!=-E= C8 5al? #S ro,num 6=!1 Sales.!r erDalues :=!'P C8 5al<

This 4uer0 generates the follo,ing output: 5al ro,num --------- ------"2.57 " "(.%7 2 2..(7 . 2(.77 % .7.77 5 .../5 ) .).77 / %7.77 ( %5.77 2 %(.77 "7 ... "2)"5.75 /2. "5("7.77 /2% ").(/.57 /25

>/25 ro,>s? affecte ?

Aere3 the :=!'P C8 phase pro uces /25 groups for the /25 istinct 5alues3 an then the SELECT phase pro uces a ro, for each group ,ith the 5alue an a ro, number base on 5al or er.

Pre icates an

!perators

T-SQL has ifferent language elements ,here logical e$pressions can be specifie for e$ample3 4uer0 filters such as *AE=E an A#DI&:3 CAECJ constraints3 an others. Logical e$pressions can ma+e use of 5arious pre icates >e$pressions that e5aluate to T='E3 6#LSE or '&J&!*&? an operators. E$amples for pre icates supporte b0 T-SQL inclu e I&3 CET*EE&3 an LIJE. The I& pre icate allo,s 0ou to chec+ ,hether a 5alue3 or scalar e$pression3 is e4ual to at least one of the elements in a set. 6or e$ample3 the follo,ing 4uer0 returns or ers ,here the or er Iis e4ual to "72%( or "72%2 or "7257: SELECT or eri 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or eri I&>"72%(3 "72%23 "7257?<

The CET*EE& pre icate allo,s 0ou to chec+ ,hether a 5alue is in a specifie range3 inclusi5e of the t,o specifie boun ar0 5alues. 6or e$ample3 the follo,ing 4uer0 returns all or ers in the range "7.77 through "7."7: SELECT or eri 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or eri CET*EE& "7.77 #&- "7."7<

The LIJE pre icate allo,s 0ou to chec+ ,hether a character string 5alue meets a specifie pattern. 6or e$ample3 the follo,ing 4uer0 returns emplo0ees ,hose last name starts ,ith -: SELECT empi 3 firstname3 lastname 6=!1 A=.Emplo0ees *AE=E lastname LIJE &;-Q;<

Later in the chapter I;ll elaborate on pattern matching an pre icate.

the LIJE

If 0ou;re curious about the use of the letter & to prefi$ the string ;-Q;3 it stan s for &ational an is use to enote that a character string is of a 'nico e ata t0pe >&CA#= or &D#=CA#=?3 as oppose to a regular character ata t0pe >CA#= or D#=CA#=?. Cecause the ata t0pe of the lastname attribute is &D#=CA#=>%7?3 the letter & is use to prefi$ the string. Later in the chapter3 in the section 9*or+ing ,ith Character -ata39 I elaborate on the treatment of character strings. T-SQL supports the follo,ing comparison operators: B3 E3 M3 EB3 MB3 ME3 RB3 RE3 RM3 out of ,hich the last three are not stan ar . Cecause the nonstan ar operators ha5e stan ar alternati5es >such as ME instea of RB?3 I recommen that 0ou a5oi the use of the nonstan ar operators. 6or e$ample3 the follo,ing 4uer0 returns all or ers place on or after Sanuar0 "3 277(: SELECT or eri 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or er ate EB ;277(7"7";<

If 0ou nee to combine logical e$pressions3 0ou can use the logical operators != an #&-. If 0ou ,ant to negate an e$pression3 0ou can use the &!T operator. 6or e$ample3 the follo,ing 4uer0 returns or ers place on or after Sanuar0 "3 277(3 an ,ere han le b0 one of the emplo0ees "3 .3 5: SELECT or eri 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or er ate EB ;277(7"7"; #&- empi I&>"3 .3 5?<

T-SQL supports the four ob5ious arithmetic operators: N3 3 @3 G3 an also the Q operator >mo ulo? that returns the remain er of integer i5ision. 6or e$ample3 the follo,ing 4uer0 calculates the net 5alue as a result of arithmetic manipulation of the 4uantit03 unitprice3 an iscount attributes: SELECT or eri 3 pro ucti 3 4t03 unitprice3 4t0 @ unitprice @ >" - iscount? #S 5al iscount3

6=!1 Sales.!r er-etails<

&ote that the ata t0pe of a scalar e$pression in5ol5ing t,o operan s is etermine in T-SQL b0 the higher of the t,o in terms of ata t0pe prece ence. If both operan s are of the same ata t0pe3 the result of the e$pression is of the same ata t0pe as ,ell. 6or e$ample3 a i5ision bet,een t,o integers >I&T? 0iel s an integer. The e$pression 5G2 returns the integer 2 an not the numeric 2.5. This is not a problem ,hen ealing ,ith constants because 0ou can al,a0s specif0 the 5alues as numeric ones ,ith a ecimal point. Cut ,hen ealing ,ith3 sa03 t,o integer columns3 such as col"Gcol23 0ou nee to cast the operan s to the appropriate t0pe if 0ou ,ant the calculation to be a numeric one: C#ST>col" #S &'1E=IC>"23 2??G C#ST>col2 #S &'1E=IC>"23 2??. The ata t0pe &'1E=IC>"23 2? has precision "2 an scale 23 meaning t,el5e igits in total3 t,o of ,hich are after the ecimal point. If the t,o operan s are of ifferent t0pes3 the one ,ith the lo,er prece ence is promote to the one that is higher. 6or e$ample3 in the e$pression 5G2.7 the first operan is I&T an the secon is &'1E=IC. Cecause &'1E=IC is consi ere higher than I&T3 the I&T operan 5 is implicitl0 con5erte to the &'1E=IC 5.7 before the arithmetic operation3 an 0ou get the result 2.5. 8ou can fin the prece ence or er among t0pes in SQL Ser5er Coo+s !nline un er 9-ata T0pe Prece ence.9 *hen multiple operators appear in the same e$pression3 SQL Ser5er e5aluates them base on operator prece ence rules. The follo,ing list has the prece ence among operators3 from highest to lo,est: ". > ? >Parentheses? 2. @ >1ultipl0?3 G >-i5ision?3 Q >1o ulo? .. N >Positi5e?3 >&egati5e?3 N ># ?3 >N Concatenate?3 >Subtract? %. B3 E3 M3 EB3 MB3 ME3 RB3 RE3 RM >Comparison operators? 5. &!T ). #&/. CET*EE&3 I&3 LIJE3 != (. B >#ssignment? 6or e$ample3 in the follo,ing 4uer03 #&- has prece ence o5er !=:

SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E custi B " #&- empi I&>"3 .3 5? != custi B (5 #&- empi I&>23 %3 )?<

The 4uer0 returns or ers that ,ere either place b0 customer " an han le b0 emplo0ees "3 .3 or 5 or place b0 customer (5 an han le b0 emplo0ees 23 %3 or ). Parentheses ha5e the highest prece ence3 so the0 gi5e 0ou full control. 6or the sa+e of other people ,ho nee to re5ie, or maintain 0our co e an for rea abilit0 purposes3 it;s a goo practice to use parentheses e5en ,hen not re4uire 3 as ,ell as in entation. 6or e$ample3 the follo,ing 4uer0 is the logical e4ui5alent of the pre5ious 4uer03 onl0 its logic is much clearer: SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E >custi B " #&- empi I&>"3 .3 5?? != >custi B (5 #&- empi I&>23 %3 )??<

'sing parentheses to force prece ence ,ith logical operators is similar to using parentheses ,ith arithmetic operators. 6or e$ample3 ,ithout parentheses in the follo,ing e$pression multiplication prece es a ition: SELECT "7 N 2 @ .<

Therefore3 this e$pression returns "). 8ou can use parentheses to force the a ition to be calculate first: SELECT >"7 N 2? @ .<

This time the e$pression returns .).

C#SE E$pressions
# C#SE e$pression is a scalar e$pression that returns a 5alue base on con itional logic. &ote that C#SE is an e$pression an not a statement< that is3 it oesn;t let 0ou control flo, of acti5it0 or o something base on con itional logic. Instea 3 the 5alue it returns is base on con itional logic. Cecause C#SE is a scalar e$pression3 it is allo,e ,here5er scalar e$pressions are allo,e 3 such as the SELECT3 *AE=E3 A#DI&:3 an !=-E= C8 clauses< CAECJ constraints< an so on. The t,o forms of C#SE e$pression are simple an searche . The simple form allo,s 0ou to compare one 5alue3 or scalar e$pression3 ,ith a list of possible 5alues3 an return a 5alue bac+ for the first match. If no 5alue in the list is e4ual to the teste 5alue3 the C#SE e$pression returns the 5alue that appears in the ELSE clause >if one e$ists?. If a C#SE e$pression oesn;t ha5e an ELSE clause3 it efaults to ELSE &'LL. 6or e$ample3 the follo,ing 4uer0 against the Pro uction.Pro ucts table uses a C#SE e$pression in the SELECT clause to pro uce the escription of the categor0i column 5alue: SELECT pro ucti 3 pro uctname3 categor0i 3 C#SE categor0i *AE& " TAE& ;Ce5erages; *AE& 2 TAE& ;Con iments; *AE& . TAE& ;Confections; *AE& % TAE& ;-air0 Pro ucts; *AE& 5 TAE& ;:rainsGCereals; *AE& ) TAE& ;1eatGPoultr0; *AE& / TAE& ;Pro uce; *AE& ( TAE& ;Seafoo ; ELSE ;'n+no,n Categor0; E&- #S categor0name 6=!1 Pro uction.Pro ucts<

This 4uer0 pro uces the follo,ing output3 sho,n in abbre5iate form: pro ucti pro uctname categor0i categor0name

----------- ----------------------------- ---------------" Pro uct AA8-P " Ce5erages 2 Pro uct =ECTE " Ce5erages . Pro uct I1EAS 2 Con iments % Pro uct JSC=1 2 Con iments 5 Pro uct EPEI1 2 Con iments ) Pro uct D#IID 2 Con iments / Pro uct A1L&I / Pro uce ( Pro uct *DS6P 2 Con iments 2 Pro uct #!TC* ) 1eatGPoultr0 "7 Pro uct 8AK:E ( Seafoo ... >// ro,>s? affecte ?

The prece ing 4uer0 is a simple e$ample of using the C#SE e$pression. 'nless the set of categories is 5er0 small an static3 0our best esign choice is probabl0 to maintain the pro uct categories in a table3 an Foin that table ,ith the Pro ucts table ,hen 0ou nee to get the categor0 escriptions. In fact3 the TSQL6un amentals277( atabase has Fust such a Categories table. #gain emonstrating the simple form of the C#SE e$pression3 the follo,ing 4uer0 against the Sales.!r erDalues 5ie, pro uces three tiles base on 5al logical or er3 an translates the tile numbers to tile escriptions >Lo,3 1e ium3 an Aigh?: SELECT or eri 3 custi 3 5al3 C#SE &TILE>.? !DE=>!=-E= C8 5al? *AE& " TAE& ;Lo,; *AE& 2 TAE& ;1e ium; *AE& . TAE& ;Aigh; ELSE ;'n+no,n; E&- #S title esc 6=!1 Sales.!r erDalues !=-E= C8 5al<

This 4uer0 generates the follo,ing output: Co e Die,: Scroll G Sho, #ll or eri custi 5al

title esc

----------- ----------- ----------------"7/(2 "2 "2.57 Lo, "7(7/ 2/ "(.%7 Lo, "75() )) 2..(7 Lo, "7/)/ /) 2(.77 Lo, "7(2( 5% .7.77 Lo, ... "7).2 () 5(2.77 Lo, ""7%% 2" 52".)7 Lo, "75(% / 52../5 Lo, "7/7% )2 525.57 Lo, "7)5% 5 )7".(. Lo, "7(". )/ )72.%7 1e ium "7)5) .2 )7%.22 1e ium "7((( .7 )75.77 1e ium "7.77 %2 )7(.77 1e ium "7%2. %" )7(.%7 1e ium ... "7)%5 .% "5.5.77 1e ium "7))/ 27 "5.).(7 1e ium "7%)" %) "5.(./7 1e ium "7(/( ). "5.2.77 1e ium "755. (/ "5%)..7 1e ium "7.)2 2 "5%2.)7 Aigh "7257 .% "552.)7 Aigh "7/22 .2 "55..57 Aigh "7/22 /" "5/7.77 Aigh ""7"( %( "5/5.77 Aigh ... "7%"/ /. """((.%7 Aigh "7((2 )5 "".(7.77 Aigh ""7.7 /" "2)"5.75 Aigh "72(" .% "5("7.77 Aigh "7()5 ). ").(/.57 Aigh >(.7 ro,>s? affecte ?

The simple C#SE form has a single test 5alue3 or e$pression3 right after the C#SE +e0,or that is compare ,ith a list of possible 5alues in the *AE& clauses. The searche C#SE form is more

fle$ible because it allo,s 0ou to specif0 pre icates3 or logical e$pressions3 in the *AE& clauses rather than restricting 0ou to e4ualit0 comparisons. The searche C#SE e$pression returns the 5alue in the TAE& clause that is associate ,ith the first *AE& logical e$pression that e5aluates to T='E. If none of the *AE& e$pressions e5aluates to T='E3 the C#SE e$pression returns the 5alue that appears in the ELSE clause >or &'LL if an ELSE clause is not specifie ?. 6or e$ample3 the follo,ing 4uer0 pro uces a 5alue categor0 escription base on ,hether the 5alue is less than "3777.773 bet,een "3777.77 an .3777.773 or greater than .3777.77: SELECT or eri 3 custi 3 5al3 C#SE *AE& 5al M "777.77 TAE& ;Less then "777; *AE& 5al CET*EE& "777.77 #&- .777.77 TAE& ;Cet,een "777 an .777; *AE& 5al E .777.77 TAE& ;1ore than .777; ELSE ;'n+no,n; E&- #S 5aluecategor0 6=!1 Sales.!r erDalues<

This 4uer0 generates the follo,ing output: or eri custi 5al 5aluecategor0 ----------- ----------- ----------------------------"72%( (5 %%7.77 Less then "777 "72%2 /2 "()..%7 Cet,een "777 an "7257 .% "552.)7 Cet,een "777 an "725" (% )5%.7) Less then "777 "7252 /) .52/.27 1ore than .777 "725. .% "%%%.(7 Cet,een "777 an "725% "% 55).)2 Less then "777 "7255 )( 2%27.57 Cet,een "777 an "725) (( 5"/.(7 Less then "777 "725/ .5 """2.27 Cet,een "777 an ... >(.7 ro,>s? affecte ?

.777 .777

.777 .777 .777

8ou can see that e5er0 simple C#SE e$pression can be con5erte to the searche C#SE form3 but not necessaril0 the other ,a0 aroun . So far I;5e Fust use a fe, e$amples to familiariOe 0ou ,ith the C#SE e$pression. E5en though it might not be apparent at this point from these e$amples3 the C#SE e$pression is an e$tremel0 po,erful an useful language element.

&'LLs
#s e$plaine in Chapter "3 9Cac+groun to T-SQL Quer0ing an Programming39 SQL supports the &'LL mar+ to represent missing 5alues3 an uses three-5alue logic3 meaning that pre icates can e5aluate to T='E3 6#LSE3 or '&J&!*&. T-SQL follo,s the stan ar in this respect. Treatment of &'LLs an '&J&!*& in SQL can be 5er0 confusing because intuiti5el0 people are more accustome to thin+ing in terms of t,o-5alue logic >T='E3 6#LSE?. To a to the confusion3 ifferent language elements in SQL treat &'LLs an '&J&!*& ifferentl0. Let;s start ,ith three-5alue pre icate logic. # logical e$pression in5ol5ing onl0 e$isting or present3 5alues e5aluates to either T='E or 6#LSE3 but ,hen the logical e$pression in5ol5es a missing 5alue3 it e5aluates to '&J&!*&. 6or e$ample3 consi er the pre icate salar0 E 7. *hen salar0 is e4ual to "7773 the e$pression e5aluates to T='E. *hen salar0 is e4ual to "7773 the e$pression e5aluates to 6#LSE. *hen salar0 is &'LL3 the e$pression e5aluates to '&J&!*&. SQL treats T='E an 6#LSE in an intuiti5e an probabl0 e$pecte manner. 6or e$ample3 if the pre icate salar0 E 7 appears in a 4uer0 filter >the *AE=E an A#DI&: clauses?3 ro,s or groups for ,hich the e$pression e5aluates to T='E are returne 3 ,hile those for ,hich the e$pression e5aluates to 6#LSE are filtere out. Similarl03 if the pre icate salar0 E 7 appears in a CAECJ constraint in a table3 I&SE=T or 'P-#TE statements for ,hich the e$pression e5aluates to T='E are accepte 3 ,hile those for ,hich the e$pression e5aluates to 6#LSE are reFecte . SQL has ifferent treatments for '&J&!*& in ifferent language elements >an for some people3 not necessaril0 the e$pecte treatments?. The correct efinition of the treatment SQL has for 4uer0 filters is 9accept T='E39 meaning that both 6#LSE an

'&J&!*& are filtere out. Con5ersel03 the efinition of the treatment SQL has for CAECJ constraints is 9reFect 6#LSE39 meaning that both T='E an '&J&!*& are accepte . If SQL use t,o-5alue pre icate logic3 there ,oul n;t be a ifference bet,een the efinitions 9accept T='E9 an 9reFect 6#LSE.9 Cut ,ith three5alue pre icate logic3 9accept T='E9 reFects '&J&!*& >accepts T='E3 hence reFects both 6#LSE an '&J&!*&? ,hile 9reFect 6#LSE9 accepts it >reFects 6#LSE3 hence accepts both T='E an '&J&!*&?. 'sing the pre icate salar0 E 7 from the pre5ious e$ample3 a &'LL salar0 ,oul cause the e$pression to e5aluate to '&J&!*&. If this pre icate appears in a 4uer0;s *AE=E clause3 a ro, ,ith a &'LL salar0 ,oul be filtere out. If this pre icate appears in a CAECJ constraint in a table3 a ro, ,ith a &'LL salar0 ,oul be accepte . !ne of the tric+0 aspects of '&J&!*& is that ,hen 0ou negate it3 0ou still get '&J&!*&. 6or e$ample3 gi5en the pre icate &!T >salar0 E 7?3 ,hen salar0 is &'LL3 salar0 E 7 e5aluates to '&J&!*&3 an &!T '&J&!*& remains '&J&!*&. *hat some people fin surprising is that an e$pression comparing t,o &'LLs >&'LL B &'LL? e5aluates to '&J&!*&. The reasoning for this is that a &'LL represents a missing or un+no,n 5alue3 an 0ou can;t reall0 tell ,hether one un+no,n 5alue is e4ual to another. Therefore3 SQL pro5i es 0ou ,ith the pre icates IS &'LL an IS &!T &'LL3 ,hich 0ou shoul use instea of B &'LL an ME &'LL. To ma+e things a bit more tangible3 I;ll emonstrate the aforementione aspects of the three-5alue pre icate logic. The Sales.Customers table has three attributes calle countr03 region3 an cit03 ,here the customer;s location information is store . #ll locations ha5e e$isting countries an cities. Some ha5e e$isting regions >such as countr0: 'S#3 region: *#3 cit0: Seattle?3 0et for some the region element is missing or inapplicable >such as countr0: 'J3 region: &'LL3 cit0: Lon on?. Consi er the follo,ing 4uer0 that attempts to return all customers ,here the region is e4ual to *#: SELECT custi 3 countr03 region3 cit0 6=!1 Sales.Customers *AE=E region B &;*#;<

This 4uer0 generates the follo,ing output:

custi countr0 region cit0 ----------- ----------------------------- --------------%. 'S# *# *alla *alla (2 'S# *# Jir+lan (2 'S# *# Seattle

!ut of the 2" ro,s in the Customers table3 the 4uer0 returns the three ro,s ,here the region attribute is e4ual to *#. The 4uer0 neither returns ro,s ,here the 5alue in the region attribute is present an ifferent than *# >pre icate e5aluates to 6#LSE? nor those ,here the region attribute is &'LL >pre icate e5aluates to '&J&!*&?. The follo,ing 4uer0 attempts to return all customers ,here the region is ifferent than *#: SELECT custi 3 countr03 region3 cit0 6=!1 Sales.Customers *AE=E region ME &;*#;<

This 4uer0 generates the follo,ing output: Co e Die,: Scroll G Sho, #ll custi countr0 region cit0 ----------- ----------------------------- --------------"7 Cana a CC Tsa,assen "5 CraOil SP Sao Paulo 2" CraOil SP Sao Paulo ." CraOil SP Campinas .2 'S# != Eugene .. DeneOuela -6 Caracas .% CraOil =S =io e Saneiro .5 DeneOuela Tchira San Cristbal .) 'S# != Elgin ./ Irelan Co. Cor+ Cor+ .( 'J Isle of *ight Co,es %2 Cana a CC Dancou5er %5 'S# C# San 6rancisco %) DeneOuela Lara Car4uisimeto %/ DeneOuela &ue5a Esparta I. e 1argarita

%( 5" 55 )" )2 )5 )/ /" /5 // /( (" ((

'S# Cana a 'S# CraOil CraOil 'S# CraOil 'S# 'S# 'S# 'S# CraOil CraOil

!= Qubec #J =S SP &1 =S I*8 != 1T SP SP

Portlan 1ontral #nchorage =io e Saneiro Sao Paulo #lbu4uer4ue =io e Saneiro Coise Lan er Portlan Cutte Sao Paulo =esen e

>2( ro,>s? affecte ?

If 0ou e$pecte to get (( ro,s bac+ >2" ro,s in the table minus . returne b0 the pre5ious 4uer0?3 0ou might fin the fact that this 4uer0 returne onl0 2( ro,s surprising. Cut remember3 a 4uer0 filter 9accepts T='E39 meaning that it reFects both ro,s for ,hich the logical e$pression e5aluates to 6#LSE an those for ,hich it e5aluates to '&J&!*&. So this 4uer0 returne ro,s in ,hich a 5alue ,as present in the region attribute an that 5alue ,as ifferent than *#. It returne neither ro,s ,here the region attribute ,as e4ual to *# nor ro,s ,here region ,as &'LL. 8ou ,ill get the e$act same output if 0ou use the pre icate &!T >region B &;*#;? because in the ro,s ,here region is &'LL an the e$pression region B &;*#; e5aluates to '&J&!*&3 &!T >region B &;*#;? e5aluates to '&J&!*& also. If 0ou ,ant all ro,s ,here region is &'LL3 o not use the pre icate region B &'LL3 because the e$pression e5aluates to '&J&!*& in all ro,sboth those ,here the 5alue is present an those ,here the 5alue is missing >is &'LL?. The follo,ing 4uer0 returns an empt0 set: SELECT custi 3 countr03 region3 cit0 6=!1 Sales.Customers *AE=E region B &'LL< custi countr0 region cit0

----------- ----------------------------- -------------->7 ro,>s? affecte ?

Instea 3 0ou shoul

use the IS &'LL pre icate:

SELECT custi 3 countr03 region3 cit0 6=!1 Sales.Customers *AE=E region IS &'LL<

This 4uer0 generates the follo,ing output3 sho,n in abbre5iate form: custi countr0 region cit0 ----------- ----------------------------- --------------" :erman0 &'LL Cerlin 2 1e$ico &'LL 1$ico -.6. . 1e$ico &'LL 1$ico -.6. % 'J &'LL Lon on 5 S,e en &'LL Lule ) :erman0 &'LL 1annheim / 6rance &'LL Strasbourg ( Spain &'LL 1a ri 2 6rance &'LL 1arseille "" 'J &'LL Lon on ... >)7 ro,>s? affecte ?

If 0ou ,ant to return all ro,s ,here the region attribute is not *#3 inclu ing those in ,hich the 5alue is present an ifferent than *# along ,ith those in ,hich the 5alue is missing3 0ou nee to inclu e an e$plicit test for &'LLs3 li+e so: SELECT custi 3 countr03 region3 cit0 6=!1 Sales.Customers *AE=E region ME &;*#; != region IS &'LL<

This 4uer0 generates the follo,ing output3 sho,n in abbre5iate form: custi countr0 region cit0 ----------- ----------------------------- --------------" :erman0 &'LL Cerlin 2 1e$ico &'LL 1$ico -.6. . 1e$ico &'LL 1$ico -.6. % 'J &'LL Lon on 5 S,e en &'LL Lule ) :erman0 &'LL 1annheim / 6rance &'LL Strasbourg ( Spain &'LL 1a ri 2 6rance &'LL 1arseille "7 Cana a CC Tsa,assen ... >(( ro,>s? affecte ?

SQL also treats &'LLs inconsistentl0 in ifferent language elements for comparison an sorting purposes. Some elements treat t,o &'LLs as e4ual to each other an others as ifferent. 6or e$ample3 for grouping an sorting purposes3 t,o &'LLs are consi ere e4ual. That is3 the :=!'P C8 clause arranges all &'LLs in one group Fust li+e present 5alues3 an the !=-E= C8 clause sorts all &'LLs together. #&SI SQL lea5es it to the pro uct implementation as to ,hether &'LLs sorts before present 5alues or after. T-SQL sorts &'LLs before present 5alues. #s mentione earlier3 4uer0 filters 9accept T='E.9 #n e$pression comparing t,o &'LLs 0iel s '&J&!*&< therefore3 such a ro, is filtere out. #&SI SQL has t,o +in s of '&IQ'E constraint: one that treats &'LLs as e4ual >allo,ing onl0 one &'LL? an one that treats &'LLs as ifferent >allo,ing multiple &'LLs?. T-SQL implemente onl0 the former. Jeeping in min the inconsistent treatment SQL has for '&J&!*& an &'LLs an the potential for logical errors3 0ou shoul e$plicitl0 thin+ of three-5alue logic in e5er0 4uer0 that 0ou ,rite. If the

efault treatment is not the one 0ou esire3 0ou ha5e to inter5ene e$plicitl0< other,ise3 Fust ensure that the efault beha5ior is in fact the one 0ou are after.

#ll-#t-!nce !perations
SQL supports a concept calle all-at-once operations3 ,hich means that all e$pressions that appear in the same logical 4uer0 processing phase are e5aluate as if at the same point in time. This concept e$plains ,h03 for e$ample3 0ou cannot refer to column aliases assigne in the SELECT clause ,ithin the same SELECT clause3 e5en if it seems intuiti5el0 that 0ou shoul be able to. Consi er the follo,ing 4uer0: SELECT or eri 3 8E#=>or er ate? #S or er0ear3 or er0ear N " #S ne$t0ear 6=!1 Sales.!r ers<

The reference to the column alias or er0ear is in5ali in the thir e$pression in the SELECT list3 e5en though the referencing e$pression appears 9after9 the one ,here the alias is assigne . The reason is that logicall0 there is no or er of e5aluation of the e$pressions in the SELECT listit;s a set of e$pressions. #t the logical le5el all e$pressions in the SELECT list are e5aluate at the same point in time. Therefore this 4uer0 generates the follo,ing error: 1sg 27/3 Le5el ")3 State "3 Line % In5ali column name ;or er0ear;.

Aere;s another e$ample of the rele5ance of all-at-once operations: Suppose 0ou ha a table calle T" ,ith t,o integer columns calle col" an col23 an 0ou ,ante to return all ro,s ,here col2Gcol" is greater than 2. Cecause there ma0 be ro,s in the table ,here col" is e4ual to 73 0ou nee to ensure that the i5ision oesn;t ta+e place in those casesother,ise3 the 4uer0 fails because of a i5i e-b0-Oero error. So if 0ou ,rite a 4uer0 using the follo,ing format:

SELECT col"3 col2 6=!1 bo.T" *AE=E col" ME 7 #&- col2Gcol" E 2<

8ou assume that SQL Ser5er e5aluates the e$pressions from left to right3 an that if the e$pression col" ME 7 e5aluates to 6#LSE3 SQL Ser5er ,ill short-circuit< that is3 it oesn;t bother to e5aluate the e$pression "7Gcol" E 2 because at this point it is +no,n that the ,hole e$pression is 6#LSE. So 0ou might thin+ that this 4uer0 ne5er pro uces a i5i e-b0-Oero error. SQL Ser5er oes support short circuits3 but because of the allat-once operations concept in #&SI SQL3 SQL Ser5er is free to process the e$pressions in the *AE=E clause in an0 or er that it li+es. SQL Ser5er usuall0 ma+es ecisions li+e this base on cost estimations3 meaning that t0picall0 the e$pression that is cheaper to e5aluate is e5aluate first. 8ou can see that if SQL Ser5er eci es to process the e$pression "7Gcol" E 2 first3 this 4uer0 might fail because of a i5i e-b0-Oero error. 8ou ha5e se5eral ,a0s to tr0 an a5oi a failure here. 6or e$ample3 the or er in ,hich the *AE& clauses of a C#SE e$pression are e5aluate is guarantee . So 0ou coul re5ise the 4uer0 as follo,s: SELECT col"3 col2 6=!1 bo.T" *AE=E C#SE *AE& col" B 7 TAE& ;no; or ;0es; if ro, shoul *AE& col2Gcol" E 2 TAE& ;0es; ELSE ;no; E&- B ;0es;<

be returne

In ro,s ,here col" is e4ual to Oero3 the first *AE& clause e5aluates to T='E an the C#SE e$pression returns the string ;no; >replace ,ith ;0es; if 0ou ,ant to return the ro, ,hen col" is e4ual to Oero?. !nl0 if the first C#SE e$pression oes not e5aluate to T='Emeaning that col" is not 7 oes the secon *AE& clause chec+ ,hether the e$pression "7Gcol" E 2 e5aluates to T='E. If it oes3 the C#SE e$pression returns the string ;0es.; In all other cases3 the C#SE e$pression returns the string ;no.; The pre icate

in the *AE=E clause returns T='E onl0 ,hen the result of the C#SE e$pression is e4ual to the string ;0es.; This means that there ,ill ne5er be an attempt here to i5i e b0 Oero. This ,or+aroun turne out to be 4uite con5olute 3 an in this particular case ,e can use a simpler mathematical ,or+aroun that a5oi s i5ision altogether: SELECT col"3 col2 6=!1 bo.T" *AE=E col" ME 7 an

col2 E 2@col"<

I inclu e this e$ample to e$plain the uni4ue an important all-atonce operations concept3 an the fact that SQL Ser5er guarantees the processing or er of the *AE& clauses in a C#SE e$pression.

*or+ing ,ith Character -ata


In this section3 I co5er 4uer0 manipulation of character ata3 inclu ing ata t0pes3 collation3 operators an functions3 an pattern matching. -ata T0pes SQL Ser5er supports t,o +in s of character ata t0pesregular an 'nico e. =egular ata t0pes inclu e CA#= an D#=CA#=3 an 'nico e ata t0pes inclu e &CA#= an &D#=CA#=. The ifference is that regular characters use one b0te of storage for each character3 ,hile 'nico e characters re4uire t,o b0tes per character. *ith one b0te of storage per character3 a choice of a regular character t0pe for a column restricts 0ou to onl0 one language in a ition to English because onl0 25) >2U(? ifferent characters can be represente b0 a single b0te. The language support for the column is etermine b0 the column;s effecti5e collation3 ,hich I;ll escribe shortl0. *ith 'nico e ata t0pes3 )535.) >2U")? istinct characters can be represente because t,o b0tes of storage are use for each character. #ll languages can be represente in the same 'nico e table3 so ,hen using a 'nico e ata t0pe for a column3 0ou can mi$ multiple languages rather than being restricte to onl0 one in a ition to English. The t,o +in s of character ata t0pes also iffer in the ,a0 literals are e$presse . *hen e$pressing a regular character literal3

0ou simpl0 use single 4uotes: ;This is a regular character string literal;. *hen e$pressing a 'nico e character literal3 0ou nee to specif0 the character & >for &ational? as a prefi$: &;This is a 'nico e character string literal;. #n0 ata t0pe ,ithout the D#= element >CA#=3 &CA#=? in its name is fi$e length3 ,hich means that SQL Ser5er preser5es space in the ro, base on the column;s efine siOe an not on the actual number of characters in the character string. 6or e$ample3 efining a column as CA#=>25? means that SQL Ser5er preser5es space for 25 characters in the ro, regar less of the length of the store character string. Cecause no e$pansion of the ro, is re4uire ,hen the strings are e$pan e 3 fi$e -length ata t0pes are more suite for ,rite-focuse s0stems. Cut because storage consumption is not optimal3 0ou pa0 more ,hen rea ing ata. # ata t0pe ,ith the D#= element >D#=CA#=3 &D#=CA#=? in its name is 5ariable length3 ,hich means that SQL Ser5er uses as much storage space in the ro, as re4uire to store the characters that appear in the character string3 plus t,o e$tra b0tes for offset ata. 6or e$ample3 efining a column as D#=CA#=>25? means that the ma$imum number of characters supporte ,ill be 253 but in practice3 the actual number of characters in the string etermines storage. Cecause storage consumption is re uce ,hen compare to that of fi$e -length t0pes3 rea operations are faster. Ao,e5er3 up ates might result in ro, e$pansion3 ,hich ma0 result in ata mo5ement outsi e the current page. Therefore3 up ates of ata ha5ing 5ariable-length ata t0pes are less efficient than up ates of ata ha5ing fi$e -length ata t0pes. 8ou can also efine the 5ariable-length ata t0pes ,ith the 1#K specifier instea of a ma$imum number of characters. *hen the column is efine ,ith the 1#K specifier3 a 5alue ,ith a siOe up to a certain threshol >(3777 b0tes b0 efault? is store inline in the ro,. # 5alue ,ith a siOe abo5e the threshol is store e$ternal to the ro, as a large obFect >L!C?. Later in this chapter3 in the section 9Quer0ing 1eta ata39 I ,ill e$plain ho, 0ou can obtain meta ata information about obFects in the atabase3 inclu ing the ata t0pes of columns. Collation

Collation is a propert0 of character ata that encapsulates se5eral aspects3 inclu ing language support >rele5ant to regular t0pes because 'nico e supports all languages?3 sort or er3 case sensiti5it03 accent sensiti5it03 an more. To get the set of supporte collations an their escriptions3 0ou can 4uer0 the table function fnLhelpcollations as follo,s: SELECT name3 escription 6=!1 s0s.fnLhelpcollations>?<

6or e$ample3 the collation Latin"L:eneralLCIL#S means that:


Latin"L:eneral The supporte language is English. -ictionar0 sorting Sorting an comparison of character ata is base on ictionar0 or er >;#; an ;a; M ;C; an ;b;?. 8ou etermine that it is ictionar0 or er because that;s the efault ,hen no other or ering is efine e$plicitl0. 1ore specificall03 the element CI& oesn;t e$plicitl0 appear in the collation name. If the element CI& appeare 3 it ,oul mean that sorting an comparison of character ata ,as base on the binar0 representation of characters >;#; M ;C; M ;a; M ;b;?.

CI The ata is case insensiti5e >;a; B ;#;?. #S The ata is accent sensiti5e >;; ME ;;?.

Collation can be efine at four ifferent le5els: instance3 atabase3 column3 an e$pression. The lo,est le5el is the effecti5e one. The collation of the instance is chosen as part of the setup program. It etermines the collations of all s0stem atabases3 an use as the efault for user atabases. *hen 0ou create a user atabase3 0ou can specif0 a collation for the atabase using the C!LL#TE clause. If 0ou on;t3 the instance;s collation is assume b0 efault. The atabase collation etermines the collation of meta ata of obFects in the atabase3 an is use as the efault for user table columns. It is important to emphasiOe that the atabase collation etermines the collation of meta ata3 inclu ing obFect an column names. 6or e$ample3 if the atabase collation is case insensiti5e3

is

0ou can;t create t,o tables calle T" an t" ,ithin the same schema3 but if the atabase collation is case sensiti5e 0ou can. 8ou can e$plicitl0 specif0 a collation for a column as part of its efinition using the C!LL#TE clause. If 0ou on;t3 the atabase collation is assume b0 efault. 8ou can con5ert the collation of an e$pression using the C!LL#TE clause. 6or e$ample3 in a case-insensiti5e en5ironment the follo,ing 4uer0 uses a case-insensiti5e comparison: SELECT empi 3 firstname3 lastname 6=!1 A=.Emplo0ees *AE=E lastname B &; a5is;<

The follo,ing 4uer0 returns the ro, for Sara -a5is e5en though the casing oesn;t match because the effecti5e casing is insensiti5e: empi firstname lastname ----------- ----------------------------" Sara -a5is

If 0ou ,ant to ma+e the filter case sensiti5e e5en though the column;s collation is case insensiti5e3 0ou can con5ert the collation of the e$pression li+e so: SELECT empi 3 firstname3 lastname 6=!1 A=.Emplo0ees *AE=E lastname C!LL#TE Latin"L:eneralLCSL#S B &; a5is;<

This time the 4uer0 returns an empt0 set because no match is foun ,hen using a case-sensiti5e comparison.

Quote

I entifiers

In stan ar SQL3 single 4uotes are use to elimit literal character strings >for e$ample3 ;literal;? an ouble 4uotes are use to elimit irregular i entifiers li+e table or column

names that inclu e a space or start ,ith a igit >for e$ample3 9Irregular I entifier9?. In SQL Ser5er3 there;s a setting calle Q'!TE-LI-E&TI6IE= that controls the meaning of ouble 4uotes. This setting can be applie either at the atabase le5el using the #LTE= -#T#C#SE comman or at the session le5el using the SET comman . *hen the setting is turne on3 the beha5ior is accor ing to stan ar SQL3 meaning that ouble 4uotes are use to elimit i entifiers. *hen the setting is turne off3 the beha5ior is nonstan ar 3 an ouble 4uotes are use to elimit literal character strings. It is strongl0 recommen e to follo, best practices an stic+ to stan ar beha5ior >setting is on?. 1ost atabase interfaces inclu ing !LE-C an !-CC turn this setting on b0 efault. Tip #s an alternati5e to using ouble 4uotes to elimit i entifiers3 SQL Ser5er also supports s4uare brac+ets >for e$ample3 HIrregular I entifierI?. =egar ing single 4uotes that are use to elimit literal character strings3 if 0ou ,ant to incorporate a single 4uote character as part of the string3 0ou nee to specif0 t,o single 4uotes. 6or e$ample3 to e$press the literal abc; e3 specif0 ;abc; ; e;.

!perators an

6unctions functions that operate

This section co5ers string concatenation an on character strings.


String Concatenation >Plus Sign HNI !perator?

T-SQL pro5i es the plus sign >N? operator to concatenate strings. 6or e$ample3 the follo,ing 4uer0 against the Emplo0ees table pro uces the fullname result column b0 concatenating firstname3 a space3 an lastname:

SELECT empi 3 firstname N &; ; N lastname #S fullname 6=!1 A=.Emplo0ees<

This 4uer0 pro uces the follo,ing output: empi fullname ----------------------------------------" Sara -a5is 2 -on 6un+ . Su 0 Le, % 8ael Pele 5 S5en Cuc+ ) Paul Suurs / =ussell Jing ( 1aria Cameron 2 To0a -olgop0ato5a

#&SI SQL ictates that a concatenation ,ith a &'LL shoul 0iel a &'LL. This is the efault beha5ior of SQL Ser5er. 6or e$ample3 consi er the 4uer0 against the Customers table sho,n in Listing 2/:
Listing 2-/. Quer0 -emonstrating String Concatenation

SELECT custi 3 countr03 region3 cit03 countr0 N &;3; N region N &;3; N cit0 #S location 6=!1 Sales.Customers<

Some of the ro,s in the Customers table ha5e a &'LL in the region column. 6or those3 SQL Ser5er returns b0 efault a &'LL in the location result column: Co e Die,: Scroll G Sho, #ll custi countr0 region cit0 location ----------- --------------- -------------------- ------------------" :erman0 &'LL Cerlin &'LL 2 1e$ico &'LL 1$ico -.6. &'LL

. 1e$ico % 'J 5 S,e en ) :erman0 / 6rance ( Spain 2 6rance "7 Cana a Cana a3CC3Tsa,assen "" 'J "2 #rgentina ". 1e$ico "% S,itOerlan "5 CraOil Paulo ") 'J "/ :erman0 "( 6rance "2 'J 27 #ustria ... >2" ro,>s? affecte ?

&'LL 1$ico -.6. &'LL Lon on &'LL Lule &'LL 1annheim &'LL Strasbourg &'LL 1a ri &'LL 1arseille CC Tsa,assen &'LL Lon on &'LL Cuenos #ires &'LL 1$ico -.6. &'LL Cern SP Sao Paulo &'LL Lon on &'LL #achen &'LL &antes &'LL Lon on &'LL :raO

&'LL &'LL &'LL &'LL &'LL &'LL &'LL

&'LL &'LL &'LL &'LL CraOil3SP3Sao &'LL &'LL &'LL &'LL &'LL

8ou can change the ,a0 SQL Ser5er treats concatenation b0 setting a session option calle C!&C#TL&'LLL8IEL-SL&'LL to !66. SQL Ser5er treats a &'LL set to !66 as an empt0 string for concatenation purposes. To emonstrate this beha5ior3 run the follo,ing co e to set the option to !663 an then rerun the 4uer0 in Listing 2-/: SET C!&C#TL&'LLL8IEL-SL&'LL !66<

The 4uer0 no, treats &'LLs as empt0 strings for concatenation purposes3 an 0ou get the follo,ing output3 sho,n here in abbre5iate form: Co e Die,: Scroll G Sho, #ll custi countr0 region cit0

location

----------- --------------- -------------------- ------------------" :erman0 &'LL Cerlin :erman033Cerlin 2 1e$ico &'LL 1$ico -.6. 1e$ico331$ico -.6. . 1e$ico &'LL 1$ico -.6. 1e$ico331$ico -.6. % 'J &'LL Lon on 'J33Lon on 5 S,e en &'LL Lule S,e en33Lule ) :erman0 &'LL 1annheim :erman0331annheim / 6rance &'LL Strasbourg 6rance33Strasbourg ( Spain &'LL 1a ri Spain331a ri 2 6rance &'LL 1arseille 6rance331arseille "7 Cana a CC Tsa,assen Cana a3CC3Tsa,assen "" 'J &'LL Lon on 'J33Lon on "2 #rgentina &'LL Cuenos #ires #rgentina33Cuenos #ires ". 1e$ico &'LL 1$ico -.6. 1e$ico331$ico -.6. "% S,itOerlan &'LL Cern S,itOerlan 33Cern "5 CraOil SP Sao Paulo CraOil3SP3Sao Paulo ") 'J &'LL Lon on 'J33Lon on "/ :erman0 &'LL #achen :erman033#achen "( 6rance &'LL &antes 6rance33&antes "2 'J &'LL Lon on 'J33Lon on 27 #ustria &'LL :raO #ustria33:raO ... >2" ro,>s? affecte ?

It is strongl0 recommen e that 0ou a5oi changing the stan ar beha5ior< most programmers e$pect the co e to beha5e in a stan ar manner. If 0ou ,ant to treat a &'LL as an empt0 string3 0ou can o so programmaticall0. Cut before I emonstrate ho,3

first ma+e sure 0ou set the C!&C#TL&'LLL8IEL-SL&'LL option bac+ to !& in 0our session: SET C!&C#TL&'LLL8IEL-SL&'LL !&<

To treat a &'LL as an empt0 stringor more accuratel03 to substitute a &'LL ,ith an empt0 string0ou can use the C!#LESCE function. This function accepts a list of input 5alues an returns the first that is not &'LL. Aere;s ho, 0ou can re5ise the 4uer0 from Listing 2-/ to substitute &'LLs ,ith empt0 strings programmaticall0: SELECT custi 3 countr03 region3 cit03 countr0 N &;3; N C!#LESCE>region3 &;;? N &;3; N cit0 #S location 6=!1 Sales.Customers<

T-SQL pro5i es a set of functions that manipulate character strings3 inclu ing S'CST=I&:3 LE6T3 =I:AT3 LE&3 CA#=I&-EK3 P#TI&-EK3 =EPL#CE3 =EPLIC#TE3 ST'663 'PPE=3 L!*E=3 =T=I13 LT=I13 an others. In the follo,ing sections3 I;ll escribe the commonl0 use ones.
The S'CST=I&: 6unction

The S'CST=I&: function e$tracts a substring from a string.


S0nta$

S'CST=I&:> string3 start3 length ? The function operates on the input string3 an e$tracts a substring starting at position start3 length characters long. 6or e$ample3 the follo,ing co e returns the output ;abc;: SELECT S'CST=I&:>;abc e;3 "3 .?<

If the 5alue of the thir argument e$cee s the en of the input string3 the function returns e5er0thing until the en ,ithout raising an error. This can be con5enient ,hen 0ou ,ant to return e5er0thing from a certain point until the en of the string 0ou can

simpl0 specif0 a 5er0 large 5alue or a 5alue representing the full length of the input string.
The LE6T an =I:AT 6unctions

The LE6T an =I:AT functions are abbre5iations of the S'CST=I&: function3 returning a re4ueste number of characters from the left or right of the input string.
S0nta$

LE6T> string3 n ?3 =I:AT> string3 n ? The first argument3 string3 is the string the function operates on. The secon argument3 n3 is the number of characters to e$tract from the left or right of the string. 6or e$ample3 the follo,ing co e returns the output ;c e;: SELECT =I:AT>;abc e;3 .?<

The LE& an

-#T#LE&:TA 6unctions

The LE& function returns the number of characters in the input string.
S0nta$

LE&> string ?< &ote that this function returns the number of characters in the input string an not necessaril0 the number of b0tes. *ith regular characters3 both numbers are the same because each character re4uires one b0te of storage. *ith 'nico e characters each character re4uires t,o b0tes of storage< therefore3 the number of characters is half the number of b0tes. To get the number of b0tes3 use the -#T#LE&:TA function instea of LE&. 6or e$ample3 the follo,ing co e returns 5: SELECT LE&>&;abc e;?<

The follo,ing co e returns "7:

SELECT -#T#LE&:TA>&;abc e;?<

#nother ifference bet,een LE& an -#T#LE&:TA is that the former e$clu es trailing blan+s ,hile the latter oesn;t.
The CA#=I&-EK 6unction

The CA#=I&-EK function returns the position of the first occurrence of a substring ,ithin a string.
S0nta$

CA#=I&-EK> substring3 string H3 startLposI ? The function returns the position of the first argument3 substring3 ,ithin the secon argument3 string. 8ou can optionall0 specif0 a thir argument3 startLpos3 to tell the function the position from ,hich to start loo+ing. If 0ou on;t specif0 the thir argument3 the function starts loo+ing from the first character. If the substring is not foun 3 the function returns 7. 6or e$ample3 the follo,ing co e returns the first position of a space in ;ItOi+ Cen-:an3; an returns the output ): SELECT CA#=I&-EK>; ;3;ItOi+ Cen-:an;?<

The P#TI&-EK 6unction

The P#TI&-EK function returns the position of the first occurrence of a pattern ,ithin a string.
S0nta$

P#TI&-EK> pattern3 string ? The argument pattern uses similar patterns to those use b0 the LIJE pre icate in T-SQL. I;ll e$plain patterns an the LIJE pre icate shortl03 in the section 9The LIJE Pre icate.9 E5en though I ha5en;t e$plaine 0et ho, patterns are e$presse in T-SQL3 the follo,ing e$ample sho,s ho, to fin the position of the first occurrence of a igit ,ithin a string: SELECT P#TI&-EK>;QH7-2IQ;3 ;abc "2.efgh;?<

This co e returns the output 5.


The =EPL#CE 6unction

The =EPL#CE function replaces all occurrences of a substring ,ith another.


S0nta$

=EPL#CE> string3 substring"3 substring2 ? The function replaces all occurrences of substring" in string ,ith substring2. 6or e$ample3 the follo,ing co e substitutes all occurrences of a ash in the input string ,ith colons: SELECT =EPL#CE>;"-a 2-b;3 ;-;3 ;:;?<

This co e returns the output: ;":a 2:b;. 8ou can use the =EPL#CE function to count the number of occurrences of a character ,ithin a string. To achie5e this 0ou replace all occurrences of the character ,ith an empt0 string >Oero characters?3 an calculate the original length of the string minus the ne, length. 6or e$ample3 the follo,ing 4uer0 returns3 for each emplo0ee3 the number of times the character ;e; appears in the lastname attribute: SELECT empi 3 lastname3 LE&>lastname? - LE&>=EPL#CE>lastname3 ;e;3 ;;?? #S numoccur 6=!1 A=.Emplo0ees<

This 4uer0 generates the follo,ing output: empi lastname numoccur ----------- -----------------------------5 Cuc+ 7 ( Cameron " " -a5is 7 2 -olgop0ato5a 7 2 6un+ 7

/ . % )

Jing Le, Pele Suurs

7 " 2 7

The =EPLIC#TE 6unction

The =EPLIC#TE function replicates a string a re4ueste times.


S0nta$

number of

=EPLIC#TE> string3 n ? 6or e$ample3 the follo,ing co e replicates the string ;abc; three times returning the string ;abcabcabc;: SELECT =EPLIC#TE>;abc;3 .?<

The ne$t e$ample emonstrates using the =EPLIC#TE function3 along ,ith the =I:AT function an string concatenation. The follo,ing 4uer0 against the Pro uction.Suppliers table generates a "7- igit string representation of the integer supplier I- ,ith lea ing Oeros: Co e Die,: Scroll G Sho, #ll SELECT supplieri 3 =I:AT>=EPLIC#TE>;7;3 2? N C#ST>supplieri "7? #S strsupplieri 6=!1 Pro uction.Suppliers<

#S D#=CA#=>"7??3

The e$pression pro ucing the result column strsupplieri replicates the character ;7; nine times >pro ucing the string ;777777777;? an concatenates the string representation of the supplier I- to form the result. The string representation of the integer supplier I- is pro uce b0 the C#ST function3 ,hich is use to con5ert the ata t0pe of the input 5alue. 6inall03 the e$pression e$tracts the "7 rightmost characters of the result string3 returning the "7- igit

string representation of the supplier I- ,ith lea ing Oeros. Aere;s the output of this 4uer03 sho,n in abbre5iate form: supplieri strsupplieri ----------- ------------22 7777777722 2( 777777772( % 777777777% 2" 777777772" 2 7777777772 22 7777777722 "% 77777777"% "" 77777777"" 25 7777777725 / 777777777/ ... >22 ro,>s? affecte ?

The ST'66 6unction

The ST'66 function allo,s 0ou to remo5e a substring from a string an insert a ne, substring instea .
S0nta$

ST'66> string3 pos3

eleteLlength3 insertstring ?

The function operates on the input parameter string. It eletes as man0 characters as the number specifie in the eleteLlength parameter starting at the character position specifie in the pos input parameter. The function inserts the string specifie in the insertstring parameter in position pos. 6or e$ample3 the follo,ing co e operates on the string ;$0O;3 remo5es one character from the secon character3 an inserts the substring ;abc; instea : SELECT ST'66>;$0O;3 23 "3 ;abc;?<

The output of this co e is ;$abcO;.


The 'PPE= an L!*E= 6unctions

The 'PPE= an L!*E= functions return the input string ,ith all uppercase or lo,ercase characters.
S0nta$

'PPE=> string ?3 L!*E=> string ? 6or e$ample3 the follo,ing co e returns ;ITTIJ CE&-:#&;: SELECT 'PPE=>;ItOi+ Cen-:an;?<

The follo,ing co e returns ;itOi+ ben-gan;: SELECT L!*E=>;ItOi+ Cen-:an;?<

The =T=I1 an

LT=I1 6unctions

The =T=I1 an LT=I1 functions return the input string ,ith lea ing or trailing spaces remo5e .
S0nta$

=T=I1> string ?3 LT=I1> string ? If 0ou ,ant to remo5e both lea ing an trailing spaces3 use the result of one function as the input to the other. 6or e$ample3 the follo,ing co e remo5es both lea ing an trailing spaces from the input string returning ;abc;: SELECT =T=I1>LT=I1>; abc ;??<

The LIJE Pre icate T-SQL pro5i es a pre icate calle LIJE that allo,s 0ou to chec+ ,hether a character string matches a specifie pattern. Similar patterns are use b0 the P#TI&-EK function escribe earlier. The follo,ing section escribes the ,il car s supporte in the patterns an emonstrates their use.
The Q >Percent? *il car

The percent sign represents a string of an0 siOe3 inclu ing an empt0 string. 6or e$ample3 the follo,ing 4uer0 returns emplo0ees ,here the last name starts ,ith ;-;: SELECT empi 3 lastname 6=!1 A=.Emplo0ees *AE=E lastname LIJE &;-Q;<

This 4uer0 returns the follo,ing output: empi lastname ----------- -------------------" -a5is 2 -olgop0ato5a

The L >'n erscore? *il car

#n un erscore represents a single character. 6or e$ample3 the follo,ing 4uer0 returns emplo0ees ,here the secon character in the last name is ;e;: SELECT empi 3 lastname 6=!1 A=.Emplo0ees *AE=E lastname LIJE &;LeQ;<

This 4uer0 returns the follo,ing output: empi lastname ----------- -------------------. Le, % Pele

The HMList of CharactersEI *il car

S4uare brac+ets ,ith a list of characters >such as ;H#CCI;? represent a single character that must be one of the characters specifie in the list. 6or e$ample3 the follo,ing 4uer0 returns emplo0ees ,here the first character in the last name is ;#;3 ;C; or ;C;:

SELECT empi 3 lastname 6=!1 A=.Emplo0ees *AE=E lastname LIJE &;H#CCIQ;<

This 4uer0 returns the follo,ing output: empi lastname ----------- -------------------5 Cuc+ ( Cameron

The HMCharacterE-MCharacterEI *il car

S4uare brac+ets ,ith a character range >such as ;H#-EI;? represent a single character that must be ,ithin the specifie range. 6or e$ample3 the follo,ing 4uer0 returns emplo0ees ,here the first character in the last name is ;#; through ;E;: SELECT empi 3 lastname 6=!1 A=.Emplo0ees *AE=E lastname LIJE &;H#-EIQ;<

This 4uer0 returns the follo,ing output: empi lastname ----------- -------------------5 Cuc+ ( Cameron " -a5is 2 -olgop0ato5a

The HUMCharacter List or =angeEI *il car

S4uare brac+ets ,ith a caret sign >U? follo,e b0 a character list or range >such as ;HU#-EI;? represent a single character not in the specifie character list or range. 6or e$ample3 the follo,ing 4uer0 returns emplo0ees ,here the first character in the last name is not # through E:

SELECT empi 3 lastname 6=!1 A=.Emplo0ees *AE=E lastname LIJE &;HU#-EIQ;<

This 4uer0 returns the follo,ing output: empi lastname ----------- -------------------2 6un+ / Jing . Le, % Pele ) Suurs

The ESC#PE Character

If 0ou ,ant to loo+ for a character that is also use as a ,il car 3 >;Q;3 ;L;3 ;H;3 ;I;3 for e$ample? 0ou can use an escape character. Specif0 a character that 0ou +no, for sure oesn;t appear in the ata as the escape character in front of the character 0ou are loo+ing for3 an specif0 the +e0,or ESC#PE follo,e b0 the escape character right after the pattern. 6or e$ample3 to chec+ ,hether a column calle col" contains an un erscore3 use col" LIJE ;QRLQ; ESC#PE ;R;. 6or ,il car s ;Q;3 ;L;3 an ;H; 0ou can use s4uare brac+ets instea of an escape character. Instea of col" LIJE ;QRLQ; ESC#PE ;R; 0ou can use col" LIJE ;QHLIQ;.

*or+ing ,ith -ate an

Time -ata

*or+ing ,ith ate an time ata in SQL Ser5er is not tri5ial. 8ou ,ill face se5eral challenges in this area3 such as e$pressing literals in a language-neutral manner3 ,or+ing separatel0 ,ith ate an time3 an so on. In this section3 I first intro uce the ate an time ata t0pes supporte b0 SQL Ser5er3 then I e$plain the recommen e ,a0 to ,or+ ,ith those t0pes3 an finall0 I co5er ate- an time-relate functions.

-ate an

Time -ata T0pes

Prior to SQL Ser5er 277(3 SQL Ser5er supporte t,o temporal ata t0pes calle -#TETI1E an S1#LL-#TETI1E. Coth t0pes inclu e ate an time components that are inseparable. The t,o ata t0pes iffer in their storage re4uirements3 their supporte ate range3 an their accurac0. SQL Ser5er 277( intro uces separate -#TE an TI1E ata t0pes: -#TETI1E23 ,hich has a bigger ate range an better accurac0 than -#TETI1E3 an -#TETI1E!66SET3 ,hich also has a time Oone component. Table 2" lists etails about ate an time ata t0pes3 inclu ing storage re4uirements3 supporte ate range3 accurac03 an recommen e entr0 format.
Table 2-". -ate an Time -ata T0pes

-ata T0pe

Storag -ate e =ange >b0tes ? ( Sanuar0 "3 "/5. through -ecember ."3 2222 Sanuar0 "3 "277 through Sune )3 27/2 Sanuar0 "3 777" through -ecember ."3 2222

#ccurac0

=ecommen e Entr0 6ormat an E$ample ;888811-hh:mm:ss.nnn; ;277272"2 "2:.7:"5."2.;

-#TETI1E

. "G. millisecon s

S1#LL-#TET % I1E

" minute

;888811-- hh:mm;

;277272"2 "2:.7; " a0 ;8888-11---;

-#TE

TI1E

. to 5

"77 ;hh:mm:ss.nnnnnnn; nanosecon s ;"2:.7:"5."2.%5)/; Sanuar0 "3 777" through "77 ;8888-11--nanosecon s hh:mm:ss.nnnnnnn;

-#TETI1E2

) to (

Table 2-". -ate an

Time -ata T0pes

-ata T0pe

Storag -ate e =ange >b0tes ? -ecember ."3 2222

#ccurac0

=ecommen e Entr0 6ormat an E$ample

;2772-72-"2 "2:.7:"5."2.%5)/; "77 ;8888-11--nanosecon s hh:mm:ss.nnnnnnn HNV-I hh:mm; ;2772-72-"2 "2:.7:"5."2.%5)/ N72:77;

-#TETI1E!6 6SET

( to "7

Sanuar0 "3 777" through -ecember ."3 2222

The storage re4uirements for the last three ata t0pes in Table 2" >TI1E3 -#TETI1E23 an -#TETI1E!66SET? epen on the accurac0 0ou choose. 8ou specif0 the accurac0 as an integer in the range 7 to / representing the fractional secon precision. 6or e$ample3 TI1E>7? means 7 fractional secon precision in other ,or s3 one-secon accurac0. TI1E>.? means one-millisecon accurac03 an TI1E>/? means "77-nanosecon accurac0. If 0ou on;t specif0 a fractional secon precision3 SQL Ser5er assumes / b0 efault ,ith all three aforementione t0pes. Literals *hen 0ou nee to specif0 a literal >constant? of a ate an time ata t0pe3 0ou shoul consi er se5eral things. 6irst3 though it might soun a bit strange3 SQL Ser5er oesn;t pro5i e the means to e$press a ate an time literal< instea 3 it allo,s 0ou to specif0 a literal of a ifferent t0pe that can be con5erte e$plicitl0 or implicitl0to a ate an time ata t0pe. It is a best practice to use character strings to e$press ate an time 5alues3 as sho,n in the follo,ing e$ample: SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or er ate B ;277/72"2;<

SQL Ser5er recogniOes the literal ;277/72"2; as a character string literal an not as a ate an time literal3 but because the e$pression in5ol5es operan s of t,o ifferent t0pes3 one operan nee s to be con5erte to the other;s t0pe. *hen an e$pression in5ol5es t,o operan s of ifferent t0pes3 one of the operan ,ill nee to be implicitl0 con5erte to the other;s t0pe. &ormall03 implicit con5ersion bet,een t0pes is base on ,hat;s calle atat0pe prece ence. SQL Ser5er efines prece ence among atat0pes3 an ,ill usuall0 implicitl0 co5ert the operan that has lo,er atat0pe prece ence to the one that has higher prece ence. In our e$ample the character string literal is con5erte to the column;s ata t0pe >-#TETI1E? because character strings are consi ere lo,er in terms of ata t0pe prece ence ,ith respect to ate an time ata t0pes. Implicit con5ersion rules are not al,a0s that simple3 an in fact there are ifferent rules applie in cases of filters an in other e$pressions3 but for the purposes of our iscussion ,e;ll +eep things simple. 6or the complete list of ata t0pe prece ence please see 9-ata T0pe Prece ence9 in SQL Ser5er Coo+s !nline. The point I;m tr0ing to ma+e is that in the prece ing e$ample3 implicit con5ersion ta+es place behin the scenes. This 4uer0 is logicall0 e4ui5alent to the follo,ing one3 ,hich con5erts the character string to a -#TETI1E ata t0pe e$plicitl0: SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or er ate B C#ST>;277/72"2; #S -#TETI1E?<

It is important to note that some character string formats of ate an time literals are language- epen ent3 meaning that ,hen 0ou con5ert them to a ate an time ata t0pe3 SQL Ser5er ma0 interpret the 5alue ifferentl0 base on the language setting in effect in the session. Each login efine b0 the -C# has a efault language associate ,ith it3 an unless change e$plicitl03 that language becomes the effecti5e language in the session. 8ou can o5er,rite the efault language in 0our session b0 using the SET L#&:'#:E comman 3 but this is generall0 not recommen e because some aspects of the co e might rel0 on the user;s efault language. The effecti5e language in the session sets se5eral language-relate settings behin the scenes3 among them one calle -#TE6!=1#T that etermines ho, SQL Ser5er interprets literals 0ou enter ,hen

con5erte from a character string t0pe to a ate an time t0pe. The -#TE6!=1#T setting is e$presse as a combination of the characters 3 m3 an 0. 6or e$ample3 the usLenglish language setting sets the -#TE6!=1#T to m 03 ,hile the Critish language setting sets the -#TE6!=1#T to m0. 8ou can o5er,rite the -#TE6!=1#T setting in 0our session b0 using the SET -#TE6!=1#T comman 3 but as mentione earlier3 changing language-relate settings is generall0 not recommen e . Consi er3 for e$ample3 the literal ;72G"2G277/;. SQL Ser5er can interpret the ate as either 6ebruar0 "23 277/ or -ecember 23 277/ ,hen 0ou con5ert this literal to one of the follo,ing t0pes: -#TETI1E3 -#TE3 -#TETI1E23 or -#TETI1E!66SET. The effecti5e L#&:'#:EG -#TE6!=1#T setting is the etermining factor. To emonstrate ifferent interpretations of the same character string literal3 run the follo,ing co e: SET L#&:'#:E Critish< SELECT C#ST>;72G"2G277/; #S -#TETI1E?< SET L#&:'#:E usLenglish< SELECT C#ST>;72G"2G277/; #S -#TETI1E?<

&otice in the output that the literal ,as interprete the t,o ifferent language en5ironments: Change language setting to Critish.

ifferentl0 in

----------------------277/-"2-72 77:77:77.777 Change language setting to usLenglish.

----------------------277/-72-"2 77:77:77.777

&ote that the L#&:'#:EG-#TE6!=1#T setting onl0 affects the ,a0 the 5alues 0ou enter are interprete < these settings ha5e no impact on the format use in the output for presentation purposes3 ,hich is etermine b0 the atabase interface use b0 the client tool >such as !LE-C? an not b0 the L#&:'#:EG-#TE6!=1#T

setting. 6or e$ample3 !LE-C an !-CC present -#TETI1E 5alues in the format ;8888-11--- hh:mm:ss.nnn;. Cecause the co e 0ou ,rite might en up being use b0 international users ,ith ifferent language setting for their logins3 un erstan ing that some formats of literals are language- epen ent is crucial. It is strongl0 recommen e that 0ou phrase 0our literals in a language-neutral manner. Language-neutral formats are al,a0s interprete b0 SQL Ser5er the same ,a03 an are not affecte b0 language-relate settings. Table 2-2 pro5i es literal formats that are consi ere neutral for each of the ate an time t0pes.
Table 2-2. -ate an Time -ata T0pe 6ormats

-ata T0pe -#TETI1E

Language-&eutral 6ormats ;888811-- hh:mm:ss.nnn; ;8888-11--Thh:mm:ss.nnn; ;888811--;

E$amples ;277272"2 "2:.7:"5."2.; ;2772-72"2T"2:.7:"5."2.; ;277272"2; ;277272"2 "2:.7; ;2772-72-"2T"2:.7; ;277272"2; ;277272"2; ;2772-72-"2; ;277272"2 "2:.7:"5."2.%5)/; ;2772-72-"2 "2:.7:"5."2.%5)/; ;2772-72"2T"2:.7:"5."2.%5)/; ;277272"2; ;2772-72-"2;

S1#LL-#TE ;888811-- hh:mm; TI1E ;8888-11---Thh:mm; ;888811--; -#TE ;888811--; ;8888-11---; -#TETI1E2 ;888811-hh:mm:ss.nnnnnnn; ;8888-11--hh:mm:ss.nnnnnnn; ;8888-11--Thh:mm:ss.nnnnnnn; ;888811--; ;8888-11---;

Table 2-2. -ate an

Time -ata T0pe 6ormats

-ata T0pe -#TETI1E! 66SET

Language-&eutral 6ormats ;888811-hh:mm:ss.nnnnnnn HNV-Ihh:mm; ;8888-11--hh:mm:ss.nnnnnnn HNV-Ihh:mm; ;888811--; ;8888-11---;

E$amples ;277272"2 "2:.7:"5."2.%5)/ N72:77; ;2772-72-"2 "2:.7:"5."2.%5)/ N72:77; ;277272"2; ;2772-72-"2;

TI1E

;hh:mm:ss.nnnnnnn;

;"2:.7:"5."2.%5)/;

&ote a couple of things about Table 2-2. *ith all t0pes that inclu e both ate an time components3 if 0ou on;t specif0 a time part in 0our literal3 SQL Ser5er assumes mi night. If 0ou on;t specif0 a time Oone3 SQL Ser5er assumes 77:77. It is also important to note that the formats ;8888-11---; an ;8888-11--- hh:mm...; are language- epen ent ,hen con5erte to -#TETI1E or S1#LL-#TETI1E3 an language-neutral ,hen con5erte to -#TE3 -#TETI1E2 an -#TETI1E!66SET. 6or e$ample3 notice in the follo,ing co e that the language setting has no impact on ho, a literal e$presse ,ith the format ;888811--; is interprete ,hen con5erte to -#TETI1E: SET L#&:'#:E Critish< SELECT C#ST>;277/72"2; #S -#TETI1E?< SET L#&:'#:E usLenglish< SELECT C#ST>;277/72"2; #S -#TETI1E?<

The output sho,s that the literal ,as interprete 6ebruar0 "23 277/: Change language setting to Critish.

in both cases as

----------------------277/-72-"2 77:77:77.777 Change language setting to usLenglish.

----------------------277/-72-"2 77:77:77.777

I probabl0 can;t emphasiOe enough that using language-neutral formats li+e ;888811--; is a best practice since such formats are interprete the same ,a0 regar less of the L#&:'#:EG-#TE6!=1#T settings. If 0ou insist on using a language- epen ent format to e$press literals3 0ou can use the C!&DE=T function to e$plicitl0 con5ert the character string literal to the esire ata t0pe3 an in the thir argument specif0 a number representing the st0le 0ou use . SQL Ser5er Coo+s !nline has a table ,ith all st0le numbers an the formats the0 represent un er the section 9The C#ST an C!&DE=T 6unctions.9 6or e$ample3 if 0ou ,ant to specif0 the literal ;72G"2G277/; ,ith the format mmG G00003 use st0le number "7"3 as sho,n here: SELECT C!&DE=T>-#TETI1E3 ;72G"2G277/;3 "7"?<

The literal is interprete as 6ebruar0 "23 277/ regar less of the language setting that is in effect. If 0ou ,ant to use the format GmmG00003 use st0le number "7.:

SELECT C!&DE=T>-#TETI1E3 ;72G"2G277/;3 "7.?<

This time the literal is interprete *or+ing ,ith -ate an

as -ecember 23 277/.

Time Separatel0

SQL Ser5er 277( intro uce separate -#TE an TI1E ata t0pes3 but in pre5ious 5ersions there is no separation bet,een the t,o components. If 0ou ,ant to ,or+ onl0 ,ith ates or onl0 ,ith times in 5ersions of SQL Ser5er prior to SQL Ser5er 277(3 0ou can use one of the ata t0pes -#TETI1E or S1#LL-#TETI1E that contain

both components. 8ou can also use t0pes li+e integers or character strings ,here 0ou implement the ate an time logic3 but I ,on;t iscuss this option here. If 0ou ,ant to use the -#TETI1E or S1#LL-#TETI1E t0pes3 ,hen 0ou ,ant to ,or+ onl0 ,ith ates 0ou store the ate ,ith a 5alue of mi night >all Oeros in the time parts?. *hen 0ou ,ant to ,or+ onl0 ,ith times3 0ou store the time ,ith the base ate Sanuar0 "3 "277. 6or e$ample3 the or er ate column in the Sales.!r ers table is of a -#TETI1E ata t0pe3 but because onl0 the ate component is actuall0 rele5ant3 all 5alues ,ere store at mi night. *hen 0ou nee to filter onl0 or ers from a certain ate3 0ou on;t ha5e to use a range filter. Instea 3 0ou can use the e4ualit0 operator li+e so: SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or er ate B ;277/72"2;<

*hen the character string literal gets con5erte to -#TETI1E3 SQL Ser5er assumes mi night as the time component if time is not specifie . Cecause all 5alues in the or er ate column ,ere store ,ith mi night in the time component3 0ou get all or ers place on the re4ueste ate. If the time component is store use a range filter li+e so: ,ith non-mi night 5alues3 0ou can

SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or er ate EB ;277/72"2; #&- or er ate M ;277/72".;<

If 0ou ,ant to ,or+ onl0 ,ith times in 5ersions prior to SQL Ser5er 277(3 0ou can store all 5alues using the base ate Sanuar0 "3 "277. *hen SQL Ser5er con5erts a character string literal that contains onl0 a time component to -#TETI1E or S1#LL-#TETI1E3 SQL Ser5er assumes 0ou mean the base ate. 6or e$ample3 run the follo,ing co e: SELECT C#ST>;"2:.7:"5."2.; #S -#TETI1E?<

8ou get the follo,ing output: ----------------------"277-7"-7" "2:.7:"5."2.

Suppose 0ou ha a table ,ith a column calle tm of a -#TETI1E ata t0pe an 0ou store all 5alues using the base ate. To return all ro,s ,here the time 5alue is "2:.7:"5."2.3 0ou use the filter *AE=E tm B ;"2:.7:"5."2.;. Cecause 0ou i not specif0 a ate component3 SQL Ser5er assumes 0ou mean the base ate ,hen it implicitl0 con5erts the character string to a -#TETI1E ata t0pe. If 0ou ,ant to ,or+ onl0 ,ith ates or onl0 ,ith times3 but the input 5alues 0ou get inclu e both ate an time components3 0ou nee to appl0 some manipulation on the input 5alues to 9Oero9 the irrele5ant part. That is3 set the time component to mi night if 0ou ,ant to ,or+ onl0 ,ith ates3 an set the ate component to the base ate if 0ou ,ant to ,or+ onl0 ,ith times. I;ll e$plain ho, 0ou can achie5e this shortl03 in the section 9-ate an Time 6unctions.9 6iltering -ate =anges *hen 0ou nee to filter a range of ates3 such as a ,hole 0ear or a ,hole month3 it seems natural to use functions such as 8E#= an 1!&TA. 6or e$ample3 the follo,ing 4uer0 returns all or ers place in the 0ear 277/: SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E 8E#=>or er ate? B 277/<

Ao,e5er3 0ou shoul be a,are that in most cases3 ,hen 0ou appl0 manipulation on the filtere column 0ou cannot use an in e$ in an efficient manner. This is probabl0 har to un erstan ,ithout some bac+groun about in e$es an performance3 ,hich are outsi e the scope of this boo+3 but for no,3 Fust +eep this general point in min : To ha5e the potential to use an in e$ efficientl03 0ou nee to re5ise the pre icate so that there is no manipulation on the filtere column3 li+e so: SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers

*AE=E or er ate EB ;277/7"7"; #&- or er ate M ;277(7"7";<

Similarl03 instea of using functions to filter or ers place particular month3 li+e so:

on a

SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E 8E#=>or er ate? B 277/ #&- 1!&TA>or er ate? B 2<

use a range filter3 li+e so: SELECT or eri 3 custi 3 empi 3 or er ate 6=!1 Sales.!r ers *AE=E or er ate EB ;277/727"; #&- or er ate M ;277/7.7";<

-ate an

Time 6unctions

In this section3 I escribe functions that operate on ate an time ata t0pes3 inclu ing :ET-#TE3 C'==E&TLTI1EST#1P3 :ET'TC-#TE3 S8S-#TETI1E3 S8S'TC-#TETI1E3 S8S-#TETI1E!66SET3 C#ST3 C!&DE=T3 S*ITCA!66SET3 T!-#TETI1E!66SET3 -#TE#--3 -#TE-I663 -#TEP#=T3 8E#=3 1!&TA3 -#83 an -#TE&#1E. &ote that the functions S8S-#TETI1E3 S8S'TC-#TETI1E3 S8S-#TETI1E!66SET3 S*ITCA!66SET3 an T!-#TETI1E!66SET are ne, in SQL Ser5er 277(3 ,hile the others ,ere a5ailable in pre5ious 5ersions as ,ell. The functions a5ailable prior to SQL Ser5er 277( ,ere enhance to support the ne, ate an time ata t0pes an the ne, ate an time parts.
Current -ate an Time

The follo,ing parameterless functions return the current ate an time 5alues in the s0stem ,here the SQL Ser5er instance resi es: :ET-#TE3 C'==E&TLTI1EST#1P3 :ET'TC-#TE3 S8S-#TETI1E3 S8S'TC-#TETI1E3 an S8S-#TETI1E!66SET. Table 2-. pro5i es the escription of these functions.

Table 2-.. 6unctions =eturning Current -ate an

Time

6unction

=eturn T0pe

-escription

&e, in SQL Ser5er 277(P &o &o &o 8es 8es 8es

:ET-#TE C'==E&TLTI1E ST#1P :ET'TC-#TE S8S-#TETI1E S8S'TC-#TETI 1E S8S-#TETI1E! 66SET

-#TETI1E -#TETI1E -#TETI1E -#TETI1E2 -#TETI1E2 -#TETI1E!6 6SET

Current time

ate an

Same as :ET-#TE but #&SI Current ate an time in 'TC Current time ate an

Current ate an time in 'TC Current ate time inclu ing time Oone

&ote that 0ou nee to specif0 empt0 parentheses ,ith all functions that shoul be specifie ,ithout parentheses3 e$cept the #&SI function C'==E&TLTI1EST#1P. #lso3 because C'==E&TLTI1EST#1P an :ET-#TE return the same thing but onl0 the former is stan ar 3 it is recommen e that 0ou use the former. This is a practice that I tr0 to follo, in general ,hen I ha5e se5eral options that o the same thing ,ith no functional or performance ifference3 an one is stan ar ,hile others aren;t3 m0 preference is to use the stan ar option. The follo,ing co e functions: emonstrates using the current ate an time

SELECT :ET-#TE>? #S H:ET-#TEI3 C'==E&TLTI1EST#1P #S HC'==E&TLTI1EST#1PI3 :ET'TC-#TE>? #S H:ET'TC-#TEI3 S8S-#TETI1E>? #S HS8S-#TETI1EI3 S8S'TC-#TETI1E>? #S HS8S'TC-#TETI1EI3 S8S-#TETI1E!66SET>? #S HS8S-#TETI1E!66SETI<

#s 0ou probabl0 notice 3 none of the ne, functions in SQL Ser5er 277( return onl0 the current s0stem ate or onl0 the current s0stem time. Ao,e5er3 0ou can get those easil0 b0 con5erting C'==E&TLTI1EST#1P or S8S-#TETI1E to -#TE or TI1E li+e so: SELECT C#ST>S8S-#TETI1E>? #S -#TE? #S HcurrentL ateI3 C#ST>S8S-#TETI1E>? #S TI1E? #S HcurrentLtimeI<

The C#ST an

C!&DE=T 6unctions

The C#ST an C!&DE=T functions are use t0pe of a 5alue.


S0nta$

to con5ert the

ata

C#ST> 5alue #S C!&DE=T >

atat0pe ?

atat0pe3 5alue H3 st0leLnumberI ?

Coth functions con5ert the input 5alue to the specifie atat0pe. In some cases3 C!&DE=T has a thir argument ,ith ,hich 0ou can specif0 the st0le of the con5ersion. 6or e$ample3 ,hen con5erting from a character string to one of the ate an time ata t0pes >or the other ,a0 aroun ?3 the st0le number in icates the format of the string. 6or e$ample3 st0le "7" in icates ;11G--G8888;3 ,hile st0le "7. in icates ;--G11G8888;. 8ou can fin the full list of st0le numbers an their meanings in SQL Ser5er Coo+s !nline un er 9C#ST an C!&DE=T.9 #s mentione earlier3 ,hen con5erting from a character string to one of the ate an time ata t0pes3 some of the string formats are language- epen ent. I recommen either using one of the language-neutral formats3 or using the C!&DE=T function an e$plicitl0 specif0ing the st0le number 0ou use . This ,a0 0our co e is interprete the same ,a0 regar less of the language of the login running it. &ote that C#ST is #&SI an C!&DE=T isn;t3 so unless 0ou nee to use the st0le number3 it is recommen e that 0ou use the C#ST function< this ,a0 0our co e is as stan ar as possible. 6ollo,ing are a fe, e$amples of using the C#ST an C!&DE=T functions ,ith ate an time ata t0pes. The follo,ing co e

con5erts the character string literal ;277272"2; to a -#TE t0pe: SELECT C#ST>;277272"2; #S -#TE?<

ata

The follo,ing co e con5erts the current s0stem ate an time 5alue to a -#TE ata t0pe3 practicall0 e$tracting onl0 the current s0stem ate: SELECT C#ST>S8S-#TETI1E>? #S -#TE?<

The follo,ing co e con5erts the current s0stem ate an time 5alue to a TI1E ata t0pe3 practicall0 e$tracting onl0 the current s0stem time: SELECT C#ST>S8S-#TETI1E>? #S TI1E?<

=emember that the -#TE an TI1E ata t0pes ,ere intro uce in SQL Ser5er 277(. #s suggeste earlier3 if 0ou ,ant to ,or+ onl0 ,ith ates or onl0 ,ith times in a 5ersion prior to SQL Ser5er 277(3 0ou can 9Oero9 the irrele5ant part in the -#TETI1E or S1#LL-#TETI1E 5alue. In other ,or s3 to ,or+ onl0 ,ith ates3 0ou set the time to mi night. To ,or+ onl0 ,ith time3 0ou set the ate to the base ate Sanuar0 "3 "277. I ,ill escribe techni4ues to Oero the irrele5ant part in a gi5en ate an time 5alue3 such as C'==E&TLTI1EST#1P. The follo,ing co e con5erts the current CA#=>(? using st0le ""2 >;888811--;?: ate an time 5alue to

SELECT C!&DE=T>CA#=>(?3 C'==E&TLTI1EST#1P3 ""2?<

6or e$ample3 if the current ate is 6ebruar0 "23 27723 this co e returns ;277272"2;. =emember that this st0le is language-neutral3 so ,hen the co e is con5erte bac+ to -#TETI1E3 0ou get the current ate at mi night: SELECT C#ST>C!&DE=T>CA#=>(?3 C'==E&TLTI1EST#1P3 ""2? #S -#TETI1E?<

Similarl03 to Oero the ate portion to the base ate3 0ou can first con5ert the current ate an time 5alue to CA#=>"2? using st0le ""% >;hh:mm:ss.nnn;?: SELECT C!&DE=T>CA#=>"2?3 C'==E&TLTI1EST#1P3 ""%?<

*hen the co e is con5erte bac+ to -#TETI1E3 0ou get the current time in the base ate: SELECT C#ST>C!&DE=T>CA#=>"2?3 C'==E&TLTI1EST#1P3 ""%? #S -#TETI1E?<

The S*ITCA!66SET 6unction

The S*ITCA!66SET function a Fusts an input -#TETI1E!66SET 5alue to a specifie time Oone.
S0nta$

S*ITCA!66SET>

atetimeoffsetL5alue3 timeLOone ?

6or e$ample3 the follo,ing co e a Fusts the current s0stem atetimeoffset 5alue to time Oone -75:77: SELECT S*ITCA!66SET>S8S-#TETI1E!66SET>?3 ;-75:77;?<

So if the current s0stem atetimeoffset 5alue is 6ebruar0 "23 2772 "7:77:77.7777777 -7(:773 this co e returns the 5alue: 6ebruar0 "23 2772 ".:77:77.7777777 -75:77. The follo,ing co e a Fusts the current 'TC: atetimeoffset 5alue to

SELECT S*ITCA!66SET>S8S-#TETI1E!66SET>?3 ;N77:77;?<

#ssuming the aforementione current atetimeoffset 5alue3 this co e returns the 5alue: 6ebruar0 "23 2772 "(:77:77.7777777 N77:77.
The T!-#TETI1E!66SET 6unction

The T!-#TETI1E!66SET function sets the time Oone offset of an input ate an time 5alue.
S0nta$

T!-#TETI1E!66SET>

ateLan LtimeL5alue3 timeLOone ?

This function is ifferent from S*ITCA!66SET in a couple of ,a0s. 6irst3 it;s not restricte to a atetimeoffset 5alue as input3 rather an0 ate an time ata t0pe. Secon 3 it oesn;t tr0 to a Fust the time base on the time Oone ifference bet,een the source 5alue an the specifie time Oone3 rather simpl0 returns the input ate an time 5alue ,ith the specifie time Oone as a atetimeoffset 5alue. 6or e$ample3 if the current s0stem atetimeoffset 5alue is 6ebruar0 "23 2772 "7:77:77.7777777 -7(:773 an 0ou run the follo,ing co e: SELECT T!-#TETI1E!66SET>S8S-#TETI1E!66SET>?3 ;-75:77;?<

8ou get bac+ the 5alue: 6ebruar0 "23 2772 "7:77:77.7777777 -75:77. =emember that the S*ITCA!66SET function returne 6ebruar0 "23 2772 ".:77:77.7777777 -75:77 because it a Fuste the time base on the time Oone ifferences bet,een the input >7(:77? an the specifie time Oone >-75:77?. #s I mentione 3 0ou can use the T!-#TETI1E!66SET function ,ith an0 ate an time ata t0pe as input. 6or e$ample3 the follo,ing co e ta+es the current s0stem ate an time 5alue an returns it as a atetimeoffset 5alue ,ith a time Oone -75:77: SELECT T!-#TETI1E!66SET>S8S-#TETI1E>?3 ;-75:77;?<

The -#TE#-- 6unction

The -#TE#-- function allo,s 0ou to a a specifie number of units of a specifie ate part to an input ate an time 5alue.
S0nta$

-#TE#--> part3 n3

tL5al ?

Dali 5alues for the part input inclu e 0ear3 4uarter3 month3 a0of0ear3 a03 ,ee+3 ,ee+ a03 hour3 minute3 secon 3 millisecon 3 microsecon 3 an nanosecon . The last t,o are ne, in SQL Ser5er 277(. 8ou can also specif0 the part in abbre5iate form3 such as 00 instea of 0ear. Please refer to SQL Ser5er Coo+s !nline for etails. The return t0pe for a ate an time input is the same t0pe as the input;s t0pe. If gi5en a string literal as input3 the output is -#TETI1E. 6or e$ample3 the follo,ing co e a s " 0ear to 6ebruar0 "23 2772:

SELECT -#TE#-->0ear3 "3 ;277272"2;?<

This co e returns the follo,ing output: ----------------------27"7-72-"2 77:77:77.777

The -#TE-I66 6unction

The -#TE-I66 function returns the ifference bet,een t,o an time 5alues in terms of a specifie ate part.
S0nta$

ate

-#TE-I66> part3

tL5al"3

tL5al2 ? ifference in terms of

6or e$ample3 the follo,ing co e returns the a0s bet,een t,o 5alues:

SELECT -#TE-I66> a03 ;277(72"2;3 ;277272"2;?<

This co e returns the output .)). =ea 0 for a bit more sophisticate use of the -#TE#-- an -#TE-I66 functionsP 8ou can use the follo,ing co e in 5ersions prior to SQL Ser5er 277( to set the time component of the current s0stem ate an time 5alue to mi night:

SELECT -#TE#--> a03 -#TE-I66> a03 ;277"7"7";3 C'==E&TLTI1EST#1P?3 ;277"7"7";?<

This is achie5e b0 first using the -#TE-I66 function to calculate the ifference in terms of ,hole a0s bet,een an anchor ate at mi night >;277"7"7"; in this case? an the current ate an time >call that ifference iff?. Then3 the -#TE#-- function is use to a iff a0s to the anchor. 8ou get the current s0stem ate at mi night. Interestingl03 if 0ou use this e$pression ,ith a month part instea of a03 an ma+e sure to use an anchor that is the first a0 of a month >as in our e$ample?3 0ou get the first a0 of the current month: SELECT -#TE#--> month3 -#TE-I66>month3 ;277"7"7";3 C'==E&TLTI1EST#1P?3 ;277"7"7";?<

Similarl03 b0 using a 0ear part an an anchor that is the first of a 0ear3 0ou get bac+ the first a0 of the current 0ear.

a0

If 0ou ,ant the last a0 of the month or 0ear3 simpl0 use an anchor that is the last a0 of a month or 0ear. 6or e$ample3 the follo,ing e$pression returns the last a0 of the current month: SELECT -#TE#--> month3 -#TE-I66>month3 ;"222"2.";3 C'==E&TLTI1EST#1P?3 ;"222"2.";?<

The -#TEP#=T 6unction

The -#TEP#=T function returns an integer representing a re4ueste part of a gi5en ate an time 5alue.
S0nta$

-#TEP#=T>

tL5al3 part ?

Dali 5alues for the part argument inclu e 0ear3 4uarter3 month3 a0of0ear3 a03 ,ee+3 ,ee+ a03 hour3 minute3 secon 3 millisecon 3 microsecon 3 nanosecon 3 TToffset3 an IS!L*EEJ. The last four parts are ne, in SQL Ser5er 277(. #s I mentione earlier3 0ou can use abbre5iations for the ate an time parts3 such as 00 instea of 0ear3 mm instea of month3 instea of a03 an so on. 6or e$ample3 the follo,ing co e returns the month part of the input 5alue: SELECT -#TEP#=T>month3 ;277272"2;?<

This co e returns the integer 2.


The 8E#=3 1!&TA an -#8 6unctions

The 8E#=3 1!&TA3 an -#8 functions are abbre5iations for the -#TEP#=T function returning the integer representation of the 0ear3 month3 an a0 parts of an input ate an time 5alue.
S0nta$

8E#=> 1!&TA> -#8>

tL5al ? tL5al ?

tL5al ? a03 month3 an 0ear

6or e$ample3 the follo,ing co e e$tracts the parts of an input 5alue: SELECT -#8>;277272"2;? #S the a03 1!&TA>;277272"2;? #S themonth3 8E#=>;277272"2;? #S the0ear<

This co e returns the follo,ing output: the a0 themonth the0ear ----------- ----------- ----------"2 2 2772

The -#TE&#1E 6unction

The -#TE&#1E function returns a character string representing the part of a gi5en ate an time 5alue.
S0nta$

-#TE&#1E>

tL5al3 part ?

This function is similar to -#TEP#=T3 an in fact has the same options for the part input. Ao,e5er3 ,hen rele5ant it returns the name of the re4ueste part rather than the number. 6or e$ample3 the follo,ing co e returns the month name of the gi5en input 5alue: SELECT -#TE&#1E>month3 ;277272"2;?<

=ecall that -#TEP#=T returne the integer 2 for this input. -#TE&#1E returns the name of the month3 ,hich is languageepen ent. If 0our session;s language is one of the English languages > usLenglish3 Critish3 an so on?3 0ou get bac+ the 5alue ;6ebruar0;. If 0our session;s language is Italian 0ou get bac+ the 5alue ;febbraio;. If a part is re4ueste that has no name3 but onl0 a numeric 5alue >such as 0ear?3 the -#TE&#1E function returns its numeric 5alue as a character string. 6or e$ample3 the follo,ing co e returns ;2772;: SELECT -#TE&#1E>0ear3 ;277272"2;?<

The IS-#TE 6unction

The IS-#TE function accepts a character string as input an returns " if it is con5ertible to a ate an time ata t0pe an it isn;t.

7 if

S0nta$

IS-#TE> string ? 6or e$ample3 the follo,ing co e returns ": SELECT IS-#TE>;277272"2;?<

#n

the follo,ing co e returns 7:

SELECT IS-#TE>;277272.7;?<

Quer0ing 1eta ata


SQL Ser5er pro5i es tools for getting information about meta ata of obFects3 such as information about tables in a atabase3 columns in a table3 an so on. Those tools inclu e catalog 5ie,s3 information schema 5ie,s3 s0stem store proce ures3 an functions. This area is ocumente ,ell in SQL Ser5er Coo+s !nline in the section 9Quer0ing the SQL Ser5er S0stem Catalog39 so I ,on;t co5er it in great etail here. I;ll Fust gi5e a couple of e$amples of each meta ata tool to gi5e 0ou a sense of ,hat;s a5ailable an get 0ou starte . Catalog Die,s Catalog 5ie,s pro5i e 5er0 etaile information about obFects in the atabase3 inclu ing information that is SQL Ser5erspecific. 6or e$ample3 if 0ou ,ant to list the tables in the atabase along ,ith their schema names3 0ou can 4uer0 the s0s.tables 5ie, as follo,s: 'SE TSQL6un amentals277(< SELECT SCAE1#L&#1E>schemaLi ? #S tableLschemaLname3 name #S tableLname 6=!1 s0s.tables<

The function SCAE1#L&#1E is use to con5ert the integer schema I- to its name. This 4uer0 returns the follo,ing output: tableLschemaLname tableLname ------------------ ------------A= Emplo0ees

Pro uction Pro uction Pro uction Sales Sales Sales Sales

Suppliers Categories Pro ucts Customers Shippers !r ers !r er-etails

To get information about columns in a table3 0ou can 4uer0 the s0s.columns table. 6or e$ample3 the follo,ing co e returns information about columns in the Sales.!r ers table inclu ing column names3 ata t0pes >s0stem t0pe I- translate to name using the T8PEL&#1E function?3 ma$imum length3 collation name3 an &'LLabilit0: SELECT name #S columnLname3 T8PEL&#1E>s0stemLt0peLi ? #S columnLt0pe3 ma$Llength3 collationLname3 isLnullable 6=!1 s0s.columns *AE=E obFectLi B !CSECTLI->&;Sales.!r ers;?<

This 4uer0 returns the follo,ing output: Co e Die,: Scroll G Sho, #ll columnLname columnLt0pe ma$Llength collationLname isLnullable --------------- ------------------------ ----------------------------------or eri int % &'LL 7 custi int % &'LL empi int % &'LL 7 or er ate atetime ( &'LL 7 re4uire ate atetime ( &'LL 7

shippe ate atetime " shipperi int freight mone0 7 shipname n5archar 7 shipa ress n5archar 7 shipcit0 n5archar 7 shipregion n5archar " shippostalco e n5archar " shipcountr0 n5archar 7

( % ( (7 "27 .7 .7 27 .7

&'LL &'LL &'LL Latin"L:eneralLCIL#I Latin"L:eneralLCIL#I Latin"L:eneralLCIL#I Latin"L:eneralLCIL#I Latin"L:eneralLCIL#I Latin"L:eneralLCIL#I 7

Information Schema Die,s Information schema 5ie,s are a set of 5ie,s that resi e in a schema calle I&6!=1#TI!&L SCAE1# an pro5i e meta ata information in a stan ar manner. That is3 the 5ie,s are efine in the #&SI SQL stan ar 3 so naturall0 the0 on;t co5er SQL Ser5er specific aspects. 6or e$ample3 the follo,ing 4uer0 against the I&6!=1#TI!&LSCAE1#.T#CLES 5ie, lists the user tables in the current atabase along ,ith their schema names: SELECT T#CLELSCAE1#3 T#CLEL&#1E 6=!1 I&6!=1#TI!&LSCAE1#.T#CLES *AE=E T#CLELT8PE B &;C#SE T#CLE;<

The follo,ing 4uer0 against the I&6!=1#TI!&LSCAE1#.C!L'1&S 5ie, pro5i es most of the a5ailable information about columns in the Sales.!r ers table: SELECT

C!L'1&L&#1E3 -#T#LT8PE3 CA#=#CTE=L1#KI1'1LLE&:TA3 C!LL#TI!&L&#1E3 ISL&'LL#CLE 6=!1 I&6!=1#TI!&LSCAE1#.C!L'1&S *AE=E T#CLELSCAE1# B &;Sales; #&- T#CLEL&#1E B &;!r ers;<

S0stem Store

Proce ures an

6unctions

S0stem store proce ures an functions internall0 4uer0 the s0stem catalog an gi5e 0ou bac+ more 9 igeste 9 meta ata information. #gain3 0ou can fin the full list of obFects an their etaile escriptions in SQL Ser5er Coo+s !nline3 but here are a fe, e$amples. The spLtables store proce ure returns a list of obFects >such as tables an 5ie,s? that can be 4uerie in the current atabase: EKEC s0s.spLtables<

&ote that the s0s schema ,as intro uce in SQL Ser5er 2775. In pre5ious 5ersions3 the s0stem store proce ures resi e in the bo schema. The spLhelp proce ure accepts an obFect name as input an returns multiple result sets ,ith general information about the obFect3 an also information about columns3 in e$es3 constraints3 an more. 6or e$ample3 the follo,ing co e returns etaile information about the !r ers table: EKEC s0s.spLhelp WobFname B &;Sales.!r ers;<

The spLcolumns proce ure returns information about columns in an obFect. 6or e$ample3 the follo,ing co e returns information about columns in the !r ers table: EKEC s0s.spLcolumns WtableLname B &;!r ers;3 WtableLo,ner B &;Sales;<

The spLhelpconstraint proce ure returns information about constraints in an obFect. 6or e$ample3 the follo,ing co e returns information about constraints in the !r ers table: EKEC s0s.spLhelpconstraint WobFname B &;Sales.!r ers;<

!ne set of functions returns information about properties of entities such as the SQL Ser5er instance3 atabase3 obFect3 column3 an so on. The SE=DE=P=!PE=T8 function returns the re4ueste propert0 of the current instance. 6or e$ample3 the follo,ing co e returns the pro uct le5el >such as =T13 SP"3 SP23 an so on? of the current instance: SELECT SE=DE=P=!PE=T8>;Pro uctLe5el;?<

The -#T#C#SEP=!PE=T8EK function returns the re4ueste propert0 of the gi5en atabase name. 6or e$ample3 the follo,ing co e returns the collation of the TSQL6un amentals277( atabase: SELECT -#T#C#SEP=!PE=T8EK>&;TSQL6un amentals277(;3 ;Collation;?

The !CSECTP=!PE=T8 function returns the re4ueste propert0 of the gi5en obFect name. 6or e$ample3 the output of the follo,ing co e in icates ,hether the !r ers table has a primar0 +e0: SELECT !CSECTP=!PE=T8>!CSECTLI->&;Sales.!r ers;?3 ;TableAasPrimar0Je0;?<

&otice the nesting of the function !CSECTLI- ,ithin !CSECTP=!PE=T8. The !CSECTP=!PE=T8 function e$pects an obFect I- an not a name3 so the !CSECTLI- function is use to return the I- of the !r ers table. The C!L'1&P=!PE=T8 function returns the re4ueste propert0 of a gi5en column. 6or e$ample3 the output of the follo,ing co e

in icates ,hether the shipcountr0 column in the !r ers table is &'LLable: SELECT C!L'1&P=!PE=T8>!CSECTLI->&;Sales.!r ers;?3 &;shipcountr0;3 ;#llo,s&ull;?<

Conclusion
This chapter intro uce 0ou to the SELECT statement3 logical 4uer0 processing3 an 5arious other aspects of single-table 4ueries. I co5ere 4uite a fe, subFects here3 inclu ing man0 ne, an uni4ue concepts. If 0ou;re ne, to T-SQL3 0ou might feel o5er,helme at this point. Cut remember3 this chapter intro uces some of the most important points about SQL that might be har to igest at the beginning. If some of the concepts ,eren;t completel0 clear3 0ou might ,ant to re5isit sections from this chapter later on3 after 0ou;5e ha a chance to sleep on it. 6or an opportunit0 to practice ,hat 0ou;5e learne an absorb the material better3 I recommen going o5er the chapter e$ercises.

E$ercises
This section contains e$ercises to practice the subFects iscusse in this chapter. Solutions to the e$ercises appear in the section that follo,s. This section occasionall0 pro5i es optional e$ercises that are more a 5ance . Those e$ercises are inten e for rea ers ,ho feel 5er0 comfortable ,ith the material an ,ant to challenge themsel5es ,ith more ifficult problems. The optional e$ercises for a 5ance rea ers are labele as such. 8ou can fin instructions for o,nloa ing an installing the TSQL6un amentals277( sample atabase in #ppen i$ #3 9:etting Starte .9 "=eturn or ers place in Sune 277/. atabase3

Tables in5ol5e : TSQL6un amentals277( Sales.!r ers table. -esire output >abbre5iate ?:

or eri or er ate custi empi ----------- --------------------------------- ----------"7555 277/-7)-72 77:77:77.777 /" ) "755) 277/-7)-7. 77:77:77.777 /. 2 "755/ 277/-7)-7. 77:77:77.777 %% 2 "755( 277/-7)-7% 77:77:77.777 % " "7552 277/-7)-75 77:77:77.777 / ) "75)7 277/-7)-7) 77:77:77.777 25 ( "75)" 277/-7)-7) 77:77:77.777 2% 2 "75)2 277/-7)-72 77:77:77.777 )) " "75). 277/-7)-"7 77:77:77.777 )/ 2 "75)% 277/-7)-"7 77:77:77.777 )5 % ... >.7 ro,>s? affecte ? 2 >!ptional3 =eturn or ers place on the last a0 of the month. # 5ance ? Tables in5ol5e : Sales.!r ers table. -esire output >abbre5iate ?:

or eri or er ate custi empi ----------- --------------------------------- ----------"72)2 277)-7/-." 77:77:77.777 (2 5 "7."/ 277)-72-.7 77:77:77.777 %( ) "7.%. 277)-"7-." 77:77:77.777 %% % "7.22 277)-"2-." 77:77:77.777 (. ( "7%.2 277/-7"-." 77:77:77.777 /5 . "7%)7 277/-72-2( 77:77:77.777 2% ( "7%)" 277/-72-2( 77:77:77.777 %) " "7%27 277/-7.-." 77:77:77.777 .5 / "7%2" 277/-7.-." 77:77:77.777 2( ( "7522 277/-7%-.7 77:77:77.777 %% % ... >2) ro,>s? affecte ? .=eturn emplo0ees ,ith last name containing the letter ;a; t,ice or more.

Tables in5ol5e : A=.Emplo0ees table. -esire output:

empi firstname lastname ----------- ----------------------------2 To0a -olgop0ato5a >" ro,>s? affecte ?

%=eturn or ers ,ith total 5alue >4uantit0 @ unitprice? greater than "737773 sorte b0 total 5alue. Tables in5ol5e : Sales.!r er-etails table. -esire output:

or eri total5alue ----------- --------------------"7()5 "/257.77 ""7.7 ").2".27 "72(" "5("7.77 "7./2 "22(".27 "7%2% ""%2..27 "7("/ ""%27./7 "7((2 "".(7.77 "7%"/ ""2(..27 "7(2/ "7(.5.2% "7.5. "7/%".)7 "75"5 "75((.57 "7%/2 "7%25.)7 "75%7 "7"2"./7 "7)2" "7")%.(7 >"% ro,>s? affecte ? 5=eturn the three ship countries ,ith the highest a5erage freight in 277/. Tables in5ol5e : Sales.!r ers table.

-esire

output:

shipcountr0 a5gfreight ----------------------------------#ustria "/(..)%2 S,itOerlan ""/."//5 S,e en "75.") >. ro,>s? affecte ? )Calculate ro, numbers for or ers base on or er ate or ering >using or er I- as tiebrea+er? for each customer separatel0. Tables in5ol5e : Sales.!r ers table. -esire output >abbre5iate ?:

custi or er ate or eri ro,num ----------- --------------------------------- -------------------" 277/-7(-25 77:77:77.777 "7)%. " " 277/-"7-7. 77:77:77.777 "7)22 2 " 277/-"7-". 77:77:77.777 "7/72 . " 277(-7"-"5 77:77:77.777 "7(.5 % " 277(-7.-") 77:77:77.777 "7252 5 " 277(-7%-72 77:77:77.777 ""7"" ) 2 277)-72-"( 77:77:77.777 "7.7( " 2 277/-7(-7( 77:77:77.777 "7)25 2 2 277/-""-2( 77:77:77.777 "7/52 . 2 277(-7.-7% 77:77:77.777 "722) % ... >(.7 ro,>s? affecte ? /6igure out the SELECT statement that returns for each emplo0ee the gen er base on the title of courtes0. 6or ;1s.; an ;1rs.; return ;6emale;< for ;1r.; return ;1ale;< an in all other cases >for e$ample3 ;-r.;? return ;'n+no,n;.

Tables in5ol5e : A=.Emplo0ees table. -esire output:

Co e Die,: Scroll G Sho, #ll empi firstname lastname titleofcourtes0 gen er ----------- ----------------------------------------------------- ------" Sara -a5is 1s. 6emale 2 -on 6un+ -r. 'n+no,n . Su 0 Le, 1s. 6emale % 8ael Pele 1rs. 6emale 5 S5en Cuc+ 1r. 1ale ) Paul Suurs 1r. 1ale / =ussell Jing 1r. 1ale ( 1aria Cameron 1s. 6emale 2 To0a -olgop0ato5a 1s. 6emale >2 ro,>s? affecte ?

(=eturn for each customer the customer I- an region. Sort the ro,s in the output b0 region3 ha5ing &'LLs sort last >after non-&'LL 5alues?. &ote that the efault sort beha5ior of &'LLs in T-SQL is to sort first >before non&'LL 5alues?. Tables in5ol5e : Sales.Customers table. -esire output >abbre5iate ?:

Co e Die,: Scroll G Sho, #ll custi region ----------- --------------55 #J "7 CC %2 CC %5 C# ./ Co. Cor+ .. -6 /" I.( Isle of *ight %) Lara /( 1T ... " &'LL 2 &'LL . &'LL % &'LL 5 &'LL ) &'LL / &'LL ( &'LL 2 &'LL "" &'LL ... >2" ro,>s? affecte ?

Solutions
This section pro5i es the solutions to the e$ercises for this chapter3 accompanie b0 e$planations ,here nee e . "8ou ma0 ha5e consi ere using the 8E#= an 1!&TA functions in the *AE=E clause of 0our solution 4uer03 li+e so: 'SE TSQL6un amentals277(< SELECT or eri 3 or er ate3 custi 3 empi 6=!1 Sales.!r ers *AE=E 8E#=>or er ate? B 277/ #&- 1!&TA>or er ate? B )<

This solution is 5ali an returns the correct result. Ao,e5er3 I e$plaine that if 0ou appl0 manipulation on the filtere

column3 in most cases SQL Ser5er can;t use an in e$ efficientl0 if such manipulation e$ists on that column. Therefore3 I a 5ise using a range filter instea : SELECT or eri 3 or er ate3 custi 3 empi 6=!1 Sales.!r ers *AE=E or er ate EB ;277/7)7"; #&- or er ate M ;277/7/7";< 2#s part of the iscussion about ate an time functions3 I pro5i e the follo,ing e$pression format to calculate the last a0 of the month correspon ing to a gi5en ate: -#TE#-->month3 -#TE-I66>month3 ;"222"2.";3 ateL5al?3 ;"222"2.";?

This e$pression first calculates the ifference in terms of ,hole months bet,een an anchor last a0 of some month >-ecember ."3 "222 in our case? an the gi5en ate. Call this ifference iff. C0 a ing iff months to the anchor ate3 0ou get the last a0 of the gi5en ate;s month. Aere;s the full solution 4uer0 returning onl0 or ers ,here the or er ate is e4ual to the last a0 of the month: Co e Die,: Scroll G Sho, #ll SELECT or eri 3 or er ate3 custi 3 empi 6=!1 Sales.!r ers *AE=E or er ate B -#TE#-->month3 -#TE-I66>month3 ;"222"2.";3 or er ate?3 ;"222"2.";?<

.This e$ercise in5ol5es using pattern matching ,ith the LIJE pre icate. =emember that the percent sign >Q? represents a character string of an0 siOe3 inclu ing an empt0 string. Therefore3 0ou can use the pattern ;QaQaQ; to e$press at least t,o occurrences of the character ;a; an0,here in the string. Aere;s the full solution 4uer0: SELECT empi 3 firstname3 lastname 6=!1 A=.Emplo0ees *AE=E lastname LIJE ;QaQaQ;< %This e$ercise is 4uite tric+03 an if 0ou manage to sol5e it

correctl0 0ou shoul be prou of 0ourself. # subtle re4uirement in the re4uest might be o5erloo+e or interprete incorrectl0. !bser5e that the re4uest sai 9return or ers ,ith total 5alue greater than "737779 an not 9return or ers ,ith 5alue greater than "73777.9 In other ,or s3 the in i5i ual or er etail ro, shoul n;t meet the re4uirement. Instea 3 the group of all or er etails ,ithin the or er shoul meet the re4uirement. This means that the 4uer0 shoul n;t ha5e a filter in the *AE=E clause sa0ing: *AE=E 4uantit0 @ unitprice E "7777

=ather3 the 4uer0 shoul group the ata b0 or er I-3 an a filter in the A#DI&: clause sa0ing: A#DI&: S'1>4uantit0@unitprice? E "7777

ha5e

Aere;s the complete solution 4uer0: SELECT or eri 3 S'1>4t0@unitprice? #S total5alue 6=!1 Sales.!r er-etails :=!'P C8 or eri A#DI&: S'1>4t0@unitprice? E "7777 !=-E= C8 total5alue -ESC< 5Cecause the re4uest in5ol5es acti5it0 in the 0ear 277%3 the 4uer0 shoul ha5e a *AE=E clause ,ith the appropriate ate range filter >or er ate EB ;277%7"7"; #&- or er ate M ;27757"7";?. Cecause the re4uest in5ol5es a5erage freight 5alues per shipping countr0 an the table can ha5e multiple ro,s per countr03 the 4uer0 shoul group the ro,s b0 countr03 an calculate the a5erage freight. To get the three countries ,ith the highest a5erage freights3 the 4uer0 shoul specif0 T!P>.?3 base on logical or er of a5erage freight escen ing. Aere;s the complete solution 4uer0: SELECT T!P>.? shipcountr03 #D:>freight? #S a5gfreight 6=!1 Sales.!r ers *AE=E or er ate EB ;277/7"7"; #&- or er ate M ;277(7"7"; :=!'P C8 shipcountr0 !=-E= C8 a5gfreight -ESC< )Cecause the e$ercise re4uests that the ro, number

calculation be one for each customer separatel03 the e$pression shoul ha5e P#=TITI!& C8 custi . In a ition3 the re4uest ,as to use logical or ering b0 or er ate3 an or eri as a tiebrea+er. Therefore3 the !DE= clause shoul ha5e !=-E= C8 or er ate3 or eri . Aere;s the complete solution 4uer0: Co e Die,: Scroll G Sho, #ll SELECT custi 3 or er ate3 or eri 3 =!*L&'1CE=>? !DE=>P#=TITI!& C8 custi !=-E= C8 or er ate3 or eri ? #S ro,num 6=!1 Sales.!r ers !=-E= C8 custi 3 ro,num<

/8ou can han le the con itional logic re4uire b0 this e$ercise b0 using a C#SE e$pression. 'sing the simple C#SE e$pression form3 0ou specif0 the titleofcourtes0 attribute right after the C#SE +e0,or < list each possible title of courtes0 in a separate *AE& clause follo,e b0 the TAE& clause an the gen er< an in the ELSE clause specif0 ;'n+no,n;: SELECT empi 3 firstname3 lastname3 titleofcourtes03 C#SE titleofcourtes0 *AE& ;1s.; TAE& ;6emale; *AE& ;1rs.; TAE& ;6emale; *AE& ;1r.; TAE& ;1ale; ELSE ;'n+no,n; E&- #S gen er 6=!1 A=.Emplo0ees<

8ou can also use the searche C#SE form ,ith t,o pre icatesone to han le all cases ,here the gen er is female an one for all cases ,here the gen er is male an an ELSE clause ,ith ;'n+no,n;: SELECT empi 3 firstname3 lastname3 titleofcourtes03 C#SE *AE& titleofcourtes0 I&>;1s.;3 ;1rs.;? TAE& ;6emale; *AE& titleofcourtes0 B ;1r.; TAE& ;1ale; ELSE ;'n+no,n; E&- #S gen er 6=!1 A=.Emplo0ees<

(C0 efault SQL Ser5er sorts &'LLs before non-&'LL 5alues. To get &'LLs to sort last3 0ou can use a C#SE e$pression that returns " ,hen the region column is &'LL an 7 ,hen it is not &'LL. &on-&'LLs get 7 bac+ from the e$pression< therefore3 the0 sort before &'LLs >,hich get "?. This C#SE e$pression is use as the first sort column. The region column shoul be specifie as the secon sort column. This ,a03 non&'LLs sort correctl0 among themsel5es. Aere;s the complete solution 4uer0: SELECT custi 3 region 6=!1 Sales.Customers !=-E= C8 C#SE *AE& region IS &'LL TAE& " ELSE 7 E&-3 region<

Potrebbero piacerti anche