Tải bản đầy đủ
Lab 5.3: NULLIF and COALESCE Functions

Lab 5.3: NULLIF and COALESCE Functions

Tải bản đầy đủ

EXPRESSION1.NotethattheNULLIFfunctiondoestheoppositeoftheNVLfunction.If
thefirstexpressionisNULL,thenNVLfunctionreturnsthesecondexpression.Ifthefirst
expressionisnotNULL,thentheNVLfunctionreturnsthefirstexpression.
TheNULLIFfunctionisequivalenttothefollowingCASEexpression:
Clickheretoviewcodeimage
CASE
WHENEXPRESSION1=EXPRESSION2THENNULL
ELSEEXPRESSION1
END

ConsiderthefollowingexampleofaNULLIFfunction:
ForExamplech05_5a.sql
Clickheretoviewcodeimage
DECLARE
v_numNUMBER:=&sv_user_num;
v_remainderNUMBER;
BEGIN
—calculatetheremainderandifitiszeroreturnNULL
v_remainder:=NULLIF(MOD(v_num,2),0);
DBMS_OUTPUT.PUT_LINE(‘v_remainder:‘||v_remainder);
END;

Thisexampleissomewhatsimilartoanexamplethatyousawearlierinthischapter.A
valueisassignedtothevariablev_numatruntime.Next,thisvalueisdividedby2,and
itsremainderiscomparedto0viatheNULLIFfunction.Iftheremainderequals0,the
NULLIFfunctionreturnsNULL;otherwise,itreturnstheremainder.Thevaluereturned
bytheNULLIFfunctionisstoredinthevariablev_remainderanddisplayedonthe
screenviatheDBMS_OUTPUT.PUT_LINEstatement.
Supposethatforthefirstrun,5isassignedtothevariablev_num.Theexample
producesthefollowingoutput:
v_remainder:1

Nowsupposethatforthesecondrun,4isassignedtothevariablev_num.Theexample
producesthefollowingoutput:
v_remainder:

Inthefirstrun,5isnotdivisibleby2,andtheNULLIFfunctionreturnsthevalueofthe
remainder.Inthesecondrun,4isdivisibleby2,andtheNULLIFfunctionreturnsNULL
asthevalueoftheremainder.
TheNULLIFfunctionhasarestriction:YoucannotassignaliteralNULLto
EXPRESSION1.YoulearnedaboutliteralsinChapter2.Consideranotherrunofthe
precedingexample,inwhichthevariablev_numisassignedavalueofNULL,asshown
inFigure5.3.Inthisinstance,theexampleproducesthefollowingoutput:
v_remainder:

Figure5.3AssigningLiteralNULLinSQLDeveloper
WhenNULLisassignedtothevariablev_num,boththeMODandNULLIFfunctions
returnNULL.Theprecedingexampledoesnotproduceanyerrorsbecausetheliteral
NULLisassignedtothevariablev_num,anditisnotusedasthefirstexpressionofthe
NULLIFfunction.
Nowconsideramodifiedversionoftheprecedingexample(changesareshownin
bold):
ForExamplech05_5b.sql
Clickheretoviewcodeimage
DECLARE
v_remainderNUMBER;
BEGIN
—calculatetheremainderandifitiszeroreturnNULL
v_remainder:=NULLIF(NULL,0);
DBMS_OUTPUT.PUT_LINE(‘v_remainder:‘||v_remainder);
END;

Inthepreviousversionofthisexample,theMODfunctionwasusedasEXPRESSION1.
Inthisversion,theliteralNULLisusedinplaceoftheMODfunction,sothattheexample
producesthefollowingsyntaxerror:
Clickheretoviewcodeimage
v_remainder:=NULLIF(NULL,0);
*
ERRORatline5:
ORA-06550:line5,column26:
PLS-00619:thefirstoperandintheNULLIFexpressionmustnotbeNULL
ORA-06550:line5,column4:
PL/SQL:Statementignored

COALESCEFunction
TheCOALESCEfunctioncompareseachexpressiontoNULLfromthelistofexpressions
andreturnsthevalueofthefirstnon-NULLexpression.TheCOALESCEfunctionhasthe
structureshowninListing5.4.

Listing5.4COALESCEFunction
Clickheretoviewcodeimage
COALESCE(EXPRESSION1,EXPRESSION2,…,EXPRESSIONN)

