You are on page 1of 8

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

-/.,-TCH comp3cur I$T" comp3rec7 I, comp3cur>,"#$D TH-$ show3list7 -/.:employee.company3id :8 comp3rec.company3id7 :employee.company3nm :8 comp3rec.company3nm7 -$D I,7 -$D I,7 C/".- comp3cur7 -$D7 =d!antages of Dual ,etch =pproach = solute minimum of C@# and memory employed to meet requirement. =!oids duplication of .A/ statement. ?ou would ha!e to maintain the (H-4- clause in oth as there were data ase changes. &e sure to read your requirements carefully and decide on the most sensi le approach. (hat seems at first glance to e the most sensi le solution may turn out to ha!e ma*or draw ac+s. (hat a out an B-fficientC C"#$T012? .-/-CT C"#$T012 I$T" my3count ,4"5 emp (H-4- empno 8 emp3in =$D 4"($#5 D E7 In the a o!e implicit cursor, 4"($#5 is used to ma+e sure that only one row is retrie!ed. This query will not e!er return a !alue greater than one, and it will return ; if no matches are found. = good fit? There are se!eral draw ac+s to this approach: The .A/ layer still performs two fetches. ?ou are Btric+ingC @/F.A/. ?ou don<t really want to do a C"#$T, you *ust want to a!oid writing the e%ception handlers for a standard nonGC"#$T query. Cle!er code is less reada le and maintaina le. #se the most straightforward approach.

CURSOR FOR LOOPS


The cursor ,"4 loop is one of the est e%amples of integration etween procedurality of @/F.A/ and setGatGaGtime processing of .A/. The cursor ,"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.

,"4 emp3rec I$ emp3cur /""@ gi!e3raise 0emp3rec.empno, 9;;;;27 -$D /""@7 There are su stantial code sa!ings with using a cursor ,"4 loop. ,or e%ample: #sing a simple loop to process all records in cursor: D-C/=4C#4."4 emp3cur I. ... 7 emp3rec emp3cur>4"(T?@-7 &-GI$ "@-$ emp3cur7 /""@ ,-TCH emp3cur I$T" emp3rec7 -HIT (H-$ emp3cur>$"T,"#$D7 gi!e3raise 0emp3rec.empno, 9;;;;27 -$D /""@7 C/".- emp3cur7 -$D7 #sing a cursor ,"4 loop to do the same: D-C/=4C#4."4 emp3cur I. ... 7 &-GI$ ,"4 emp3rec I$ emp3cur /""@ gi!e3raise 0emp3rec.empno, 9;;;;27 -$D /""@7 -$D7 (ith the cursor ,"4 loop, you do not ha!e to e%plicitly: Declare a record into which the cursor<s row is fetched. "pen the cursor. ,etch from the cursor into the record. Detect last record fetched in cursor. Close the cursor. =ll these steps are performed automatically y @/F.A/ which means you write less code and you ha!e fewer opportunities for ugs. "nly use the cursor ,"4 loop when you want to perform an action for e!ery record fetched. ?ou should not e%it prematurely from the loop using conditional logic.

CURSOR RECORDS Declare a record for the cursor with >4"(T?@- attri ute. =utomatically ta+es on structure of .-/-CT column list. Don<t ha!e to declare indi!idual !aria les and you only reference the ones you use. 4eference with dot notation. #se Cursor 4ecords to minimiIe typing and defer addressing details, such as the particular fields needed to perform computations. D-C/=4C#4."4 company3cur I. ... 7 company3rec company3cur>4"(T?@-7 &-GI$ "@-$ company3cur7 ,-TCH company3cur I$T" company3rec7 I, company3rec.short3nm 8 )=C5-) TH-$ ... -$D I,7 CURSOR PARAMETERS #se Cursor @arameters for 4eusa ility C#4."4 company3cur 0id3in I$ company.company3id>T?@-, status3in I$ company.cstatus>T?@- :8 )")2 Cursor parameters use the same structure as the parameter list for procedures and functions. ?ou supply I$ parameters. $either "#T nor I$ "#T modes are allowed. Cursor parameters can include default parameter !alues. Cursor parameters increase fle%i ilityFreusa ility of the cursor. ?ou can use the same cursor in many programs. @arameters are most important when a cursor is in a pac+age. &ecause the cursor is not defined within a single program, you cannot ind it with local or host !aria les. This frees the cursor from any particular conte%t or program unit.

=!oid HardGCoding Cursor @arameters Compare the following two cursors7 one uses an em edded ind !aria le, the other a parameter. The first cursor requires the presence of the new3company3id local !aria le to compile and e%ecute. The second cursor can e used where!er a company id is a!aila le. D-C/=4- C#4."4 company3cur I. .-/-CT comp3nm ,4"5 company (H-4- company3id 8 new3company3id7 &-GI$ "@-$ company3cur7 D-C/=4- C#4."4 company3cur 0id3in I$ company.company3id>T?@-2 I. .-/-CT comp3nm ,4"5 company (H-4- company3id 8 id3in7 &-GI$ "@-$ company3cur 0new3company3id27

