Tải bản đầy đủ - 0 (trang)
Appendix IV. Creating and Managing Server-Side Cursors

Appendix IV. Creating and Managing Server-Side Cursors

Tải bản đầy đủ - 0trang

WhyAreServer-sideCursorsImportant?

Foroveradecade,T-SQLServerandotherDBMSdevelopers

havebeenusingserver-sidecursorstoaccesstheirdatabases

andscrollthroughupdateablerowsets.Aserver-sidecursorin

itspurestformissimplyablockofpointerstolivedatarowsas

definedbyaSELECTstatement.Thecursorcanincludeallrows

fromaspecifictableorjustaselectedfew.Itcanaddressrows

generatedfromaJOIN,view,orstoredprocedure.Again,when

youcreateaserver-sidecursor,youaren'taskingfordata;

you'reaskingforpointerstothedata.Thismeansthatthedata

remainswhereitshouldremainontheserver,whereother

clientscanseeandchangethevalues.Whenyoufetchrows

fromaserver-sidecursor,youarefetchingthe"live"dataasitis

ontheserverthatinstantnotsomecachedversionthat'sbeen

sittingaroundinmemoryforafewsecondstoafewdays.

Server-sidecursorswereimplementedintheearliestversions

ofRDOandasthedefaultcursorinADOclassic.This

"connected"dataaccessparadigmassumesthatthedatabase

connectionremainsinplacewhiletheapplicationrunsaquery

andbuildsaserver-sidestructurethatpermitsonetobrowse

upandbackthroughasetofrowsthatcanberetrievedand

updatedasneeded.

Server-sidecursorsareespeciallyusefulwhenworkingwith

highlyinteractiveapplicationsespeciallywhentheapplication

cannotworkwithdisconnected(static)data.Thistypeof

applicationneedsamechanismtoworkwithasinglerowora

smallsetofrowsatonce.Server-sidecursorsaredesignedto

meetthisneed.Asillustratedbytheexamplesinthisappendix,

I'llshowyouhowto:

CreateacursorbasedonafocusedSELECTstatement



Positionacursortoanydesignatedrow

Changethedatainthecurrentlyselectedcursorrow

Adaptthecursorsootherusers'changesarevisible(ornot)







HowDoesADO.NETImplementCursors?

ADO.NETisfullycapableofrunningqueries,butthe"cursor"it

knowshowtocreateisnotthesameasDAO,RDO,orADO

"classic"(ADOc)developersmightbeusedto.Inthestrictest

sense,acursorisadeviceusedtobrowsethroughtherows

thatresultfromaquery.Somecursorsarescrollable,soyou

canpositiona"current-row"pointeratarbitrarypointsinthe

rowsetandreturnaspecificrow,whileothersare"forwardonly".Iexpectmostofyouareinterestedinfullyscrollable

cursors.

Yes,ifyousquintaDataTablemightbethoughtofasacursor,

inthatitexposesaRowscollectionthatcanbebrowsed(or

scrolled)inanyorder.ButaDataTableisstaticclient-side

datait'sreallynodifferentthansimplytakingaDB-Librarydata

streamanddumpingitintoalocalarray.Whileserver-side

cursorscanalsobestaticdata(thatdoesnotchangeasthe

databaseisupdated),server-sidecursorscanalsobeafixed

setofkeys(akeysetcursor)oradynamicallychangingsetof

keys(adynamiccursor)thatpointstolivedata.That'sthe

criticaldifference.Server-sidecursorsleavethedataonthe

server(ortheycan),returningonly"pointers"intheformof

keysthatpointbacktolivedata.Asotheruserschangethe

data,thecursormemberkeysstillpointtofreshdata.

TheADO.NETarchitectsandMicrosoftproductmanagersthink

thatstatic,client-sideDataTableandTableAdapterobjectsare

enoughformanycustomers.They'rerightuptoapoint.Ithink

thatquiteafewapplicationsdesignedtouseserver-side

cursorscouldhavebeenwrittenusingclient-sidestaticcursors.

However,whentheyare,developersaresometimesforcedto

makeextraround-tripstotheservertodetectchangesinthe

dataormembership.AnotherapproachMicrosoftispromoting

isT-SQLServerNotificationServices,whereyoucansetupcallbackstoyourapplicationwhenspecifically(andcarefully)



selecteddatachanges.However,thisapproachisnotforthe

faintofheartorsimple,fast,mainstreamapplications.

Ithinkthereareplentyofviablesituationswhereaserver-side

cursormakessense.IkeephearingthatMicrosoftwas

concernedthatdeveloperswere"misusing"server-sidecursors.

That'sunderstandable,asthedefaultcursorlibrary

(CursorType)inADOimplementsaserver-sidecursor

(adUseServer)soit'stheirownfault.Inaddition,toomany

examplesillustratedfundamentaloperationsusing(often

expensive)server-sidecursors.Ithinkthatdevelopersare

smartenoughtomakeuptheirownminds,andserver-side

