Thebasic stepsinusinga row-positionedcursorare:
1. ExecuteaDECLARE CURSORstatementtodefinetheresult tableonwhichthe cursoroperates.See“Step 1:Declarethecursor.”
2. ExecuteanOPENCURSORtomakethecursoravailable totheapplication. See
“Step2: Openthecursor” onpage127.
3. Specifywhattheprogramistodowhen allrowshavebeenretrieved.See
“Step3: Specifywhattodoatend-of-data”onpage128.
4. ExecutemultipleSQLstatementsto retrievedatafromthetableormodify selectedrowsofthetable.See “Step4:ExecuteSQLstatements”onpage128.
5. ExecuteaCLOSECURSORstatementtomake thecursorunavailable tothe application.See“Step 5:Closethecursor” onpage130.
Yourprogramcanhaveseveralcursors,eachof whichperformstheprevioussteps.
Step 1: Declare the cursor
Todefineandidentifya setofrowstobeaccessedwith acursor,issuea
DECLARE CURSORstatement.TheDECLARECURSORstatementnamesacursor and specifiesa SELECTstatement.TheSELECTstatementdefinesthecriteriafor
therowsthataretomakeuptheresulttable.For acompletelistofclausesthat youcanuseintheSELECTstatement, seethetopic“select-statement”inDB2 SQL Reference.
The followingexampleshows asimpleform oftheDECLARECURSORstatement:
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
FROM DSN8910.EMP
END-EXEC.
Youcanusethiscursortolistselectinformationaboutemployees.
More complicatedcursorsmightinclude WHEREclausesorjoinsofseveraltables.
For example,supposethatyouwanttousea cursortolistemployeeswhowork ona certainproject.Declareacursorlikethis toidentifythoseemployees:
EXEC SQL
DECLARE C2 CURSOR FOR
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
FROM DSN8910.EMP X
WHERE EXISTS
(SELECT *
FROM DSN8910.PROJ Y
WHERE X.EMPNO=Y.RESPEMP
AND Y.PROJNO=:GOODPROJ);
Declaringcursors fortablesthatusemultilevelsecurity:Youcandeclarea cursor thatretrievesrowsfroma tablethatusesmultilevelsecuritywithrow-level granularity.However, theresult tableforthecursorcontainsonlythoserowsthat havea securitylabelvaluethatisequivalenttoordominatedbythesecuritylabel value ofyourID. Formoreinformationaboutmultilevel securitywith row-level granularity,seethetopic“Multilevelsecurity” inDB2AdministrationGuide.
Updating acolumn:Youcanupdatecolumns intherowsthatyouretrieve.
Updatingarow afteryouusea cursortoretrieveit iscalleda positionedupdate. If youintendtoperformanypositionedupdatesontheidentifiedtable,includethe FOR UPDATEclause.TheFOR UPDATEclausehastwoforms:
v ThefirstformisFORUPDATEOFcolumn-list.Use thisformwhenyouknowin advancewhichcolumnsyouneedtoupdate.
v ThesecondformisFORUPDATE,withnocolumnlist.Usethisformwhen you mightusethecursortoupdateanyofthecolumns ofthetable.
For example,youcanusethiscursortoupdateonlytheSALARYcolumnof the employeetable:
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
FROM DSN8910.EMP X
WHERE EXISTS
(SELECT *
FROM DSN8910.PROJ Y
WHERE X.EMPNO=Y.RESPEMP
AND Y.PROJNO=:GOODPROJ)
FOR UPDATE OF SALARY;
Ifyoumightusethecursortoupdateanycolumnoftheemployeetable,define thecursorlikethis:
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
FROM DSN8910.EMP X
WHERE EXISTS
(SELECT *
FROM DSN8910.PROJ Y
WHERE X.EMPNO=Y.RESPEMP
AND Y.PROJNO=:GOODPROJ)
FOR UPDATE;
DB2 mustdomore processingwhenyouusetheFORUPDATEclausewithouta column listthanwhenyouusetheFORUPDATEclausewith acolumnlist.
Therefore,ifyouintendtoupdateonlyafewcolumns ofatable,yourprogram canrunmoreefficientlyifyouinclude acolumnlist.
TheprecompileroptionsNOFORandSTDSQLaffecttheuseoftheFORUPDATE clauseinstaticSQLstatements.Forinformationabouttheseoptions, seeTable95 onpage550.IfyoudonotspecifytheFORUPDATEclauseinaDECLARE CURSORstatement, andyoudonotspecifytheSTDSQL(YES)option orthe NOFOR precompileroptions, youreceiveanerrorifyouexecutea positioned UPDATE statement.
Youcanupdateacolumnoftheidentifiedtable eventhoughitisnotpartofthe result table.Inthis case,youdonotneedtonamethecolumnintheSELECT statement. Whenthecursorretrievesa row(usingFETCH)thatcontains acolumn value youwanttoupdate,youcanuseUPDATE... WHERECURRENTOFto identifytherowthatistobeupdated.
Read-onlyresulttable:Someresult tablescannotbeupdated—forexample,the result ofjoiningtwoormoretables.Forinformationaboutthedefining
characteristicsofread-onlyresult tables,seethetopic“DECLARECURSOR”in DB2 SQLReference.
Step 2: Open the cursor
TotellDB2thatyouarereadytoprocessthefirstrow oftheresult table,execute theOPEN statementinyour program.DB2then usestheSELECT statementwithin DECLARE CURSORtoidentifya setofrows. Ifyouusehostvariablesinthe searchcondition ofthatSELECTstatement,DB2usesthecurrentvalueof the variablestoselecttherows.Theresulttable thatsatisfies thesearchcondition might containzero,one,ormanyrows.An exampleofanOPEN statementis:
EXEC SQL
OPEN C1
END-EXEC.
IfyouusetheCURRENTDATE,CURRENTTIME, orCURRENTTIMESTAMP special registersinacursor,DB2determinesthevaluesinthosespecial registers onlywhenitopens thecursor.DB2usesthevaluesthatitobtainedatOPEN time forall subsequentFETCHstatements.
Two factorsthatinfluencetheamount oftimethatDB2requirestoprocessthe OPEN statementare:
v WhetherDB2must performanysortsbefore itcanretrieverows
v WhetherDB2usesparallelismtoprocess theSELECTstatementofthecursor For moreinformation,see“Theeffectof sortsonOPENCURSOR” onpage938.
Step 3: Specify what to do at end-of-data
Todeterminewhethertheprogramhasretrievedthelastrowofdata,testthe SQLCODEfieldfora valueof100 ortheSQLSTATEfieldfora valueof’02000’.
Thesecodesoccur whenaFETCHstatementhasretrievedthelastrowintheresult table andyourprogramissuesasubsequentFETCH. Forexample:
IF SQLCODE = 100 GO TO DATA-NOT-FOUND.
An alternativetothistechniqueistocodetheWHENEVERNOTFOUND statement. TheWHENEVERNOTFOUNDstatementcausesyourprogramto branchtoanotherpartthatthen issuesa CLOSEstatement. Forexample,tobranch tolabelDATA-NOT-FOUNDwhentheFETCHstatementdoesnotreturna row, usethisstatement:
EXEC SQL
WHENEVER NOT FOUND GO TO DATA-NOT-FOUND END-EXEC.
Yourprogrammustanticipateand handleanend-of-datawheneveryouusea cursortofetch arow.Formore informationabouttheWHENEVERNOT FOUND statement, see“Checkingtheexecutionof SQLstatements”onpage113.
Step 4: Execute SQL statements
YouexecuteoneoftheseSQLstatementsusingthecursor:
v AFETCHstatement
v Apositioned UPDATEstatement v Apositioned DELETEstatement