IfEXPRESSION1evaluatestoNULL,thenEXPRESSION2isevaluated.If
EXPRESSION2doesnotevaluatetoNULL,thenthefunctionreturnsEXPRESSION2.If
EXPRESSION2alsoevaluatestoNULL,thenthenextexpressionisevaluated.Ifall
expressionsevaluatetoNULL,thefunctionreturnsNULL.
NotethattheCOALESCEfunctionislikeanestedNVLfunction:
Clickheretoviewcodeimage
NVL(EXPRESSION1
,NVL(EXPRESSION2
,NVL(EXPRESSION3,…)
)
)

TheCOALESCEfunctioncanalsobeusedasanalternativetoaCASEexpression.For
example,
Clickheretoviewcodeimage
COALESCE(EXPRESSION1,EXPRESSION2)

isequivalentto
Clickheretoviewcodeimage
CASE
WHENEXPRESSION1ISNOTNULL
THEN
EXPRESSION1
ELSE
EXPRESSION2
END

Iftherearemorethantwoexpressionstoevaluate,then
Clickheretoviewcodeimage
COALESCE(EXPRESSION1,EXPRESSION2,…,EXPRESSIONN)

isequivalentto
Clickheretoviewcodeimage
CASE
WHENEXPRESSION1ISNOTNULL
THEN
EXPRESSION1
ELSE
COALESCE(EXPRESSION2,…,EXPRESSIONN)
END

whichinturnisequivalentto
Clickheretoviewcodeimage
CASE
WHENEXPRESSION1ISNOTNULL
THEN
EXPRESSION1

WHENEXPRESSION2ISNOTNULL
THEN
EXPRESSION2

ELSE
EXPRESSIONN
END

ConsiderthefollowingexampleoftheCOALESCEfunction:
ForExamplech05_6a.sql
Clickheretoviewcodeimage
SELECTe.student_id
,e.section_id
,e.final_grade
,g.numeric_grade
,COALESCE(e.final_grade,g.numeric_grade,0)grade
FROMenrollmente
,gradeg
WHEREe.student_id=g.student_id
ANDe.section_id=g.section_id
ANDe.student_id=102
ANDg.grade_type_code=‘FI’;

ThisSELECTstatementreturnsthefollowingoutput:
Clickheretoviewcodeimage

STUDENT_IDSECTION_IDFINAL_GRADENUMERIC_GRADE
–––-–––-–––—––––-–—
10286(null)85
102899292

ThevalueofGRADEequalsthevalueofNUMERIC_GRADEinthefirstrow.The
COALESCEfunctioncomparesthevalueofFINAL_GRADEtoNULL.IfitisNULL,then
thevalueofNUMERIC_GRADEiscomparedtoNULL.Becausethevalueof
NUMERIC_GRADEisnotNULL,theCOALESCEfunctionreturnsthevalueof
NUMERIC_GRADE.ThevalueofGRADEequalsthevalueofFINAL_GRADEinthe
secondrow.TheCOALESCEfunctionreturnsthevalueofFINAL_GRADEbecauseitis
notNULL.
TheCOALESCEfunctionshowninthepreviousexampleisequivalenttothefollowing
NVLstatementandCASEexpressions:
Clickheretoviewcodeimage
NVL(e.final_grade,NVL(g.numeric_grade,0))
CASE
WHENe.final_gradeISNOTNULL
THEN
e.final_grade
ELSE
COALESCE(g.numeric_grade,0)
END

and
Clickheretoviewcodeimage

CASE
WHENe.final_gradeISNOTNULL
THEN
e.final_grade
WHENg.numeric_gradeISNOTNULL
THEN
g.numeric_grade
ELSE
0
END

Summary
InChapter4,youbeganexploringconditionalcontrolstructuressupportedbyOracle’s
PL/SQLlanguage.Inthischapter,youcontinuedthisexplorationbylearningaboutCASE
statementsandexpressionsandCOALESCEandNULLIFfunctions.Youhavelearned
howtoemployCASEstructuresinbothSQLandPL/SQLlanguages.
BytheWay
Thecompanionwebsiteprovidesadditionalexercisesandsuggestedanswers
forthischapter,withdiscussionrelatedtohowthoseanswersresulted.The
mainpurposeoftheseexercisesistohelpyoutestthedepthofyour
understandingbyutilizingalloftheskillsthatyouhaveacquiredthroughout
thischapter.

