Avoid COUNT(*) Unless Count is Required
Consider the following requirement: Get the ID for the company which matches specified name. If no match, display error. If more than one match, show list. If single match, return ID. How do you handle this situation? The most o !ious and common solution is to use C"#$T to figure out how many matches you ha!e for the name, and then e%ecute logic from there. &ut are you really answering the 'right question?' (hen you do a C"#$T, you find out how many matches there are. If you don)t really care how many, ut *ust that there is more than one match, C"#$T is o!er+ill. ,or e%ample: &-GI$ .-/-CT C"#$T012 I$T" the3count ,4"5 company (H-4- name /I6- :cllr.cname7 I, the3count 8 9 TH-$ .-/-CT company3id I$T" the3id ,4"5 company (H-4- name 8 :cllr.cname7 return3!alue 0the3id27 -/.I, the3count : 9 TH-$ show3list7 -/.I, the3count 8 ; TH-$ display 0)$o matches found.)27 -$D I,7 -$D7 $otice a second .-/-CT has to e e%ecuted to retrie!e the single ID. In this case, we don<t ha!e to worry a out $"3D=T=3,"#$D, since C"#$T returns ; if no rows found. = etter solution is to use two fetches instead: D-C/=4C#4."4 comp3cur I. ...7 comp3rec comp3cur>4"(T?@-7 &-GI$ "@-$ comp3cur7 ,-TCH comp3cur I$T" comp3rec7 I, comp3cur>$"T,"#$D TH-$ display 0)$o match found.)27
The cursor ."4 loop is one of the est e%amples of integration etween procedurality of @/F.A/ and setGatGaGtime processing of .etch =pproach = solute minimum of C@# and memory employed to meet requirement. This query will not e!er return a !alue greater than one.A/ statement.
CURSOR FOR LOOPS
The cursor .7 C/". #se the most straightforward approach.A/. if no matches are found.A/. &e sure to read your requirements carefully and decide on the most sensi le approach."4 loop e%ecutes the ody of loop for e!ery record identified y the cursor which greatly reduces code !olume and the chance for error.A/ layer still performs two fetches.4"5 emp (H-4.company3nm :8 comp3rec. and it will return . = good fit? There are se!eral draw ac+s to this approach: The .-TCH comp3cur I$T" comp3rec7 I. comp3cur>. ?ou would ha!e to maintain the (H-4.empno 8 emp3in =$D 4"($#5 D E7 In the a o!e implicit cursor.company3id7 :employee. (hat a out an B-fficientC C"#$T012? .."#$D TH-$ show3list7 -/.-/.:employee.-/-CT C"#$T012 I$T" my3count . you *ust want to a!oid writing the e%ception handlers for a standard nonGC"#$T query. ?ou don<t really want to do a C"#$T. ?ou are Btric+ingC @/F.
.7 -$D I. Cle!er code is less reada le and maintaina le.clause in oth as there were data ase changes.comp3cur7 -$D7 =d!antages of Dual . =!oids duplication of .company3id :8 comp3rec.. (hat seems at first glance to e the most sensi le solution may turn out to ha!e ma*or draw ac+s.company3nm7 -$D I. 4"($#5 is used to ma+e sure that only one row is retrie!ed.
-TCH emp3cur I$T" emp3rec7 -HIT (H-$ emp3cur>$"T..27 -$D /""@7 -$D7 (ith the cursor . "nly use the cursor ....
. 7 emp3rec emp3cur>4"(T?@-7 &-GI$ "@-$ emp3cur7 /""@ ."#$D7 gi!e3raise 0emp3rec.27 -$D /""@7 C/". .. .or e%ample: #sing a simple loop to process all records in cursor: D-C/=4C#4.emp3cur7 -$D7 #sing a cursor . ?ou should not e%it prematurely from the loop using conditional logic.empno. 9."4 loop. 7 &-GI$ .."4 loop. "pen the cursor. you do not ha!e to e%plicitly: Declare a record into which the cursor<s row is fetched.."4 emp3cur I."4 emp3cur I. ..etch from the cursor into the record.A/ which means you write less code and you ha!e fewer opportunities for ugs."4 loop when you want to perform an action for e!ery record fetched. 9. =ll these steps are performed automatically y @/F."4 emp3rec I$ emp3cur /""@ gi!e3raise 0emp3rec.27 -$D /""@7 There are su stantial code sa!ings with using a cursor ..."4 loop to do the same: D-C/=4C#4..... Close the cursor.empno. . 9. Detect last record fetched in cursor."4 emp3rec I$ emp3cur /""@ gi!e3raise 0emp3rec..empno.
-/-CT column list. status3in I$ company.. =utomatically ta+es on structure of . &ecause the cursor is not defined within a single program.CURSOR RECORDS Declare a record for the cursor with >4"(T?@. 7 company3rec company3cur>4"(T?@-7 &-GI$ "@-$ company3cur7 . . 4eference with dot notation.7 CURSOR PARAMETERS #se Cursor @arameters for 4eusa ility C#4..company3id>T?@-.. D-C/=4C#4. such as the particular fields needed to perform computations. ?ou supply I$ parameters. @arameters are most important when a cursor is in a pac+age. Cursor parameters can include default parameter !alues. Cursor parameters increase fle%i ilityFreusa ility of the cursor.-TCH company3cur I$T" company3rec7 I. you cannot ind it with local or host !aria les. -$D I. This frees the cursor from any particular conte%t or program unit.attri ute.:8 )")2 Cursor parameters use the same structure as the parameter list for procedures and functions. Don<t ha!e to declare indi!idual !aria les and you only reference the ones you use.short3nm 8 )=C5-) TH-$ ."4 company3cur 0id3in I$ company.
. ?ou can use the same cursor in many programs. $either "#T nor I$ "#T modes are allowed."4 company3cur I. company3rec.cstatus>T?@. #se Cursor 4ecords to minimiIe typing and defer addressing details..
C#4.A/ in your @/F.A/ code.emp3access I.. @=C6=G.=!oid HardGCoding Cursor @arameters Compare the following two cursors7 one uses an em edded ind !aria le. . It may not e practical. It also allows you to maintain one area in which data ase structure changes impact @/F. The first cursor requires the presence of the new3company3id local !aria le to compile and e%ecute.. ut it is pro a ly worth attempting to perform an ad!ance analysis of all of the programmers< needs to produce a full set of queries preGdefined in the pac+age.company3id 8 id3in7 &-GI$ "@-$ company3cur 0new3company3id27
CURSOR PACKA ES Consolidate Cursors and ."4 company3cur 0id3in I$ company.4"5 company (H-4. you control the use of ."4 company3cur I. D-C/=4. the other a parameter. This remo!es the urden of +nowledge a out comple% *oins.C#4... .7 C#4. The second cursor can e used where!er a company id is a!aila le..4"5 company (H-4.A/ programs. 7 C#4.."4 in3sal3order ."4 emp3all .A/ in @ac+ages &y placing cursors inside pac+ages.-/-CT comp3nm . C#4.company3id 8 new3company3id7 &-GI$ "@-$ company3cur7 D-C/=4.."4 in3dept3order .-/-CT comp3nm . 7 -$D emp3access7
. etc. from indi!idual de!elopers.company3id>T?@-2 I.
"4 yauthor3cur 0 K author3in I$ oo+s. the synta% is the same as if you were declaring it in a local @/F.attri ute = record defined from a programmerGdefined record If you declare a cursor in a pac+age ody. The 4-T#4$ clause may e made up of either of the following datatype structures: = record defined from a data ase ta le using the >4"(T?@. Declare only the header of the cursor and do not include the query itself. you ha!e two options: Declare the entire cursor. ut the . hidden the implementation of the cursor.oo+3info E I. 4-C"4D 0
. This is e%actly the same as if you were declaring a cursor in a local @/F.4"5 oo+s P (H-4. J C#4.author3summary3rt I. "f course. If you declare only the header. then you must add a 4-T#4$ clause to a cursor definition that indicates the data elements returned y a fetch from the cursor. in effect. ?ou ha!e.-/-CT statement appears only in the ody. including the query. not in the specification.author 8 author3in7 9.A/ loc+.-/-CT 1 O .A/ loc+. In this case.title>T?@9J 2 4-T#4$ oo+s>4"(T?@-7 9K 9L T?@. in the specification. the query is defined in the pac+age ody only . these data elements are actually determined y the ."4 ytitle3cur 0 9E title3filter3in I$ oo+s."4 4-@/=C. N .author>T?@L 2 M I.@=C6=G. Here is a simple pac+age specification that shows oth of these approaches: 9 C4-=T.MANA !N
CURSOR PACKA ES
Declaring @ac+aged Cursors If you are declaring an e%plicit cursor in a pac+age specification. 99 C#4.-/-CT statement for that cursor.
display 0one oo+27 -$D /""@7 C/". In this case. "n lines 99Q9J.oo+3info.o if you want to get information a out all the oo+s ha!ing to do with @/F. ytitle3cur 0)>@/F. fetch from.author>T?@EE 2 4-T#4$ author3summary3rt7 EJ -$D oo+3info7 "n lines JQP you can see a !ery typical e%plicit cursor definition. 9N total3page3count @/. you do not need to learn any new synta% to open. C#4."4 summary3cur 0 E9 author3in I$ oo+s. "n lines 9LQ9O. I am telling whoe!er is loo+ing at the specification that if they open and fetch from this cursor they will recei!e a single row from the oo+s ta le for the specified Btitle filter.A/>)27 /""@ -HIT (H-$ oo+3info."#$D7 .-TCH oo+3info.irst of all. you can >4"(T?@. and on lines E.QEE. and close pac+aged cursors7 you *ust ha!e to remem er to prepend the pac+age name to the name of the cursor. ytitle3cur>$"T. fully defined in the pac+age specification.author>T?@-.C the implication eing that wild cards are accepted in the description of the title.3I$T-G-4. I define a new record type to hold summary information for a particular author. I define a cursor without a query. ytitle3cur7 -$D7 =s you can see.3I$T-G-427 9P E. 9O total3 oo+3count @/.9M author oo+s. I declare a cursor that returns summary information 0*ust three !alues2 for a gi!en author. . ytitle3cur>4"(T?@-7 &-GI$ "@-$ oo+3info.
.a pac+aged cursor and chec+ its attri utes *ust as you would with a locally defined e%plicit cursor. a loc+ can e written li+e this: D-C/=4one oo+ oo+3info.A/. (or+ing with @ac+aged Cursors $ow let<s see how you can ta+e ad!antage of pac+aged cursors. ytitle3cur I$T" one oo+7 oo+3info. ..
&ecause the cursor is declared in a pac+age specification. and then pays the price in une%pected and unhandled e%ceptions. Gi!en the persistence of pac+aged cursors.. its scope is not ound to any gi!en @/F. you should always +eep the following rules in mind: $e!er assume that a pac+aged cursor is closed 0and ready to e opened2.A/: cursor already open This happened ecause in the Bonly openC loc+. =lways e sure to e%plicitly close your pac+aged cursor when you are done with it. =n error will then occur: "4=G. you might well e%ecute an application that ma+es certain assumptions. If you neglect these rules. the cursor was not closed. in the same session.A/ cursorsR ut they are a solutely crucial for pac+aged cursors.uppose that this code is run: &-GI$ GG "nly open. -!en though the loc+ terminated. "@-$ oo+3info.There are some hidden issues lur+ing in this code. howe!er. the pac+aged cursor did not close.A/ loc+. the anonymous loc+ with the /""@ shown a o!e is also run. These three rules also apply to wor+ing with other +inds of cursorsRsuch as locally defined e%plicit cursors and D&5.3. $e!er assume that a pac+aged cursor is opened 0and ready to e closed2. ytitle3cur 0)>@-=C->)27 -$D7 and then.
..ML99: @/F. .