cursorscanincreasedeveloperandcodeperformanceifused

wisely.

Thisapproachtodataaccessisnotparticularlyinterestingin

statelessWeb-basedapplications.Itmakesthemostsensein

connectedWindowsFormsapplications.







HowAreServer-SideCursorsManaged?

AllofmyHitchhiker'sGuidebookshavediscussedcursorsat

lengthatleasttheoneswhereADO,RDO,orDAOimplemented

them.SinceADO.NETdoesnotsupportthisparadigm,I'llneed

toaddafewparagraphsheretorefreshyourunderstandingof

themechanicsandterminology.

First,whenyouexecuteaquerytobuildaserver-sidecursor

(oranycursor,forthatmatter),SQLServerlooksthroughthe

databasetofindqualifyingrows.YourWHEREclauseandother

SELECTstatementoperatorsdeterminewhichrowsaretobe

includedandwhicharenot.Whilethisoperationisnot

instantaneous,therowsfoundbecomepartofthecursor

"membership."IfthereisnoWHEREclauseintheSELECT

query,allrowsinthetargettable(s)aremademembersofthe

cursorthatcanbeexpensive.Rememberthatserver-side

cursors(likeakeysetcursor)aresimplyatemporarycollection

ofpointerstotheactualrows.

Thereareseveraltypesofserver-sidecursors[1]:

[1]See"DECLARECURSOR"(TransactSQL)inBOL.



Staticcursorscontainascrollablesetofrowsnotjustkeys.

SQLServercreatesaone-timetemporarycopyofthedata

inTempDb,somembershipisfixed.Referencestothe

cursorarefetchedfromthistemporarytable.Staticcursors

arenotupdateable.

Keysetcursorscontainasetofkeysusedtofetchthe

actualrows.SQLServercreatesaone-timetemporarytable

thatcontainsPKsofmemberrows,somembershipisfixed.

Referencestocursorrowsarefetchedusingkeysfromthis

temporarytable.Aschangesaremadetothedatabase(to



non-keycolumns),thesevaluesaremadevisiblewhenthe

rowisfetched(orrefetched).Ifamemberrowisdeleted,

@@FetchStatusreturns2.Rowsaddressedbykeyset

cursorsareupdateablethroughuseoftheUPDATEWHERE

CURRENTOFsyntax(that'sillustratedintheexample

application).Youcanpositiontoanyspecificmemberrow

usingtheABSOLUTEfetchoptionorscrollthroughrows

usingFETCHNEXT,PRIOR,LAST,andFIRSTfetchoptions.

KeysetcursorsdefaulttoSCROLL(scrollable)positioning

butcanbesettoFORWARD_ONLYhowever,thatdoesnot

makemuchsensetome.

Dynamiccursorsarelikekeysetcursorsinmostrespects,

exceptthatmembershipisdynamicthat'sbecauseeach

timeaDynamiccursorrowisaccessed,theSELECTqueryis

re-executedtorepopulatethemembership.Thesecursors

areexpensiveanddonotsupportabsolutepositioning.

Forward-Onlyisanoptionfortheothercursortypesthat

disablestheabilitytoscrollthroughtherows.FETCHNEXT

istheonlyavailablefetchoptionforFORWARD_ONLY

cursors.WhendeclaredwithouttheSTATIC,KEYSET,or

DYNAMICkeywords,theFORWARD_ONLYcursordefaultsto

DYNAMIC(whichmeansthatyoushouldalwaysindicateone

oftheothertypes).

Othercursoroptionspermityoutospecifyifthecursorcanbe

"seen"byotherapplicationsaccessingSQLServerbeyondyour

application'sconnection.SeeSQLServer2005BOLformore

specificdetailsontheseoptions.Theydescribehowtomake

cursorsvisibletostoredproceduresandelsewhere.



WhatDoServer-SideCursorsCost?

Oneofthedownsidesofserver-sidecursorsistheburdenthey



imposeonT-SQLServerandthescalabilityofyourapplications.

Whenyoucreateaserver-sidecursor,T-SQLServerwritesaset

ofkeysorentirerowstomemoryorTempDB.Thisprocessis

repeatedanditseffectsmultipliedforeachapplicationthat

opensaserver-sidecursor.Usingserver-sidecursorsalso

assumesthattheconnectionremainsopenaslongasthe

cursor'sdataisneeded.Thisisdefinitelynotagoodideafora

Web-based(ASP/ASPX)applicationbecausetheconnectionis

usuallyclosed,anditsresourcesreleased,justafteritsqueries

areexecuted.Ontheotherhand,formanytraditional

client/serverapplications,server-sidecursorshavebeenan

effectivewaytomanagedataandsimplifyapplication

designwhenusedwisely.



HowCanADO.NETCreateaServer-Side

Cursor?

InmyADO.NETbook,Istate(repeatedly)thatADO.NETcannot

createaserver-sidecursor.Strictlyspeaking,thisistrueonits