6.IterativeControl:PartI
Inthischapter,youwilllearnabout
SimpleLoops
WHILELoops
NumericFORLoops
Generally,computerprogramsarewrittenbecausecertaintasksmustbeexecuteda
numberoftimes.Forexample,manycompaniesneedtoprocesstransactionsonamonthly
basis.Aprogramallowsthecompletionofthistaskbybeingexecutedattheendofeach
month.
Similarly,programsincorporateinstructionsthatneedtobeexecutedrepeatedly.For
example,aprogrammayneedtowriteanumberofrecordstoatable.Throughtheuseof
aloop,theprogramcanwritethedesirednumberofrecordstoatable.Inotherwords,
loopsareprogrammingfacilitiesthatallowasetofinstructionstobeexecutedrepeatedly.
InPL/SQL,therearefourtypesofloops:simpleloops,WHILEloops,numericFOR
loops,andcursorFORloops.Inthischapter,youwillexploresimpleloops,WHILEloops,
andnumericFORloops.InChapter7,youwillseehowthesetypesofloopscanbenested
withinoneanother.Inaddition,youwilllearnabouttheCONTINUEandCONTINUE
WHENstatements,whichwereintroducedinOracle11g.CursorFORloopsarediscussed
inChapters11and12.

Lab6.1:SimpleLoops
Afterthislab,youwillbeableto
UseSimpleLoopswithEXITConditions
UseSimpleLoopswithEXITWHENConditions
Asimpleloop,asyoucanseefromitsname,isthemostbasickindofloopandhasthe
structureshowninListing6.1.
Listing6.1SimpleLoopStructure
LOOP
STATEMENT1;
STATEMENT2;

STATEMENTN;
ENDLOOP;

ThereservedwordLOOPmarksthebeginningofthesimpleloop.Statements1through
Nareasequenceofstatementsthatisexecutedrepeatedly.Thesestatementsconsistofone
ormoreofthestandardprogrammingstructures.ENDLOOPisareservedphrasethat

indicatestheendoftheloopconstruct.Theflowoflogicfromthisstructureisillustrated
inFigure6.1.

Figure6.1SimpleLoop
Everytimethesimpleloopisiterated,asequenceofstatementsisexecuted,andthen
controlpassesbacktothetopoftheloop.Thesequenceofstatementswillexecutean
infinitenumberoftimes,becausethereisnostatementspecifyingwhentheloopmust
terminate.Hence,asimpleloopiscalledaninfiniteloopbecausethereisnomeanstoexit
theloop.Aproperlyconstructedloopneedstohaveanexitconditionthatdetermines
whentheloopiscomplete.Thisexitconditionhastwoforms:EXITandEXITWHEN.

EXITStatement
TheEXITstatementcausesalooptoterminatewhentheexitconditionevaluatesto
TRUE.TheexitconditionisevaluatedwiththehelpofanIFstatement.Whentheexit
conditionevaluatestoTRUE,controlpassestothefirstexecutablestatementaftertheEND
LOOPstatement.ThestructureofthistypeofloopisshowninListing6.2.
Listing6.2SimpleLoopStructurewithanEXITStatement
LOOP
STATEMENT1;
STATEMENT2;
IFEXITCONDITIONTHEN
EXIT;
ENDIF;
ENDLOOP;
STATEMENT3;

Inthiscodelisting,youcanseethataftertheEXITCONDITIONevaluatestoTRUE,
controlpassestoSTATEMENT3,whichisthefirstexecutablestatementaftertheEND
LOOPstatement.ThisflowoflogicisillustratedinFigure6.2.

Figure6.2SimpleLoopwiththeExitCondition
AsshowninFigure6.2,duringeachiteration,theloopexecutesasequenceof
statements.Controlthenpassestotheexitconditionoftheloop.Iftheexitcondition
evaluatestoFALSE,controlpassestothetopoftheloop.Thesequenceofstatementswill
beexecutedrepeatedlyuntiltheexitconditionevaluatestoTRUE.Atthatpoint,theloopis
terminatedviatheEXITstatement,andcontrolpassestothenextexecutablestatement
followingtheloop.
Figure6.2alsoshowsthattheexitconditionisincludedinthebodyoftheloop.
Therefore,thedecisionaboutloopterminationismadeinsidethebodyoftheloop,andthe
bodyoftheloop,orapartofit,willalwaysbeexecutedatleastonce.However,the
numberofiterationsoftheloopdependsontheevaluationoftheexitconditionandisnot
knownuntiltheloopcompletes.
Thisbehaviorisfurtherillustratedbythefollowingexample:
ForExamplech06_1a.sql

Clickheretoviewcodeimage
DECLARE
v_counterBINARY_INTEGER:=0;
BEGIN
LOOP
—incrementloopcounterbyone
v_counter:=v_counter+1;
DBMS_OUTPUT.PUT_LINE(‘v_counter=‘||v_counter);
—ifexitconditionyieldsTRUEexittheloop
IFv_counter=5
THEN
EXIT;
ENDIF;
ENDLOOP;
—controlresumeshere
DBMS_OUTPUT.PUT_LINE(‘Done…’);
END;