CURSOR PACKA ES Consolidate Cursors and .A/ in @ac+ages &y placing cursors inside pac+ages, you control the use of .A/ in your @/F.A/ code. This remo!es the urden of +nowledge a out comple% *oins, etc., from indi!idual de!elopers. It also allows you to maintain one area in which data ase structure changes impact @/F.A/ programs. It may not e practical, 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. @=C6=G- emp3access I. C#4."4 emp3all ...7 C#4."4 in3dept3order ... 7 C#4."4 in3sal3order ... 7 -$D emp3access7

MANA !N

CURSOR PACKA ES

Declaring @ac+aged Cursors If you are declaring an e%plicit cursor in a pac+age specification, you ha!e two options: Declare the entire cursor, including the query, in the specification. This is e%actly the same as if you were declaring a cursor in a local @/F.A/ loc+. Declare only the header of the cursor and do not include the query itself. In this case, the query is defined in the pac+age ody only . ?ou ha!e, in effect, hidden the implementation of the cursor. 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. "f course, these data elements are actually determined y the .-/-CT statement for that cursor, ut the .-/-CT statement appears only in the ody, not in the specification. 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?@- attri ute = record defined from a programmerGdefined record If you declare a cursor in a pac+age ody, the synta% is the same as if you were declaring it in a local @/F.A/ loc+. Here is a simple pac+age specification that shows oth of these approaches: 9 C4-=T- "4 4-@/=C- @=C6=G- oo+3info E I. J C#4."4 yauthor3cur 0 K author3in I$ oo+s.author>T?@L 2 M I. N .-/-CT 1 O ,4"5 oo+s P (H-4- author 8 author3in7 9; 99 C#4."4 ytitle3cur 0 9E title3filter3in I$ oo+s.title>T?@9J 2 4-T#4$ oo+s>4"(T?@-7 9K 9L T?@- author3summary3rt I. 4-C"4D 0

9M author oo+s.author>T?@-, 9N total3page3count @/.3I$T-G-4, 9O total3 oo+3count @/.3I$T-G-427 9P E; C#4."4 summary3cur 0 E9 author3in I$ oo+s.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, fully defined in the pac+age specification. "n lines 99Q9J, I define a cursor without a query. In this case, 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,C the implication eing that wild cards are accepted in the description of the title. "n lines 9LQ9O, I define a new record type to hold summary information for a particular author, and on lines E;QEE, I declare a cursor that returns summary information 0*ust three !alues2 for a gi!en author. (or+ing with @ac+aged Cursors $ow let<s see how you can ta+e ad!antage of pac+aged cursors. ,irst of all, you do not need to learn any new synta% to open, fetch from, and close pac+aged cursors7 you *ust ha!e to remem er to prepend the pac+age name to the name of the cursor. .o if you want to get information a out all the oo+s ha!ing to do with @/F.A/, a loc+ can e written li+e this: D-C/=4one oo+ oo+3info. ytitle3cur>4"(T?@-7 &-GI$ "@-$ oo+3info. ytitle3cur 0)>@/F.A/>)27 /""@ -HIT (H-$ oo+3info. ytitle3cur>$"T,"#$D7 ,-TCH oo+3info. ytitle3cur I$T" one oo+7 oo+3info.display 0one oo+27 -$D /""@7 C/".- oo+3info. ytitle3cur7 -$D7 =s you can see, you can >4"(T?@- a pac+aged cursor and chec+ its attri utes *ust as you would with a locally defined e%plicit cursor.

There are some hidden issues lur+ing in this code, howe!er. &ecause the cursor is declared in a pac+age specification, its scope is not ound to any gi!en @/F.A/ loc+. .uppose that this code is run: &-GI$ GG "nly open... "@-$ oo+3info. ytitle3cur 0)>@-=C->)27 -$D7 and then, in the same session, the anonymous loc+ with the /""@ shown a o!e is also run. =n error will then occur: "4=G;ML99: @/F.A/: cursor already open This happened ecause in the Bonly openC loc+, the cursor was not closed. -!en though the loc+ terminated, the pac+aged cursor did not close. Gi!en the persistence of pac+aged cursors, you should always +eep the following rules in mind: $e!er assume that a pac+aged cursor is closed 0and ready to e opened2. $e!er assume that a pac+aged cursor is opened 0and ready to e closed2. =lways e sure to e%plicitly close your pac+aged cursor when you are done with it. These three rules also apply to wor+ing with other +inds of cursorsRsuch as locally defined e%plicit cursors and D&5.3.A/ cursorsR ut they are a solutely crucial for pac+aged cursors. If you neglect these rules, you might well e%ecute an application that ma+es certain assumptions, and then pays the price in une%pected and unhandled e%ceptions.

You might also like