own,itcan't.However,it'strueonlyinthesensethatitcan't

createandmanageaserver-sidecursoronitsowninthesame

waythatDAOandADOccan.AsI'llshowyouinthisappendix,

youcancreateserver-sidecursorsusingsomefairlyeasy

ADO.NETmethods.

It'snotagoodideatousethefollowingtechniqueswhen

workingwithADOc.That'sbecausetheserver-sidecursor

mechanismswithinADOccanconflictwithanycursorsyou

createonyourownusingT-SQL.



Thistechniqueisreallyprettysimpleit'sbasedonusingT-SQL

tocreateANSIcursors.Asillustratedintheexamplecode,Iuse

theADO.NETCommandobjecttoexecutespecificT-SQLscripts

(twoormoretightlycoupledT-SQLstatements),includingthe

DECLARECURSORstatementandtheFETCHandDEALLOCATE

ANSIcursorcommands.Let'sstepthroughtheprocessof

creatingandmanagingacursor.



Opening,Closing,andRe-openingthe

Connection

UnlikeotherADO.NETexamplesinthisbookandelsewhere,

whenbuildingaserver-sidecursor,thecodeneedstoopena



connectiontotheT-SQLServerinstanceandkeepitopen.

That'sbecausethecursorisbuiltandmaintainedbytheserver

andownedbytheconnection.Oncetheconnectioncloses,the

cursoris(usually)flushed[2](atleastwhentheconnection

poolerclosesorresetstheconnection).

[2]It'spossibletocreateadatabase-persistentcursorusingtheGLOBALoption.



AsdiscussedinChapter9,"GettingConnected,"considerthata

WindowsFormsapplicationcreatesanewconnectionpoolfor

eachuniqueconnectionstring.Thismeansthatifyoucreatea

cursor,itwon'tbedestroyed(atleast,notimmediately)when

youclosetheconnectionassumingthatyou'reusingconnection

pooling(whichisonbydefault).However,iftheconnection

resetoptionisenabled(itisbydefault),thecursoriscleared

whentheconnectionisreusedagainsothenewconnection

ownercannotinheritthecursor.Ifyouturnoffthereset

connectionoption,thecursorshouldremainviableforreuseby

yourapplicationitwillstillbetherewhenyoureopenthe

connection.However,iftheconnectionpooltimesoutthe

connection,whichforcestheconnectionclosed,yourcursoris

lost.Ofcourse,inaWindowsFormsapplication,it'sperfectly

reasonabletodisableconnectionpooling.Inthiscase,whenthe

connectionisclosed,thecursorislost.No,thedataaddressed

bythecursorisundisturbedwhenthecursorisclosed.



CreatingtheCursor

ThenextstepistocreatethecursorbasedonaT-SQL

statement.ThisblockofcodeusestheT-SQLstatementpassed

fromtheuserinaTextBoxcontrol.(No,it'snotagoodideato

justacceptanythingfromauser,butthisisademonstration

andtestprogram,soI'mprettygenerouswithwhatIpermitin

theT-SQL.)Tobesafe(er),IcalltheValidateSQLroutinetodo

someroughteststomakesureI'mnottoosleepyandenter



somethingdestructive.

TheT-SQLusedtocreatetheANSIserver-sidecursorcanbe

brokendownintothreeparts(asshowninFigureIV.1):

1. TheDECLAREcursorstatement,whichnamesthecursor

andsetstheoptionstouse.Inthiscase,thecodeasksfor

asimplescrollablecursor(asopposedtoaforward-only

cursor)andnamesitmyCursor.

2. TheT-SQLSELECTstatement,whichisexecutedtobuild

thecursorrowset,followstheCURSORFORargument.The

SELECTstatementshouldfocusthecursoronafew

manageablerowsinthedatabasenotanentiredatabase

tableifyouexpecttoscaletheapplication.Sure,theSELECT

cancontainaJOINoraVIEW,aslongasit'sastandard

(simple)SELECTstatement.ThekeywordsCOMPUTE,

COMPUTEBY,FORBROWSE,andINTOarenotallowed.

3. ASELECTquerytoreturnthenumberofrowsinthecursor.

Ifyouselectalargenumberofrows,thisquerywill

probablyreturn1untilT-SQLServerhascompletedserversiderowsetpopulation(untilSQLServerhasfoundallofthe

memberrowsandaddedthemtothecursor).



FigureIV.1.Constructingaserver-sidecursor.



[Viewfullsizeimage]



Next,thecodeexecutestheT-SQLusingtheADO.NET

Commandobject'sExecuteScalarmethod.Thisreturnsthe

@@CURSOR_ROWSglobalvariable,soIknowhowmanyrows

areinthecursor.Remembernottoclosetheconnectionafter

havingcreatedthecursorifyoudo,thecursorwillbedropped

byT-SQLServer.







Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Appendix IV. Creating and Managing Server-Side Cursors

Tải bản đầy đủ ngay(0 tr)

×