Inthisexample,thevariablev_counterkeepscountoftheloopiterationsandis
oftenreferredtoasaloopcounter.Thestatement
v_counter:=v_counter+1;

isusedfrequentlywhenworkingwithloops,asitincrementsthevalueofv_counterby
1.Oncethevalueofthev_counterreaches5,theexitcondition
v_counter=5

evaluatestoTRUEandtheloopterminates.Asmentionedpreviously,assoonastheloop
terminates,thecontrolpassestothefirstexecutablestatementaftertheENDLOOP
statement.
Whenexecuted,thisexampleproducesthefollowingoutput:
v_counter=1
v_counter=2
v_counter=3
v_counter=4
v_counter=5
Done…

WatchOut!
Itisveryimportanttoinitializethevariablev_counterforsuccessful
terminationoftheloop.Ifv_counterisnotinitialized,itsvalueremains
NULLandthestatement
v_counter:=v_counter+1;

neverincrementsthevalueofv_counterby1becauseNULL+1evaluates
toNULL.Asaresult,theexitconditionneverevaluatestoTRUE,andtheloop
becomesaninfiniteloop.
Asmentionedpreviously,whenworkingwiththeloops,theplacementoftheexit
conditionaffectswhetherstatementsinsidethebodyoftheloopareexecutedduringthe
lastiterationoftheloop.Consideramodifiedversionofthepreviousexamplewiththe

exitconditionplacedimmediatelyafterthevalueofv_counterisincrementedby1.
Affectedstatementsareshowninbold.
ForExamplech06_1b.sql
Clickheretoviewcodeimage
DECLARE
v_counterBINARY_INTEGER:=0;
BEGIN
LOOP
—incrementloopcounterbyone
v_counter:=v_counter+1;
—ifexitconditionyieldsTRUEexittheloop
IFv_counter=5
THEN
EXIT;
ENDIF;
DBMS_OUTPUT.PUT_LINE(‘v_counter=‘||v_counter);
ENDLOOP;
—controlresumeshere
DBMS_OUTPUT.PUT_LINE(‘Done…’);
END;

Thisversionoftheexampleproducesslightlydifferentoutput:
v_counter=1
v_counter=2
v_counter=3
v_counter=4
Done…

Inthisversionofthescript,theportionoftheloopbeforetheexitconditionexecuted5
times.Inotherwords,thevariablev_counterwasincrementedby1fivetimes.
However,onthefifthiterationoftheloop,theexitconditionevaluatedtoTRUE,sothe
Clickheretoviewcodeimage
DBMS_OUTPUT.PUT_LINE(‘v_counter=‘||v_counter);

statementwasnotexecuted.Instead,controlpassedtothefirstexecutablestatementafter
theENDLOOP.Inessence,thisplacementoftheexitconditioncausedpartialexecution
oftheloopbodyonthelastiterationoftheloop.

DidYouKnow?
TheEXITstatementisvalidonlywhenplacedinsideofaloop.Whenplaced
outsideofaloop,itwillcauseasyntaxerror.Toavoidthiserror,usethe
RETURNstatementtoterminateaPL/SQLblockbeforeitsnormalendis
reachedasfollows:
Clickheretoviewcodeimage
BEGIN
DBMS_OUTPUT.PUT_LINE(‘Line1’);
RETURN;
DBMS_OUTPUT.PUT_LINE(‘Line2’);
END;

Thisexampleproducesthefollowingoutput:
Line1

BecausetheRETURNstatementterminatesthePL/SQLblock,thesecond
DBMS_OUTPUT.PUT_LINEstatementisneverexecuted.
Ifusedwithoutanexitcondition,theEXITstatementwillcausethesimple
looptoexecuteonlyonce.Considerthefollowingexample:
Clickheretoviewcodeimage
DECLARE
v_counterNUMBER:=0;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE(‘v_counter=‘||v_counter);
EXIT;
ENDLOOP;
END;

Thisexampleproducesthefollowingoutput:
v_counter=0

BecausetheEXITstatementisusedwithoutanexitcondition,theloop
terminatesassoonastheEXITstatementexecutes.

EXITWHENStatement
TheEXITWHENstatementcausesalooptoterminateonlyiftheexitwhencondition
evaluatestoTRUE.ControlthenpassestothefirstexecutablestatementaftertheEND
LOOPstatement.ThestructureofaloopusinganEXITWHENstatementisshownin
Listing6.3.
Listing6.3SimpleLoopStructurewithanEXITWHENStatement
LOOP
STATEMENT1;
STATEMENT2;
EXITWHENEXITCONDITION;
ENDLOOP;
STATEMENT3;