0% found this document useful (0 votes)
37 views

Explicit Cursor Oracle

There are two types of cursors in PL/SQL: implicit and explicit. Implicit cursors are automatically created by PL/SQL for DML and SELECT INTO statements, while explicit cursors must be declared and opened by the developer for queries returning multiple rows. Explicit cursors give the developer more programmatic control over cursor operations like opening, fetching, and closing compared to implicit cursors. The document discusses the differences between implicit and explicit cursors and how various cursor operations work in PL/SQL.

Uploaded by

EmiliaVardarova
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
37 views

Explicit Cursor Oracle

There are two types of cursors in PL/SQL: implicit and explicit. Implicit cursors are automatically created by PL/SQL for DML and SELECT INTO statements, while explicit cursors must be declared and opened by the developer for queries returning multiple rows. Explicit cursors give the developer more programmatic control over cursor operations like opening, fetching, and closing compared to implicit cursors. The document discusses the differences between implicit and explicit cursors and how various cursor operations work in PL/SQL.

Uploaded by

EmiliaVardarova
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 57

6.

2 Cursors in PL/SQL
When you execute a SQL statement from PL/SQL, the Oracle RDBMS assigns a pri ate !or" area for that statement# $his !or" area contains information a%out the SQL statement an& the set of &ata returne& or affecte& %y that statement# $he PL/SQL cursor is a mechanism %y !hich you can name that !or" area an& manipulate the information !ithin it# 'n its simplest form, you can thin" of a cursor as a pointer into a ta%le in the &ata%ase# (or example, the follo!ing cursor &eclaration associates the entire employee ta%le !ith the cursor name& employee)cur* +,RSOR employee)cur 'S S-L-+$ . (ROM employee/ Once ' ha e &eclare& the cursor, ' can open it* OP-0 employee)cur/ 1n& then ' can fetch ro!s from it* (-$+2 employee)cur '0$O employee)rec/ an&, finally, ' can close the cursor* +LOS- employee)cur/ 'n this case, each recor& fetche& from this cursor represents an entire recor& in the employee ta%le# 3ou can, ho!e er, associate any ali& S-L-+$ statement !ith a cursor# 'n the next example ' ha e a 4oin of three ta%les in my cursor &eclaration* D-+L1R+,RSOR 4o"e)fee&%ac")cur 'S S-L-+$ 5#name, R#laugh) olume, +#name (ROM 4o"e 5, response R, come&ian + W2-R- 5#4o"e)i& 6 R#4o"e)i& 10D 5#4o"er)i& 6 +#4o"er)i&/ B-7'0 ### -0D/ 2ere, the cursor &oes not act as a pointer into any actual ta%le in the &ata%ase# 'nstea&, the cursor is a pointer into the irtual ta%le represente& %y the S-L-+$ statement 8S-L-+$ is calle& a irtual ta%le %ecause the &ata it pro&uces has the same structure as a ta%le 99 ro!s an& columns 99 %ut it exists only for the &uration of the execution of the SQL statement:# 'f the triple94oin returns ;< ro!s, each ro! containing the three columns in the prece&ing example, then the cursor functions as a pointer into those ;< ro!s#
=

>#;#= $ypes of +ursors 3ou ha e lots of options in PL/SQL for executing SQL, an& all of them occur as some type of cursor# 7enerally, there are t!o types of SQL that you can execute in PL/SQL* static an& &ynamic# SQL is static if the content of the SQL statement is &etermine& at compile time# 1 SQL statement is &ynamic if it is constructe& at runtime an& then execute&# Dynamic SQL is ma&e possi%le in PL/SQL only through the use of the DBMS)SQL %uilt9in pac"age 8see 1ppen&ix +, Built9'n Pac"ages:# 1ll other forms of SQL execute& insi&e a PL/SQL program represent static SQL/ these forms of cursors are the focus of the remain&er of this chapter# - en !ithin the category of static SQL, !e ha e further &ifferentiation# With the a& ent of PL/SQL Release ;#?, you can choose %et!een t!o &istinct types of cursor o%4ects* Static cursor o%4ects $hese are the really static cursors of PL/SQL# $he SQL is &etermine& at compile time, an& the cursor al!ays refers to one SQL statement, !hich is "no!n at compile time# $he examples sho!n earlier in this chapter are static cursors# ,nless other!ise note&, any reference to @static cursor@ refers to this su%9 category of static 8as oppose& to &ynamic: cursors# +ursor aria%les 3ou can &eclare a aria%le !hich references a cursor o%4ect in the &ata%ase# 3our aria%le may refer to &ifferent SQL statements at &ifferent times 8%ut that SQL is &efine& at compile time, not run time:# $he cursor aria%le is one of the ne!est enhancements to PL/SQL an& !ill %e unfamiliar to most programmers# +ursor aria%les act as references to cursor o%4ects# 1s a true aria%le, a cursor aria%le can change its alue as your program executes# $he aria%le can refer to &ifferent cursor o%4ects 8Aueries: at &ifferent times# 3ou can also pass a cursor aria%le as a parameter to a proce&ure or function# +ursor aria%les are &iscusse& later in this chapter# Static PL/SQL cursors ha e %een a aila%le since PL/SQL Bersion =# $he static ersion of cursors @har&co&es@ a lin" %et!een the cursor name an& a S-L-+$ statement# $he static cursor itself comes in t!o fla ors* implicit an& explicit# PL/SQL &eclares an& manages an implicit cursor e ery time you execute a SQL DML statement, such as an '0S-R$ or a S-L-+$ that returns a single ro!# 3ou, the programmer, &efine your o!n explicit cursors in your co&e# 3ou must use an explicit cursor !hen you nee& to retrie e more than one ro! of &ata at a time through a S-L-+$ statement# 3ou can then use the cursor to fetch these ro!s one at a time# $he set of ro!s returne& %y the Auery associate& !ith an explicit cursor is calle& the acti e set or result set of the cursor# $he ro! to !hich the explicit cursor points is calle& the current ro! of the result set#
;

$he %ul" of this chapter is &e ote& to the management of static, explicit cursors# 1ll information a%out cursor aria%les is localiCe& in Section >#=;, @+ursor Baria%les@# 1ny references to PL/SQL cursors an& cursor characteristics outsi&e of that section !ill pertain to static cursors# >#;#; +ursor Operations Regar&less of the type of cursor, PL/SQL performs the same operations to execute a SQL statement from !ithin your program* P1RS$he first step in processing an SQL statement is to parse it to ma"e sure it is ali& an& to &etermine the execution plan 8using either the rule9%ase& or cost9%ase& optimiCer:# B'0D When you %in&, you associate alues from your program 8host aria%les: !ith placehol&ers insi&e your SQL statement# (or static SQL, the SQL engine itself performs these %in&s# When you use &ynamic SQL, you explicitly reAuest a %in&ing of aria%le alues# OP-0 When you open a cursor, the %in& aria%les are use& to &etermine the result set for the SQL statement# $he pointer to the acti e or current ro! is set to the first ro!# Sometimes you !ill not explicitly open a cursor/ instea& the PL/SQL engine !ill perform this operation for you 8as !ith implicit cursors:# -D-+,$'n the execute phase, the statement is run !ithin the SQL engine# (-$+2 'f you are performing a Auery, the (-$+2 comman& retrie es the next ro! from the cursorEs result set# -ach time you fetch, PL/SQL mo es the pointer for!ar& in the result set# When !or"ing !ith explicit cursors, remem%er that if there are no more ro!s to retrie e, then (-$+2 &oes nothing 8it &oes not raise an error:# +LOS$he +LOS- statement closes the cursor an& releases all memory use& %y the cursor# Once close&, the cursor no longer has a result set# Sometimes you !ill not explicitly close a cursor/ instea& the PL/SQL engine !ill perform this operation for you 8as !ith implicit cursors:#
(igure >#= sho!s ho! some of these &ifferent operations are use& to fetch information

from the &ata%ase into your PL/SQL program#


?

(igure >#=* ,sing cursor operations to fetch &ata%ase information into your program

6.3 Implicit and Explicit Cursors

LetEs ta"e a closer loo" at implicit an& explicit cursors an& the !ays you can put them in your programs# >#?#= 'mplicit +ursors PL/SQL issues an implicit cursor !hene er you execute a SQL statement &irectly in your co&e, as long as that co&e &oes not employ an explicit cursor# 't is calle& an @implicit@ cursor %ecause you, the &e eloper, &o not explicitly &eclare a cursor for the SQL statement# 'f you use an implicit cursor, Oracle performs the open, fetches, an& close for you automatically/ these actions are outsi&e of your programmatic control# 3ou can, ho!e er, o%tain information a%out the most recently execute& SQL statement %y examining the alues in the implicit SQL cursor attri%utes, as explaine& later in this chapter# PL/SQL employs an implicit cursor for each ,PD1$-, D-L-$-, or '0S-R$ statement you execute in a program# 3ou cannot, in other !or&s, execute these statements !ithin an explicit cursor, e en if you !ant to# 3ou ha e a choice %et!een using an implicit or explicit cursor only !hen you execute a single9ro! S-L-+$ statement 8a S-L-+$ that returns only one ro!:# 'n the follo!ing ,PD1$- statement, !hich gi es e eryone in the company a =<F raise, PL/SQL creates an implicit cursor to i&entify the set of ro!s in the ta%le !hich !oul& %e affecte& %y the up&ate* ,PD1$- employee S-$ salary 6 salary . =#=/ $he follo!ing single9ro! Auery calculates an& returns the total salary for a &epartment# Once again, PL/SQL creates an implicit cursor for this statement* S-L-+$ S,M 8salary: '0$O &epartment)total (ROM employee W2-R- &epartment)num%er 6 =</ 'f you ha e a S-L-+$ statement that returns more than one ro!, you must use an explicit cursor for that Auery an& then process the ro!s returne& one at a time# PL/SQL &oes not yet support any "in& of array interface %et!een a &ata%ase ta%le an& a composite PL/SQL &atatype such as a PL/SQL ta%le# >#?#; Dra!%ac"s of 'mplicit +ursors - en if your Auery returns only a single ro!, you might still &eci&e to use an explicit
G

cursor# $he implicit cursor has the follo!ing &ra!%ac"s* 't is less efficient than an explicit cursor 8in PL/SQL Release ;#; an& earlier: 't is more ulnera%le to &ata errors 't gi es you less programmatic control $he follo!ing sections explore each of these limitations to the implicit cursor# >#?#;#= 'nefficiencies of implicit cursors 1n explicit cursor is, at least theoretically, more efficient than an implicit cursor 8in PL/SQL Release ;#; an& earlier:# 1n implicit cursor executes as a SQL statement an& OracleEs SQL is 10S'9stan&ar&# 10S' &ictates that a single9ro! Auery must not only fetch the first recor&, %ut must also perform a secon& fetch to &etermine if too many ro!s !ill %e returne& %y that Auery 8such a situation !ill R1'S- the $OO)M103)ROWS PL/SQL exception:# $hus, an implicit Auery al!ays performs a minimum of t!o fetches, !hile an explicit cursor only nee&s to perform a single fetch# $his a&&itional fetch is usually not noticea%le, an& you shoul&nEt %e neurotic a%out using an implicit cursor for a single9ro! Auery 8it ta"es less co&ing, so the temptation is al!ays there:# Loo" out for in&iscriminate use of the implicit cursor in the parts of your application !here that cursor !ill %e execute& repeate&ly# 1 goo& example is the Post9Query trigger in the Oracle (orms# Post9Query fires once for each recor& retrie e& %y the Auery 8create& from the %ase ta%le %loc" an& the criteria entere& %y the user:# 'f a Auery retrie es ten ro!s, then an a&&itional ten fetches are nee&e& !ith an implicit Auery# 'f you ha e ;H users on your system all performing a similar Auery, your ser er must process ;H< a&&itional 8unnecessary: fetches against the &ata%ase# So, !hile it might %e easier to !rite an implicit Auery, there are some places in your co&e !here you !ill !ant to ma"e that extra effort an& go !ith the explicit cursor# 0O$-* 'n PL/SQL Release ;#? an& a%o e, the implicit cursor has %een optimiCe& so that it may, in isolation, run faster than the correspon&ing explicit cursor# 7enerally, the &ifferences %et!een these t!o approaches from a performance stan&point are negligi%le# On the other han&, if you use an explicit cursor, you are more li"ely 8or at least a%le: to reuse that cursor, !hich increases the chance that it !ill %e pre9parse& in share& memory !hen nee&e& 99 there%y impro ing the performance of your application as a !hole# >#?#;#; Bulnera%ility to &ata errors 'f an implicit S-L-+$ statement returns more than one ro!, it raises the $OO)M103)ROWS exception# When this happens, execution in the current %loc" terminates an& control is passe& to the exception section# ,nless you &eli%erately plan to han&le this scenario, use of the implicit cursor is a &eclaration of faith# 3ou are saying, @' trust that Auery to al!ays return a single ro!I@ 't may !ell %e that to&ay, !ith the current &ata, the Auery !ill only return a single ro!#
H

'f the nature of the &ata e er changes, ho!e er, you may fin& that the S-L-+$ statement !hich formerly i&entifie& a single ro! no! returns se eral# 3our program !ill raise an exception# Perhaps this is !hat you !ill !ant# On the other han&, perhaps the presence of a&&itional recor&s is inconseAuential an& shoul& %e ignore&# With the implicit Auery, you cannot easily han&le these &ifferent possi%ilities# With an explicit Auery, your program !ill %e protecte& against changes in &ata an& !ill continue to fetch ro!s !ithout raising exceptions# >#?#;#? Diminishe& programmatic control $he implicit cursor ersion of a S-L-+$ statement is a %lac" %ox# 3ou pass the SQL statement to the SQL layer in the &ata%ase an& it returns 8you hope: a single ro!# 3ou canEt get insi&e the separate operations of the cursor, such as the open an& close stages# 3ou canEt examine the attri%utes of the cursor 99 to see !hether a ro! !as foun&, for example, or if the cursor has alrea&y %een opene&# 3ou canEt easily apply tra&itional programming control constructs, such as an '( statement, to your &ata access# Sometimes you &onEt nee& this le el of control# Sometimes you 4ust thin" you &onEt nee& this le el of control# ' ha e foun& that if ' am going to %uil& programs in PL/SQL, ' !ant as much control as ' can possi%ly get# 1l!ays ,se -xplicit +ursorsI My rule of thum% is al!ays to use an explicit cursor for all S-L-+$ statements in my applications, e en if an implicit cursor might run a little %it faster an& e en if, %y co&ing an explicit cursor, ' ha e to !rite more co&e 8&eclaration, open, fetch, close:# By setting an& follo!ing this clear9cut rule, ' gi e myself one less thing to thin" a%out# ' &o not ha e to &etermine if a particular S-L-+$ statement !ill return only one ro! an& therefore %e a can&i&ate for an implicit cursor# ' &o not ha e to !on&er a%out the con&itions un&er !hich a single9ro! Auery might su&&enly return more than one ro!, thus reAuiring a $OO)M103)ROWS exception han&ler# ' am guarantee& to get astly impro e& programmatic control o er that &ata access an& more finely9tune& exception han&ling for the cursor# >#?#? -xplicit +ursors 1n explicit cursor is a S-L-+$ statement that is explicitly &efine& in the &eclaration section of your co&e an&, in the process, assigne& a name# $here is no such thing as an explicit cursor for ,PD1$-, D-L-$-, an& '0S-R$ statements# With explicit cursors, you ha e complete control o er ho! to access information in the &ata%ase# 3ou &eci&e !hen to OP-0 the cursor, !hen to (-$+2 recor&s from the cursor 8an& therefore from the ta%le or ta%les in the S-L-+$ statement of the cursor: ho! many recor&s to fetch, an& !hen to +LOS- the cursor# 'nformation a%out the current state of your cursor is a aila%le through examination of the cursor attri%utes# $his granularity of control ma"es the explicit cursor an in alua%le tool for your &e elopment effort#
>

LetEs loo" at an example# $he follo!ing anonymous %loc" loo"s up the employee type &escription for an employee type co&e* = D-+L1R; /. -xplicit &eclaration of a cursor ./ ? +,RSOR emptyp)cur 'S G S-L-+$ emptyp#type)&esc H (ROM employees emp, employee)type emptyp > W2-R- emp#type)co&e 6 emptyp#type)co&e/ J B-7'0 K /. +hec" to see if cursor is alrea&y open# 'f not, open it# ./ L '( 0O$ emptyp)curF'SOP-0 =< $2-0 == OP-0 emptyp)cur/ =; -0D '(/ =? =G /. (etch ro! from cursor &irectly into an Oracle (orms item ./ =H (-$+2 emptyp)cur '0$O *emp#type)&esc/ => =J /. +lose the cursor ./ =K +LOS- emptyp)cur/ =L -0D/ $his PL/SQL %loc" performs the follo!ing cursor actions*
1ctionLine8s:Declare the cursor?Open the cursor 8if not alrea&y open:L, ==(etch one or more ro!s from the cursor=H+lose the cursor=K$he next fe! sections examine each of these steps in

more &etail# (or the remain&er of this chapter, unless note& other!ise, the !or& @cursor@ refers to the explicit cursor#

6.4 Declaring Cursors

$o use an explicit cursor, you must first &eclare it in the &eclaration section of your PL/SQL %loc" or in a pac"age, as sho!n here* +,RSOR cursor)name M 8 M parameter M, parameter ###N : N M R-$,R0 return)specification N 'S S-L-+$)statement/ !here cursor)name is the name of the cursor, return)specification is an optional R-$,R0 clause for the cursor, an& S-L-+$)statement is any ali& SQL S-L-+$ statement# 3ou can also pass arguments into a cursor through the optional parameter list &escri%e& in Section >#=<, @+ursor Parameters@# Once you ha e &eclare& a cursor you can then OP-0 it an& (-$+2 from it# 2ere are some examples of explicit cursor &eclarations*
J

1 cursor !ithout parameters# $he result set of this cursor is the set of company 'D num%ers for each recor& in the ta%le* +,RSOR company)cur 'S S-L-+$ company)i& (ROM company/
1 cursor !ith parameters# $he result set of this cursor is the name of the

company !hich matches the company 'D passe& to the cursor ia the parameter* +,RSOR name)cur 8company)i&)in '0 0,MB-R: 'S S-L-+$ name (ROM company W2-R- company)i& 6 company)i&)in/ 1 cursor !ith a R-$,R0 clause# $he result set of this cursor is all columns 8same structure as the un&erlying ta%le: from all employee recor&s in &epartment =<* +,RSOR emp)cur R-$,R0 employeeF 'S S-L-+$ . (ROM employee W2-R- &epartment)i& 6 =</ >#G#= $he +ursor 0ame $he name of an explicit cursor is not a PL/SQL aria%le# 'nstea&, it is an un&eclare& i&entifier use& to point to or refer to the Auery# 3ou cannot assign alues to a cursor, nor can you use it in an expression# 1s a result, %oth of the executa%le statements after the B-7'0 line %elo! are in ali&* D-+L1R+,RSOR company)cur 'S S-L-+$ company)i& (ROM company/ B-7'0 company)cur *6 =H<<L/ /. 'n ali& syntax ./ '( company)cur 'S 0O$ 0,LL $2-0 ### / /. 'n ali& syntax ./ 'n compiling either statement, you !ill recei e the follo!ing error* PLS9<?;=* expression E+OMP103)+,RE is inappropriate as the left9han& si&e of an assignment statement# $he name of a cursor can %e up to ?< characters in length an& follo!s the rules for any other i&entifier in PL/SQL# >#G#; PL/SQL Baria%les in a +ursor Because a cursor must %e associate& !ith a S-L-+$ statement, e ery cursor must
K

reference at least one ta%le from the &ata%ase an& &etermine from that 8an& from the W2-R- clause: !hich ro!s !ill %e returne& in the acti e set# $his &oes not mean, ho!e er, that a cursorEs S-L-+$ may only return &ata%ase information# $he list of expressions that appears after the S-L-+$ "ey!or& an& %efore the (ROM "ey!or& is calle& the select list# 'n nati e SQL, this select list may contain %oth columns an& expressions 8SQL functions on those columns, constants, etc#:# 'n PL/SQL, the select list of a S-L-+$ may contain PL/SQL aria%les, expressions, an& e en functions 8PL/SQL Release ;#= an& a%o e:# 'n the follo!ing cursor, the S-L-+$ statement retrie es ro!s %ase& on the employee ta%le, %ut the information returne& in the select list contains a com%ination of ta%le columns, a PL/SQL aria%le, an& a %in& aria%le from the host en ironment 8such as an Oracle (orms item:* D-+L1R/. 1 local PL/SQL aria%le ./ pro4ecte&)%onus 0,MB-R *6 =<<</ /. OO +ursor a&&s P=<<< to the salary of each employee OO hire& more than three years ago# ./ +,RSOR employee)cur 'S S-L-+$ employee)i&, salary Q pro4ecte&)%onus ne!)salary, /. +olumn alias ./ *re ie!#e aluation /. Bin& aria%le ./ (ROM employee W2-R- hire&ate R 1DD)MO0$2S 8S3SD1$-, 9?>:/ B-7'0 ### -0D/ 3ou can reference local PL/SQL program &ata 8PL/SQL aria%les an& constants:, as !ell as host language %in& aria%les in the W2-R-, 7RO,P, an& 21B'07 clauses of the cursorEs S-L-+$ statement# >#G#? '&entifier Prece&ence in a +ursor Be careful a%out naming i&entifiers !hen you mix PL/SQL aria%les in !ith &ata%ase columns# 't is, for instance, common practice to gi e a aria%le the same name as the column !hose &ata it is suppose& to represent# $his ma"es perfect sense until you !ant to reference those local aria%les in a SQL statement along !ith the column# 'n the follo!ing example, ' !ant to fetch each employee !ho !as hire& more than three years ago an&, using a local aria%le, a&& P=<<< to their salary# $he employee ta%le has a column name& @salary#@ ,nfortunately, this proce&ure relies on a local
L

aria%le of the same name to achie e its en&s# 1lthough this co&e !ill compile !ithout error, it !ill not pro&uce the &esire& result* PRO+-D,R- impro e)QOL 'S /. Local aria%le !ith same name as column* ./ salary 0,MB-R *6 =<<</ +,RSOR &ou%le)sal)cur 'S S-L-+$ salary Q salary (ROM employee W2-R- hire&ate R 1DD)MO0$2S 8S3SD1$-, 9?>:/ B-7'0 'nstea& of a&&ing P=<<< to each personEs salary, this co&e !ill instea& &ou%le his or her salary# 'nsi&e the SQL statement, any unAualifie& reference to @salary@ is resol e& %y using the column name& @salary#@ ' coul& achie e the &esire& effect %y Aualifying the PL/SQL aria%le !ith the name of the proce&ure, as follo!s* +,RSOR &ou%le)sal)cur 'S S-L-+$ salary Q impro e!Q"L.salary (ROM employee W2-R- hire&ate R 1DD)MO0$2S 8S3SD1$-, 9?>:/ 'n this situation, you are informing the compiler that the secon& reference to salary is that aria%le @o!ne&@ %y the impro e)QOL proce&ure# 't !ill then a&& the current alue of that aria%le to the salary column alue# ' &o not, ho!e er, recommen& that you ma"e use of Aualifie& local aria%le names in this !ay# 'f your local aria%le names conflict !ith &ata%ase column or ta%le names, change the name of your aria%le# Best of all, a oi& this "in& of &uplication %y using a stan&ar& naming con ention for local aria%les !hich represent &ata%ase information# >#G#G $he +ursor R-$,R0 +lause One of the most significant ne! features in PL/SQL Bersion ; is the full support for pac"ages an& the resulting mo&ulariCation of co&e that is no! possi%le !ith that construct# Pac"ages intro&uce an enhancement to the !ay you can &eclare a cursor* the R-$,R0 clause# When you group programs together into a pac"age, you can ma"e only the specification, or hea&er information, of those programs a aila%le to &e elopers# 1lthough a &e eloper can tell from the specification !hat the mo&ule is calle& an& ho! to call it, he or she &oes not nee& to see any of the un&erlying co&e# 1s a result, you can create true %lac" %oxes %ehin& !hich you can hi&e complex implementational
=<

&etails# With Bersion ; of PL/SQL you can accomplish the same o%4ecti e !ith cursors %y using the cursor R-$,R0 clause# $he R-$,R0 clause allo!s you to create a specification for a cursor !hich is separate from its %o&y 8the S-L-+$ statement:# 3ou may then place cursors in pac"ages an& hi&e the implementation &etails from &e elopers# +onsi&er the follo!ing cursor &eclaration !ith R-$,R0 clause* +,RSOR caller)cur 8i&)in '0 0,MB-R: R-$,R0 callerF 'S S-L-+$ . (ROM caller W2-R- caller)i& 6 i&)in/ $he specification of the caller)cur cursor is* +,RSOR caller)cur 8i&)in '0 0,MB-R: R-$,R0 callerF !hile the %o&y of the caller)cur cursor is* S-L-+$ . (ROM caller W2-R- caller)i& 6 i&)in/ - erything up to %ut not inclu&ing the 'S "ey!or& is the specification, !hile e erything follo!ing the 'S "ey!or& is the %o&y# 3ou can inclu&e a R-$,R0 clause for any cursor you !rite in PL/SQL Bersion ;, %ut it is reAuire& only for cursors !hich are containe& in a pac"age specification# $he R-$,R0 clause may %e ma&e up of any of the follo!ing &atatype structures* 1 recor& &efine& from a &ata%ase ta%le, using the F attri%ute 1 recor& &efine& from a programmer9&efine& recor& 2ere is an example of a cursor &efine& in a pac"age# (irst, the pac"age specification pro i&es the name of the cursor an& the R-$,R0 &atatype 8an entire ro! from the company ta%le:* P1+S17- company 'S +,RSOR company)cur 8i&)in 0,MB-R: R-$,R0 companyF/ -0D company/ $hen the follo!ing pac"age %o&y repeats the cursor specification an& a&&s the SQL statement* P1+S17- BOD3 company 'S +,RSOR company)cur 8i&)in 0,MB-R: R-$,R0 companyF 'S S-L-+$ . (ROM company W2-R- company)i& 6 i&)in/ -0D company/
==

$he num%er of expressions in the cursorEs select list must match the num%er of columns in the recor& i&entifie& %y ta%le)nameF or PLSQL)recor&F# $he &atatypes of the elements must also %e compati%le# 'f the secon& element in the select list is type 0,MB-R, then the secon& column in the R-$,R0 recor& cannot %e type B1R+21R; or BOOL-10# Why place cursors in a pac"ageT (or the same reasons you !oul& place a proce&ure or a function in a pac"age* a pac"age is a collection of logically relate& o%4ects# By grouping the co&e into a pac"age you ma"e it easier for a &e eloper to i&entify an& use the co&e 8see+hapter =>, Pac"ages, for more &etails:# Pac"age& cursors are essentially %lac" %oxes# $his is a& antageous to &e elopers %ecause they ne er ha e to co&e or e en see the S-L-+$ statement# $hey only nee& to "no! !hat recor&s the cursor returns, in !hat or&er it returns them, an& !hich columns are in the column list# When cursor information is limite& on this "in& of @nee& to "no!@ %asis, it protects &e elopers an& the o erall application from change# Suppose that a year from no! the W2-R- clause of a Auery has to change# 'f a pac"age& cursor is not use&, then each program that has a har&co&e& or local cursor !ill ha e to %e mo&ifie& to meet the ne! specification# 'f, on the other han&, all &e elopers simply access the same cursor, then changes !ill only nee& to %e ma&e to that pac"age& &eclaration of the cursor# $he programs can then %e recompile& to automatically support this change#

6.# "pening Cursors $he first step in using a cursor is to &efine it in the &eclaration section# $he next step you must perform %efore you try to extract or fetch recor&s from a cursor is to open that cursor# $he syntax for the OP-0 statement is simplicity itself* OP-0 Rcursor)nameU M 8 argument M, argument ###N : N/ !here Rcursor)nameU is the name of the cursor you &eclare& an& the arguments are the alues to %e passe& if the cursor !as &eclare& !ith a parameter list# When you open a cursor, PL/SQL executes the Auery for that cursor# 't also i&entifies the acti e set of &ata 99 that is, the ro!s from all in ol e& ta%les that meet the criteria in the W2-R- clause an& 4oin con&itions# $he OP-0 &oes not itself actually retrie e any of these ro!s 99 that action is performe& %y the (-$+2 statement# Regar&less of !hen you perform the first fetch, ho!e er, the rea& consistency mo&el in the Oracle RDBMS guarantees that all fetches !ill reflect the &ata as it existe& !hen the cursor !as opene&# 'n other !or&s, from the moment you open your cursor until the moment that cursor is close&, all &ata fetche& through the cursor !ill ignore any inserts, up&ates, an& &eletes performe& after the cursor !as opene&# (urthermore, if the S-L-+$ statement in your cursor uses a (OR ,PD1$- clause, then, !hen the cursor is opene&, all the ro!s i&entifie& %y the Auery are loc"e&# 8$his
=;

topic is co ere& in Section >#==, @S-L-+$ (OR ,PD1$- in +ursors@ later in this chapter#: 3ou shoul& open a cursor only if it has %een close& or !as ne er opene&# 'f you try to open a cursor that is alrea&y open you !ill get the follo!ing error* OR19<>H==* PL/SQL* cursor alrea&y open 3ou can %e sure of a cursorEs status %y chec"ing the F'SOP-0 cursor attri%ute %efore you try to open the cursor* '( 0O$ company)curF'SOP-0 $2-0 OP-0 company)cur/ -0D '(/
Section >#L, @+ursor 1ttri%utes@ later in the chapter, explains the &ifferent cursor attri%utes

an& ho! to ma"e %est use of them in your programs#

6.6 $etc%ing &'()*'+,-./ 0rom Cursors 1 S-L-+$ statement creates a irtual ta%le in SQL* its return set is a series of ro!s &etermine& %y the W2-R- clause 8or lac" thereof: an& !ith columns &etermine& %y the column list of the S-L-+$# So a cursor represents that irtual ta%le !ithin your PL/SQL program# 'n almost e ery situation, the point of &eclaring an& opening a cursor is to return, or fetch, the ro!s of &ata from the cursor an& then manipulate the information retrie e&# PL/SQL pro i&es a (-$+2 statement for this action# $he general syntax for a (-$+2 is sho!n %elo!* (-$+2 Rcursor)nameU '0$O Rrecor&)or) aria%le)listU/ !here Rcursor)nameU is the name of the cursor from !hich the recor& is fetche& an& Rrecor&)or) aria%le)listU is the PL/SQL &ata structure into !hich the next ro! of the acti e set of recor&s is copie&# 3ou can fetch into a recor& structure 8&eclare& !ith the F attri%ute or $3P- &eclaration statement: or you can fetch into a list of one or more aria%les 8PL/SQL aria%les or application9specific %in& aria%les such as Oracle (orms items:# $he follo!ing examples illustrate the ariety of possi%le fetches* (etch into a PL/SQL recor&* (-$+2 company)cursor '0$O company)rec/ (etch into a aria%le* (-$+2 ne!)%alance)cursor '0$O ne!)%alance)&ollars/
=?

(etch into the ro! of a PL/SQL ta%le ro!, a aria%le, an& an Oracle (orms %in& aria%le* (-$+2 emp)name)cur '0$O emp)name 8=:, hire&ate, *&ept#min)salary/ >#>#= Matching +olumn List !ith '0$O +lause When you fetch into a list of aria%les, the num%er of aria%les must match the num%er of expressions in the S-L-+$ list of the cursor# When you fetch into a recor&, the num%er of columns in the recor& must match the num%er of expressions in the S-L-+$ list of the cursor# 'f you &o not match up the column list in the cursorEs Auery !ith the '0$O elements in the (-$+2, you !ill recei e the follo!ing compile error* PLS9<<?LG* !rong num%er of alues in the '0$O list of a (-$+2 statement LetEs loo" at ariations of (-$+2 to see !hat !ill an& !ill not !or"# Suppose ' ha e &eclare& the follo!ing cursor, recor&s, an& aria%les* +ursor that selects 4ust three columns from &r)seuss ta%le an& a recor& %ase& on that cursor* +,RSOR green)eggs)cur 8character)in '0 B1R+21R;: 'S S-L-+$ ham)Auantity, times)refuse&, excuse (ROM &r)seuss W2-R- %oo")title 6 E7R--0 -77S 10D 21ME 10D character)name 6 character)in/ green)eggs)rec green)eggs)curF/ +ursor for all columns in &r)seuss ta%le an& a recor& %ase& on the &r)seuss ta%le* +,RSOR &r)seuss)cur 'S S-L-+$ . (ROM &r)seuss/ &r)seuss)rec &r)seuss)curF/ Programmer9&efine& recor& type !hich contains all three of the green)eggs)cur columns, follo!e& %y &eclaration of recor&* $3P- green)eggs)rectype 'S R-+ORD 8hamV &r)seuss#ham)AuantityF$3P-/ sai&noV &r)seuss#times)refuse&F$3P-, reason &r)seuss#excuseF$3P-:/ full)green)eggs)rec green)eggs)rectype/
=G

Programmer9&efine& recor& type !hich contains only t!o of the three cursor columns, follo!ing %y &eclaration of recor&* $3P- partial)green)eggs)rectype 'S R-+ORD 8hamV &r)seuss#ham)AuantityF$3P-/ sai&noV &r)seuss#times)refuse&F$3P-:/ partial)rec partial)green)eggs)rectype/ 1 set of local PL/SQL aria%les* ham)amount 0,MB-R/ refuse&)count '0$-7-R/ lousy)excuse B1R+21R;8><:/ 0o! that e erything is &eclare&, ' then OP-0 the cursor for the @Sam ' 1m@ character 8passe& as an argument: as follo!s* OP-0 green)eggs)cur 8ESam ' 1mE:/ 1ll of the follo!ing fetches !ill compile !ithout error %ecause the num%er an& type of items in the '0$O clause match those of the cursor* (-$+2 green)eggs)cur '0$O green)eggs)rec/ (-$+2 green)eggs)cur '0$O ham)amount, refuse&)count, lousy)excuse/ (-$+2 green)eggs)cur '0$O full)green)eggs)rec/ (-$+2 &r)seuss)cur '0$O &r)seuss)rec/ 0otice that you can (-$+2 a cursorEs ro! into either a ta%le9%ase& or a programmer9 &efine& recor&# 3ou &o not ha e to !orry a%out recor& type compati%ility in this situation# PL/SQL 4ust nee&s to %e a%le to match up a cursor column/expression !ith a aria%le/fiel& in the '0$O clause# 1s you can see from the a%o e (-$+2es, you are not restricte& to using any single recor& or aria%le list for a particular (-$+2 99 e en in the same program# 3ou can &eclare multiple recor&s for the same cursor an& use all those &ifferent recor&s for &ifferent fetches# 3ou can also fetch once '0$O a recor& an& then later '0$O a aria%le list, as sho!n %elo!* OP-0 green)eggs)cur 8ESam ' 1mE:/ (-$+2 green)eggs)cur '0$O green)eggs)rec/ (-$+2 green)eggs)cur '0$O amount)of)ham, num)re4ections, reason/ +LOS- green)eggs)cur/ PL/SQL is ery flexi%le in ho! it matches up the cursor columns !ith the '0$O clause# >#>#; (etching Past the Last Ro! Once you open a cursor, you can (-$+2 from it until there are no more recor&s left in
=H

the acti e set# 1t this point the F0O$(O,0D cursor attri%ute for the cursor is set to $R,-# 1ctually, you can e en (-$+2 past the last recor&I 'n this case, PL/SQL !ill not raise any exceptions# 't 4ust !onEt &o anything for you# Because there is nothing left to fetch, though, it also !ill not mo&ify the alues in the '0$O list of the (-$+2# $he fetch !ill not set those alues to 0,LL# 3ou shoul&, therefore, ne er test the alues of '0$O aria%les to &etermine if the (-$+2 against the cursor succee&e&# 'nstea&, you shoul& chec" the alue of the F0O$(O,0D attri%ute, as explaine& in Section >#L#

>#J +olumn 1liases in +ursors $he S-L-+$ statement of the cursor inclu&es the list of columns that are returne& %y that cursor# 5ust as !ith any S-L-+$ statement, this column list may contain either actual column names or column expressions, !hich are also referre& to as calculate& or irtual columns# 1 column alias is an alternati e name you pro i&e to a column or column expression in a Auery# 3ou may ha e use& column aliases in SQL.Plus in or&er to impro e the rea&a%ility of a& hoc report output# 'n that situation, such aliases are completely optional# 'n an explicit cursor, on the other han&, column aliases are reAuire& for calculate& columns !hen* 3ou (-$+2 into a recor& &eclare& !ith a F &eclaration against that cursor# 3ou !ant to reference the calculate& column in your program# +onsi&er the follo!ing Auery# (or all companies !ith sales acti ity &uring =LLG, the S-L-+$ statement retrie es the company name an& the total amount in oice& to that company 8assume that the &efault &ate format mas" for this instance is WDD9MO09 3333E:* S-L-+$ company)name, S,M 8in )amt: (ROM company +, in oice ' W2-R- +#company)i& 6 '#company)i& 10D '#in oice)&ate B-$W--0 E<=95109=LLGE 10D E?=9D-+9=LLGE/ 'f you run this SQL statement in SQL.Plus, the output !ill loo" something li"e this* +OMP103)01M999999999999999999999999 1+M- $,RBO '0+# W1S2'07$O0 21'R +O# S,M 8'0B)1M$: 99999999999999999999999999 =<<< ;H#;<

S,M 8'0B)1M$: &oes not ma"e a particularly attracti e column hea&er for a report,
=>

%ut it !or"s !ell enough for a Auic" &ip into the &ata as an a& hoc Auery# LetEs no! use this same Auery in an explicit cursor an& a&& a column alias* D-+L1R+,RSOR comp)cur 'S S-L-+$ company)name, S,M 8in )amt: total)sales (ROM company +, in oice ' W2-R- +#company)i& 6 '#company)i& 10D '#in oice)&ate B-$W--0 E<=95109=LLGE 10D E?=9D-+9 =LLGE/ comp)rec comp)curF/ B-7'0 OP-0 comp)cur/ (-$+2 comp)cur '0$O comp)rec/ ### -0D/ With the alias in place, ' can get at that information 4ust as ' !oul& any other column in the Auery* '( comp)rec#total)sales U H<<< $2-0 DBMS)O,$P,$#P,$)L'08E 3ou ha e excee&e& your cre&it limit of PH<<< %y E OO $O)+21R 8H<<<9company)rec#total)sales, EPLLLLE::/ -0D '(/ 'f you fetch a ro! into a recor& &eclare& !ith F, the only !ay to access the column or column expression alue is to &o so %y the column name 99 after all, the recor& o%tains its structure from the cursor itself# >#K +losing +ursors -arly on ' !as taught that ' shoul& al!ays clean up after myself# $his rule is particularly important as it applies to cursors*
When you are done with a cursor, close it#2ere is the syntax for a +LOS- cursor statement*

+LOS- Rcursor)nameU !here Rcursor)nameU is the name of the cursor you are closing# 1n open cursor uses a certain amount of memory/ the exact amount &epen&s on the acti e set for the cursor# 't can, therefore, use up Auite a lot of the Share& 7lo%al 1rea of the RDBMS# $he cursor can also cause the &ata%ase to issue ro!9le el loc"s !hen the (OR ,PD1$- clause is use& in the S-L-+$ statement# >#K#= Maximum 0um%er of +ursors When your &ata%ase instance is starte&, an initialiCation parameter calle&
=J

OP-0)+,RSORS specifies the maximum num%er of open cursors that a single9user process can ha e at once# $his parameter &oes not control a system9!i&e feature, %ut rather the maximum a&&ress/memory space use& %y each process# 'f you are sloppy an& &o not close your cursors, you an& all other users might encounter the &rea&e& error message* OR19<=<<<* maximum open cursors excee&e& 3ou !oul& rather not &eal !ith this situation# (or one thing, you !ill nee& to com% through your co&e an& chec" for opene& cursors !hich ha e not %een close&# - en more frightening, your &ata%ase a&ministrator might insist that you tune your application so as to re&uce the num%er of cursors you are using 99 real co&e changesI ' say this in 4est, %ut in fact L<F of all the tuning that can %e &one for an application has nothing to &o !ith the &ata%ase, an& e erything to &o !ith the application# 1re the SQL statements tune&T 1re you closing all opene& cursorsT 1n& so on# When you close a cursor, you &isa%le it# Because the cursor no longer has an acti e set associate& !ith it, you cannot fetch recor&s from the cursor# $he memory for that cursor is release& an& the num%er of cursors mar"e& as currently open in your session is &ecrease& %y one, pulling you a!ay from the %rin" of error OR19<=<<<# 3ou shoul& close a cursor only if it is currently open# 3ou can %e sure of a cursorEs status %y chec"ing the F'SOP-0 cursor attri%ute %efore you try to close the cursor* '( company)curF'SOP-0 $2-0 +LOS- company)cur/ -0D '(/ >#K#; +losing Local +ursors 'f you &eclare a cursor in a PL/SQL %loc" 8an anonymous %loc", proce&ure, or function:, the cursor is only &efine& !ithin 8is @local to@: that %loc"# When execution of the %loc" terminates, PL/SQL !ill automatically close any local cursors !hich !ere left open !ithout raising an exception# ' recommen&, ho!e er, that you still inclu&e +LOS- statements for any cursor you opene& in your programs# DonEt &epen& on the runtime engine to &o your cleaning up for you# 'n a&&ition, if your cursor is &efine& in a pac"age, then its scope is not limite& to any particular PL/SQL %loc"# 'f you open such a cursor, it !ill stay open until you +LOSit explicitly or you &isconnect your Oracle session# >#L +ursor 1ttri%utes 3ou can manipulate cursors using the OP-0, (-$+2, an& +LOS- statements# When you nee& to get information a%out the current status of your cursor, or the result of the last fetch from a cursor, you !ill access cursor attri%utes#
=K

Both explicit an& implicit cursors ha e four attri%utes, as sho!n in $a%le >#=#
$a%le >#=* +ursor 1ttri%utes 0ameDescriptionF(O,0DReturns $R,- if recor& !as fetche& successfully, (1LS- other!ise# F0O$(O,0DReturns $R,- if recor& !as not fetche& successfully, (1LS- other!ise# FROW+O,0$Returns num%er of recor&s fetche& from cursor at that point in time# F'SOP-0Returns $R,- if cursor is open, (1LS- other!ise# $o o%tain information a%out the

execution of the cursor, you appen& the cursor attri%ute name to the name of your cursor# (or example, if you &eclare a cursor as follo!s* +,RSOR caller)cur 'S S-L-+$ caller)i&, company)i& (ROM caller/ then the four attri%utes associate& !ith the cursor are* caller)curF(O,0D caller)curF0O$(O,0D caller)curFROW+O,0$ caller)curF'SOP-0 Some of the !ays you can access the attri%utes of an explicit cursor are sho!n %elo! in %ol&* D-+L1R+,RSOR caller)cur 'S S-L-+$ caller)i&, company)i& (ROM caller/ caller)rec caller)curF/ B-7'0 /. Only open the cursor if it is not yet open ./ '( 0O$ caller!cur1IS"PE2 $2-0 OP-0 caller)cur -0D '(/ (-$+2 caller)cur '0$O caller)rec/ /. Seep fetching until no more recor&s are (O,0D ./ W2'L- caller!cur1$"32D LOOP DBMS)O,$P,$#P,$)L'08E5ust fetche& recor& num%er E OO $O)+21R &caller!cur14"5C"326//7 (-$+2 caller)cur '0$O caller)rec/ -0D LOOP/ CL"SE caller!cur7 -0D/ PL/SQL &oes pro i&e these same attri%utes for an implicit cursor# Because an implicit cursor has no name, PL/SQL assigns the generic name SQL to it# ,sing this name, you
=L

can access the attri%utes of an implicit cursor# (or more information on this topic, see Section >#L#H, @'mplicit SQL +ursor 1ttri%utes@ later in the chapter# 3ou can reference cursor attri%utes in your PL/SQL co&e, as sho!n in the prece&ing example, %ut you cannot use those attri%utes insi&e a SQL statement# 'f you try to use the FROW+O,0$ attri%ute in the W2-R- clause of a S-L-+$, for example* S-L-+$ caller)i&, company)i& (ROM caller W2-R- company)i& 6 company)curFROW+O,0$/ then you !ill get a compile error* PLS9<<;;L* 1ttri%ute expression !ithin SQL expression $he four explicit cursor attri%utes are examine& in &etail in the follo!ing sections# >#L#= $he F(O,0D 1ttri%ute $he F(O,0D attri%ute reports on the status of your most recent (-$+2 against the cursor# $he attri%ute e aluates to $R,- if the most recent (-$+2 against the explicit cursor returne& a ro!, or (1LS- if no ro! !as returne&# 'f the cursor has not yet %een opene&, a reference to the F(O,0D attri%ute raises the '0B1L'D)+,RSOR exception# 3ou can e aluate the F(O,0D attri%ute of any open cursor, %ecause you reference the cursor %y name# 'n the follo!ing example, ' loop through all the callers in the caller)cur cursor, assign all calls entere& %efore to&ay to that particular caller, an& then fetch the next recor&# 'f ' ha e reache& the last recor&, then the F0O$(O,0D attri%ute is set to $R,- an& ' exit the simple loop# OP-0 caller)cur/ LOOP (-$+2 caller)cur '0$O caller)rec/ -D'$ W2-0 0O$ caller)curF(O,0D/ ,PD1$- call S-$ caller)i& 6 caller)rec#caller)i& W2-R- call)timestamp R S3SD1$-/ -0D LOOP/ +LOS- call)cur/ 'n this next example, ' "eep a count of the total num%er of or&ers entere& for a particular company# 'f ' ha e fetche& my last or&er 8F(O,0D is (1LS-:, then ' &isplay a message in Oracle (orms informing the user of the total num%er of or&ers* OP-0 or&er)cur/ LOOP (-$+2 or&er)cur '0$O or&er)num%er, company)i&/ -D'$ W2-0 or&er)curF0O$(O,0D/
;<

&o)other)stuff)then)"eep)count/ *or&er#count)or&ers *6 *or&er#count)or&ers Q =/ -0D LOOP/ +LOS- or&er)cur/ '( *or&er#count)or&ers U = $2-0 DBMS)O,$P,$#P,$)L'08E1 total of E OO $O)+21R 8*or&er#count)or&ers: OO E or&ers ha e %een foun&#E:/ -LS/. OO ' hate to co&e messages li"e E1 total of = or&ers !as foun&#E OO 't ma"es me soun& illiterate# So ' !ill inclu&e a special9case OO message !hen 4ust one or&er is foun&# ./ DBMS)O,$P,$#P,$)L'0-8E5ust one or&er !as foun&#E:/ -0D '(/ >#L#; $he F0O$(O,0D 1ttri%ute $he F0O$(O,0D attri%ute is the opposite of F(O,0D# 't returns $R,- if the explicit cursor is una%le to fetch another ro! %ecause the last ro! !as fetche&# 'f the cursor is una%le to return a ro! %ecause of an error, the appropriate exception is raise&# 'f the cursor has not yet %een opene&, a reference to the F0O$(O,0D attri%ute raises the '0B1L'D)+,RSOR exception# 3ou can e aluate the F0O$(O,0D attri%ute of any open cursor, %ecause you reference the cursor %y name# When shoul& you use F(O,0D an& !hen shoul& you use F0O$(O,0DT $he t!o attri%utes are &irectly, logically oppose&, so !hate er you can &o !ith one you can also &o !ith a 0O$ of the other# 'n other !or&s, once a fetch has %een performe& against the open cursor Rcursor)nameU, the follo!ing expressions are eAui alent* Rcursor)nameUF(O,0D Rcursor)nameUF0O$(O,0D Rcursor)nameUF0O$(O,0D Rcursor)nameUF(O,0D 6 0O$ 6 0O$

,se !hiche er formulation fits most naturally in your co&e# 'n a pre ious example, ' issue& the follo!ing statement* -D'$ W2-0 0O$ caller)curF(O,0D/ to terminate the loop# 1 simpler an& more &irect statement !oul& use the F0O$(O,0D instea& of F(O,0D, as follo!s* -D'$ W2-0 caller)recF0O$(O,0D/
;=

>#L#? $he FROW+O,0$ 1ttri%ute $he FROW+O,0$ attri%ute returns the num%er of recor&s fetche& from a cursor at the time that the attri%ute is Auerie&# When you first open a cursor, its FROW+O,0$ is set to Cero# 'f you reference the FROW+O,0$ attri%ute of a cursor that is not open, you !ill raise the '0B1L'D)+,RSOR exception# 1fter each recor& is fetche&, FROW+O,0$ is increase& %y one# $his attri%ute can %e reference& in a PL/SQL statement, %ut not in a SQL statement# 3ou can use FROW+O,0$ to limit the num%er of recor&s fetche& from a cursor# $he follo!ing example retrie es only the first ten recor&s from the cursor, pro i&ing the top ten companies placing or&ers in =LL?* D-+L1R+,RSOR company)cur 'S S-L-+$ company)name, company)i&, total)or&er (ROM company)re enue) ie! W2-R- $O)0,MB-R 8$O)+21R 8or&er)&ate:: 6 =LL? ORD-R B3 total)or&er D-S+/ company)rec company)curF/ B-7'0 OP-0 company)cur/ LOOP (-$+2 company)cur '0$O company)rec/ -D'$ W2-0 company)curFROW+O,0$ U =< OR company)curF0O$(O,0D/ DBMS)O,$P,$#P,$)L'08E+ompany E OO company)rec#company)name OO E ran"e& num%er E OO $O)+21R 8company)curFROW+O,0$: OO E#E:/ -0D LOOP/ +LOS- company)cur/ >#L#G $he F'SOP-0 1ttri%ute $he F'SOP-0 attri%ute returns $R,- if the cursor is open/ other!ise, it returns (1LS-# 'n most cases !hen you use a cursor, you open it, fetch from it, an& close it, all !ithin one routine# Most of the time it is easy to "no! !hether your cursor is open or close&# 'n some cases, ho!e er, you !ill sprea& your cursor actions out o er a !i&er area of co&e, perhaps across &ifferent routines 8possi%le if the cursor is &eclare& in a pac"age:# 'f so, it !ill ma"e sense to use the F'SOP-0 attri%ute to ma"e sure that a cursor is open %efore you perform a fetch* '( 0O$ caller)curF'SOP-0 $2-0 OP-0 caller)cur/ -0D '(/ (-$+2 caller)cur '0$O caller)rec/ ###
;;

0O$-* Remem%er that if you try to open a cursor that has alrea&y %een opene&, you !ill recei e a runtime error* OR19<>H==* PL/SQL* cursor alrea&y open >#L#H 'mplicit SQL +ursor 1ttri%utes When the RDBMS opens an implicit cursor to process your reAuest 8!hether it is a Auery or an '0S-R$ or an ,PD1$-:, it ma"es cursor attri%utes a aila%le to you !ith the SQL cursor# $his is not a cursor in the !ay of an explicit cursor# 3ou cannot open, fetch from, or close the SQL cursor, %ut you can access information a%out the most recently execute& SQL statement through SQL cursor attri%utes# $he SQL cursor has the same four attri%utes as an explicit cursor* SQLF(O,0D SQLF0O$(O,0D SQLFROW+O,0$ SQLF'SOP-0 >#L#> Differences Bet!een 'mplicit an& -xplicit +ursor 1ttri%utes $he alues returne& %y implicit cursor attri%utes &iffer from those of explicit cursor attri%utes in the follo!ing !ays* 'f the RDBMS has not opene& an implicit SQL cursor in the session, then the SQLFROW+O,0$ attri%ute returns 0,LL instea& of raising the '0B1L'D)+,RSOR error# References to the other attri%utes 8'SOP-0, (O,0D, 0O$(O,0D: all return (1LS-# 3ou !ill ne er raise the '0B1L'D)+,RSOR error !ith an implicit cursor attri%ute reference# $he F'SOP-0 attri%ute !ill al!ays return (1LS- 99 %efore an& after the SQL statement# 1fter the statement is execute& 8!hether it is S-L-+$, ,PD1$-, D-L-$-, or '0S-R$:, the implicit cursor !ill alrea&y ha e %een opene& an& close& implicitly# 1n implicit cursor can ne er %e open outsi&e of the statement itself# SQL cursor attri%utes are al!ays set accor&ing to the results of the most recently execute& SQL statement# $hat SQL statement might ha e %een execute& in a store& proce&ure !hich your program calle&/ you might not e en %e a!are of that SQL statement execution# 'f you plan to ma"e use of a SQL cursor attri%ute, ma"e sure that you reference that attri%ute imme&iately after you execute the SQL statement# $he F(O,0D attri%ute returns $R,- if an ,PD1$-, D-L-$-, or '0S-R$ affecte& at least one recor&# 't !ill return (1LS- if those statements faile& to affect any recor&s# 't returns $R,- if an implicit S-L-+$ returns one ro!# $he %eha ior of the F0O$(O,0D attri%ute for ,PD1$-, D-L-$-, or
;?

'0S-R$ statements is the opposite of F(O,0D# $he situation for an implicit S-L-+$ is a %it &ifferent* !hen you use an implicit S-L-+$ statement, ne er rely on the F0O$(O,0D an& F(O,0D attri%utes# When an implicit S-L-+$ statement &oes not return any ro!s, PL/SQL imme&iately raises the 0O)D1$1)(O,0D exception# When an implicit S-L-+$ statement returns more than one ro!, PL/SQL imme&iately raises the $OO)M103)ROWS exception# 'n either case, once the exception is raise&, control shifts to the exception section of the PL/SQL %loc"#

6.89 Cursor Parameters 3ou are pro%a%ly familiar !ith parameters for proce&ures an& functions# Parameters pro i&e a !ay to pass information into an& out of a mo&ule# ,se& properly, parameters impro e the usefulness an& flexi%ility of mo&ules# PL/SQL also allo!s you to pass parameters into cursors# $he same rationale for using parameters in mo&ules applies to parameters for cursors*
1 parameter ma"es the cursor more reusa%le# 'nstea& of har&co&ing a alue

into the W2-R- clause of a Auery to select particular information, you can use a parameter an& then pass &ifferent alues to the W2-R- clause each time a cursor is opene&#
1 parameter a oi&s scoping pro%lems# When you pass parameters instea& of

har&co&ing alues, the result set for that cursor is not tie& to a specific aria%le in a program or %loc"# 'f your program has neste& %loc"s, you can &efine the cursor at a higher9le el 8enclosing: %loc" an& use it in any of the su%%loc"s !ith aria%les &efine& in those local %loc"s# 3ou can specify as many cursor parameters as you !ant an& nee&# When you OP-0 the parameter, you nee& to inclu&e an argument in the parameter list for each parameter, except for trailing parameters that ha e &efault alues# When shoul& you parameteriCe your cursorT ' apply the same rule of thum% to cursors as to mo&ules* if ' am going to use the cursor in more than one place, !ith &ifferent alues for the same W2-R- clause, then ' shoul& create a parameter for the cursor# LetEs ta"e a loo" at the &ifference %et!een parameteriCe& an& unparameteriCe& cursors# (irst, a cursor !ithout any parameters* +,RSOR 4o"e)cur 'S S-L-+$ name, category, last)use&)&ate (ROM 4o"e/ $he result set of this cursor is all the ro!s in the 4o"e ta%le# 'f ' 4ust !ante& to retrie e all 4o"es in the 2,SB10D category, ' !oul& nee& to a&& a W2-R- clause as follo!s*
;G

+,RSOR 4o"e)cur 'S S-L-+$ name, category, last)use&)&ate (ROM 4o"e W2-R- category 6 E2,SB10DE/ ' &i&nEt use a cursor parameter to accomplish this tas", nor &i& ' nee& to# $he 4o"e)cur cursor no! retrie es only those 4o"es a%out hus%an&s# $hatEs all !ell an& goo&, %ut !hat if ' also !oul& li"e to see light%ul% 4o"es an& then chic"en9an&9egg 4o"es an& finally, as my ten9year9ol& !oul& certainly &eman&, all my "noc"9"noc" 4o"esT >#=<#= 7eneraliCing +ursors !ith Parameters ' really &onEt !ant to !rite a separate cursor for each &ifferent category 99 that is &efinitely not a &ata9&ri en approach to programming# 'nstea&, ' !oul& much rather %e a%le to change the 4o"e cursor so that it can accept &ifferent categories an& return the appropriate ro!s# $he %est 8though not the only: !ay to &o this is !ith a cursor parameter* D-+L1R/. OO +ursor !ith parameter list consisting of a single OO string parameter# ./ +,RSOR 4o"e)cur 8category)in B1R+21R;: 'S S-L-+$ name, category, last)use&)&ate (ROM 4o"e W2-R- category 6 ,PP-R 8category)in:/ 4o"e)rec4o"e)curF/ B-7'0 /. 0o! !hen ' open the cursor, ' also pass the argument ./ OP-0 4o"e)cur8*4o"e#category:/ (-$+2 4o"e)cur '0$O 4o"e)rec/ ' a&&e& a parameter list after the cursor name an& %efore the 'S "ey!or&# ' too" out the har&co&e& @2,SB10D@ an& replace& it !ith @,PP-R 8category)in:@ so that ' coul& enter @2,SB10D@, @hus%an&@, or @2uS%1nD@ an& the cursor !oul& still !or"# 0o! !hen ' open the cursor, ' specify the alue ' !ish to pass as the category %y inclu&ing that alue 8!hich can %e a literal, constant, or expression: insi&e parentheses# 1t the moment the cursor is opene&, the S-L-+$ statement is parse& an& %oun& using the specifie& alue for category)in# $he result set is i&entifie& an& the cursor is rea&ie& for fetching# 6.89.2 "pening Cursors :it% Parameters ' can OP-0 that same cursor !ith any category ' li"e# 0o! ' &onEt ha e to !rite a
;H

separate cursor to accommo&ate this reAuirement* OP-0 4o"e)cur 8*4o"e#category:/ OP-0 4o"e)cur 8Ehus%an&E:/ OP-0 4o"e)cur 8EpoliticianE:/ OP-0 4o"e)cur 8*4o"e#relation OO E '09L1WE:/ $he most common place to use a parameter in a cursor is in the W2-R- clause, %ut you can ma"e reference to it any!here in the S-L-+$ statement, as sho!n here* D-+L1R+,RSOR 4o"e)cur 8category)in B1R+21R;: 'S S-L-+$ name, category)in, last)use&)&ate (ROM 4o"e W2-R- category 6 ,PP-R 8category)in:/ 'nstea& of returning the category from the ta%le, ' simply pass %ac" the category)in parameter in the select list# $he result !ill %e the same either !ay, %ecause my W2-R- clause restricts categories to the parameter alue# >#=<#? Scope of +ursor Parameters $he scope of the cursor parameter is confine& to that cursor# 3ou cannot refer to the cursor parameter outsi&e of the S-L-+$ statement associate& !ith the cursor# $he follo!ing PL/SQL fragment !ill not compile %ecause the program)name i&entifier is not a local aria%le in the %loc"# 'nstea&, it is a formal parameter for the cursor an& is &efine& only insi&e the cursor* D-+L1R+,RSOR scariness)cur 8program)name B1R+21R;: 'S S-L-+$ S,M 8scary)le el: total)scary)le el (ROM tales)from)the)crypt W2-R- prog)name 6 program)name/ B-7'0 program)name *6 E$2- BR-1$2'07 M,MM3E/ /. 'llegal reference ./ OP-0 scariness)cur 8program)name:/ -0D/ >#=<#G +ursor Parameter Mo&es $he syntax for cursor parameters is ery similar to that of proce&ures an& functions, !ith the restriction that a cursor parameter can %e an '0 parameter only# 3ou cannot specify O,$ or '0 O,$ mo&es for cursor parameters 8see +hapter =H, Proce&ures an& (unctions, for more information on parameter mo&es:# $he '0 an& '0 O,$ mo&es are use& to pass alues out of a proce&ure through that parameter# $his &oesnEt ma"e sense for a cursor# Balues cannot %e passe& %ac" out of a
;>

cursor through the parameter list# 'nformation is retrie e& from a cursor only %y fetching a recor& an& copying alues from the column list !ith an '0$O clause# >#=<#H Default Balues for Parameters +ursor parameters can %e assigne& &efault alues# 2ere is an example of a parameteriCe& cursor !ith a &efault alue* +,RSOR emp)cur 8emp)i&)in 0,MB-R *6 <: 'S S-L-+$ employee)i&, emp)name (ROM employee W2-R- employee)i& 6 emp)i&)in/ So if 5oe SmithEs employee 'D is =<<=, the follo!ing statements !oul& set my)emp)i& to =<<= an& my)emp)name to 5O- SM'$2* OP-0 emp)cur 8=<<=:/ (-$+2 emp)cur '0$O my)emp)i&, my)emp)name/ Because the emp)i&)in parameter has a &efault alue, ' can also open an& fetch from the cursor !ithout specifying a parameter# 'f ' &o not specify a alue for the parameter, the cursor uses the &efault alue#

>#== S-L-+$ (OR ,PD1$- in +ursors When you issue a S-L-+$ statement against the &ata%ase to Auery some recor&s, no loc"s are place& on the selecte& ro!s# 'n general, this is a !on&erful feature %ecause the num%er of recor&s loc"e& at any gi en time is 8%y &efault: "ept to the a%solute minimum* only those recor&s !hich ha e %een change& %ut not yet committe& are loc"e&# - en then, others !ill %e a%le to rea& those recor&s as they appeare& %efore the change 8the @%efore image@ of the &ata:# $here are times, ho!e er, !hen you !ill !ant to loc" a set of recor&s e en %efore you change them in your program# Oracle offers the (OR ,PD1$- clause of the S-L-+$ statement to perform this loc"ing# When you issue a S-L-+$###(OR ,PD1$- statement, the RDBMS automatically o%tains exclusi e ro!9le el loc"s on all the ro!s i&entifie& %y the S-L-+$ statement, hol&ing the recor&s @for your changes only@ as you mo e through the ro!s retrie e& %y the cursor# 0o one else !ill %e a%le to change any of these recor&s until you perform a ROLLB1+S or a +OMM'$# 2ere are t!o examples of the (OR ,PD1$- clause use& in a cursor* +,RSOR toys)cur 'S S-L-+$ name, manufacturer, preference)le el, sell)at)yar&sale)flag (ROM my)sons)collection
;J

W2-R- hours)use& 6 < (OR ,PD1$-/ +,RSOR fall)4o%s)cur 'S S-L-+$ tas", expecte&)hours, tools)reAuire&, &o)it)yourself)flag (ROM !interiCe W2-R- year 6 $O)+21R 8S3SD1$-, E3333E: (OR ,PD1$- O( tas"/ $he first cursor uses the unAualifie& (OR ,PD1$- clause, !hile the secon& cursor Aualifies the (OR ,PD1$- !ith a column name from the Auery# 3ou can use the (OR ,PD1$- clause in a S-L-+$ against multiple ta%les# 'n this case, ro!s in a ta%le are loc"e& only if the (OR ,PD1$- clause references a column in that ta%le# 'n the follo!ing example the (OR ,PD1$- clause &oes not result in any loc"e& ro!s in the !interiCe ta%le* +,RSOR fall)4o%s)cur 'S S-L-+$ !#tas", !#expecte&)hours, !#tools)reAuire&, !#&o)it)yourself)flag (ROM !interiCe !, hus%an&)config hc W2-R- year 6 $O)+21R 8S3SD1$-, E3333E: (OR ,PD1$- O( hus%an&)config#max)procrastination)allo!e&/ $he (OR ,PD1$- O( clause only mentions the max)procrastination)allo!e& column/ no columns in the !interiCe ta%le are liste&# $he O( list of the (OR ,PD1$- clause &oes not restrict you to changing only those columns liste&# Loc"s are still place& on all ro!s/ the O( list 4ust gi es you a !ay to &ocument more clearly !hat you inten& to change# 'f you simply state (OR ,PD1$in the Auery an& &o not inclu&e one or more columns after the O( "ey!or&, then the &ata%ase !ill then loc" all i&entifie& ro!s across all ta%les liste& in the (ROM clause# (urthermore, you &o not ha e to actually ,PD1$- or D-L-$- any recor&s 4ust %ecause you issue& a S-L-+$###(OR ,PD1$- 99 that act simply states your intention to %e a%le to &o so# (inally, you can appen& the optional "ey!or& 0OW1'$ to the (OR ,PD1$- clause to tell Oracle not to !ait if the ta%le has %een loc"e& %y another user# 'n this case, control !ill %e returne& imme&iately to your program so that you can perform other !or" or simply !ait for a perio& of time %efore trying again# Without the 0OW1'$ clause, your process !ill %loc" until the ta%le is a aila%le# $here is no limit to the !ait time unless the ta%le is remote# (or remote o%4ects, the Oracle initialiCation parameter, D'S$R'B,$-D)LO+S)$'M-O,$, is use& to set the limit# >#==#= Releasing Loc"s !ith +OMM'$ 1s soon as a cursor !ith a (OR ,PD1$- clause is OP-0e&, all ro!s i&entifie& in the result set of the cursor are loc"e& an& remain loc"e& until your session issues either a +OMM'$ statement to sa e any changes or a ROLLB1+S statement to cancel those
;K

changes# When either of these actions occurs, the loc"s on the ro!s are release&# 1s a result, you cannot execute another (-$+2 against a (OR ,PD1$- cursor after you +OMM'$ or ROLLB1+S# 3ou !ill ha e lost your position in the cursor# +onsi&er the follo!ing program, !hich assigns !interiCation chores*M=N M=N +a eat* ' &onEt !ant to set false expectations !ith anyone, especially my !ife# $he co&e in this %loc" is purely an example# 'n reality, ' set the max)procrastination)allo!e& to fi e years an& let my house &ecay until ' can affor& to pay someone to &o something, or my !ife &oes it, or she gi es me an ultimatum# 0o! you "no! !hy ' &eci&e& to !rite a %oo"### D-+L1R/. 1ll the 4o%s in the (all to prepare for the Winter ./ +,RSOR fall)4o%s)cur 'S S-L-+$ tas", expecte&)hours, tools)reAuire&, &o)it)yourself)flag (ROM !interiCe W2-R- year 6 $O)+21R 8S3SD1$-, E3333E: 10D complete&)flag 6 E0O$3-$E (OR ,PD1$- O( tas"/ B-7'0 /. (or each 4o% fetche& %y the cursor### ./ (OR 4o%)rec '0 fall)4o%s)cur LOOP '( 4o%)rec#&o)it)yourself)flag 6 E3O,+10DO'$E $2-0 /. OO ' ha e foun& my next 4o%# 1ssign it to myself 8li"e someone OO is going to &o itI: an& then commit the changes# ./ ,PD1$- !interiCe S-$ responsi%le 6 ES$-B-0E W2-R- tas" 6 4o%)rec#tas" 10D year 6 $O)+21R 8S3SD1$-, E3333E:/ +OMM'$/ -0D '(/ -0D LOOP/ -0D/ Suppose this loop fin&s its first 3O,+10DO'$ 4o%# 't then commits an assignment of a 4o% to S$-B-0# When it tries to (-$+2 the next recor&, the program raises the follo!ing exception* OR19<=<<;* fetch out of seAuence 'f you e er nee& to execute a +OMM'$ or ROLLB1+S as you (-$+2 recor&s from a S-L-+$ (OR ,PD1$- cursor, you shoul& inclu&e co&e 8such as a loop -D'$ or other con&itional logic: to halt any further fetches from the cursor#
;L

>#==#; $he W2-R- +,RR-0$ O( +lause PL/SQL pro i&es the W2-R- +,RR-0$ O( clause for %oth ,PD1$- an& D-L-$statements insi&e a cursor in or&er to allo! you to easily ma"e changes to the most recently fetche& ro! of &ata# $he general format for the W2-R- +,RR-0$ O( clause is as follo!s* ,PD1$- ta%le)name S-$ set)clause W2-R- +,RR-0$ O( cursor)name/ D-L-$(ROM ta%le)name W2-R- +,RR-0$ O( cursor)name/ 0otice that the W2-R- +,RR-0$ O( clause references the cursor an& not the recor& into !hich the next fetche& ro! is &eposite&# $he most important a& antage to using W2-R- +,RR-0$ O( !here you nee& to change the ro! fetche& last is that you &o not ha e to co&e in t!o 8or more: places the criteria use& to uniAuely i&entify a ro! in a ta%le# Without W2-R- +,RR-0$ O(, you !oul& nee& to repeat the W2-R- clause of your cursor in the W2-R- clause of the associate& ,PD1$-s an& D-L-$-s# 1s a result, if the ta%le structure changes in a !ay that affects the construction of the primary "ey, you ha e to ma"e sure that each SQL statement is upgra&e& to support this change# 'f you use W2-R- +,RR-0$ O(, on the other han&, you only ha e to mo&ify the W2-R- clause of the S-L-+$ statement# $his might seem li"e a relati ely minor issue, %ut it is one of many areas in your co&e !here you can le erage su%tle features in PL/SQL to minimiCe co&e re&un&ancies# ,tiliCation of W2-R- +,RR-0$ O(, F$3P-, an& F &eclaration attri%utes, cursor (OR loops, local mo&ulariCation, an& other PL/SQL language constructs can ha e a %ig impact on re&ucing the pain you may experience !hen you maintain your Oracle9 %ase& applications# LetEs see ho! this clause !oul& impro e the pre ious example# 'n the 4o%s cursor (OR loop a%o e, ' !ant to ,PD1$- the recor& that !as currently (-$+2e& %y the cursor# ' &o this in the ,PD1$- statement %y repeating the same W2-R- use& in the cursor %ecause 8tas", year: ma"es up the primary "ey of this ta%le* W2-R- tas" 6 4o%)rec#tas" 10D year 6 $O)+21R 8S3SD1$-, E3333E:/ $his is a less than i&eal situation, as explaine& a%o e* ' ha e co&e& the same logic in t!o places, an& this co&e must %e "ept synchroniCe&# 't !oul& %e so much more con enient an& natural to %e a%le to co&e the eAui alent of the follo!ing statements*
Delete the record I just fetched.or* Update these columns in that row I just fetched.1 perfect fit for W2-R- +,RR-0$ O(I ?<

$he next ersion of my !interiCation program %elo! uses this clause# ' ha e also s!itche& to a simple loop from (OR loop %ecause ' !ant to exit con&itionally from the loop* D-+L1R+,RSOR fall)4o%s)cur 'S S-L-+$ ### same as %efore ### / 4o%)rec fall)4o%s)curF/ B-7'0 OP-0 fall)4o%s)cur/ LOOP (-$+2 fall)4o%s)cur '0$O 4o%)rec/ '( fall)4o%s)curF0O$(O,0D $2-0 -D'$/ -LS'( 4o%)rec#&o)it)yourself)flag 6 E3O,+10DO'$E $2-0 ,PD1$- !interiCe S-$ responsi%le 6 ES$-B-0E W2-R- +,RR-0$ O( fall)4o%s)cur/ +OMM'$/ -D'$/ -0D '(/ -0D LOOP/ +LOS- fall)4o%s)cur/ -0D/ 6.82 Cursor ;aria<les 'n PL/SQL Release ;#?, a aila%le !ith the release of Oracle Ser er Release J#?, you can create an& use cursor aria%les# ,nli"e an explicit cursor, !hich names the PL/SQL !or" area for the result set, a cursor aria%le is instea& a 8Release ;#?: reference to that !or" area# -xplicit an& implicit cursors are %oth static in that they are tie& to specific Aueries# $he cursor aria%le can %e opene& for any Auery, e en &ifferent Aueries !ithin a single program execution# $he most important %enefit of the cursor aria%le is that it pro i&es a mechanism for passing results of Aueries 8the ro!s returne& %y fetches against a cursor: %et!een &ifferent PL/SQL programs 99 e en %et!een client an& ser er PL/SQL programs# Prior to PL/SQL Release ;#?, you !oul& ha e ha& to fetch all &ata from the cursor, store it in PL/SQL aria%les 8perhaps a PL/SQL ta%le:, an& then pass those aria%les as arguments# With cursor aria%les, you simply pass the reference to that cursor# $his impro es performance an& streamlines your co&e# 't also means that the cursor is, in effect, share& among the programs !hich ha e access to the cursor aria%le# 'n a client9ser er en ironment, for example, a program on the client si&e coul& open an& start fetching from the cursor aria%le, then pass that aria%le as an argument to a store& proce&ure on the ser er# $his store& program coul&
?=

then continue fetching an& pass control %ac" to the client program to close the cursor# 3ou can also perform the same steps %et!een &ifferent store& programs, on the same or &ifferent &ata%ase instances# +ursor Baria%les in PL/SQL Release ;#; +ursor aria%les first %ecame a aila%le in PL/SQL Release ;#;# $his first ersion of cursor aria%les allo!e& you to open an& close the cursor o%4ects !ithin PL/SQL, %ut you coul& fetch through these cursor aria%les only !ithin a host language 8using the Oracle +all 'nterface 99 O+' 99 or a precompiler li"e Pro.+:# 't !as not until Release ;#? that the PL/SQL language ma&e cursor aria%les a aila%le for @self9containe&@ execution, in&epen&ent of any host language# Because the focus of this %oo" is on stan&alone PL/SQL &e elopment, ' present cursor aria%les as a PL/SQL Release ;#? enhancement# 'f you &o ha e PL/SQL Release ;#; an& !or" !ith PL/SQL in a host language en ironment, you can still use cursor aria%les# 5ust &onEt try to (-$+2 !ithin PL/SQL an& &onEt expect any of the cursor attri%utes to %e a aila%le for your cursor aria%les# 0O$-* $he client9ser er aspect of this sharing !ill only really come into play !hen the Oracle De eloper/;<<< tools are con erte& to use PL/SQL Release ;#? or a%o e# $his process, sho!n in (igure >#;, offers &ramatic ne! possi%ilities for &ata sharing an& cursor management in PL/SQL programs# $igure 6.2= 4e0erencing a cursor aria<le across t:o programs $he co&e you !rite to ta"e a& antage of cursor aria%les is ery similar to that for explicit cursors# $he follo!ing example &eclares a cursor type 8calle& a R-( +,RSOR type: for the company ta%le, then opens, fetches from, an& closes the cursor* D-+L1R/. +reate the cursor type# ./ $3P- company)curtype 'S R-( +,RSOR R-$,R0 companyF/ /. Declare a cursor aria%le of that type# ./ company)cur ar company)curtype/ /. Declare a recor& !ith same structure as cursor aria%le# ./ company)rec companyF/ B-7'0 /. Open the cursor aria%le, associating !ith it a SQL statement# ./ OP-0 company)cur ar (OR S-L-+$ . (ROM company/ /. (etch from the cursor aria%le# ./ (-$+2 company)cur ar '0$O company)rec/ /. +lose the cursor o%4ect associate& !ith aria%le# ./
?;

+LOS- company)cur ar/ -0D/ $hat loo"s an a!ful lot li"e explicit cursor operations, except for the follo!ing* $he R-( +,RSOR type &eclaration $he OP-0 (OR syntax !hich specifie& the Auery at the time of the open While the syntax is ery similar, the fact that the cursor aria%le is a aria%le opens up many ne! opportunities in your programs# $hese are explore& in the remain&er of this section# >#=;#= (eatures of +ursor Baria%les +ursor aria%les let you* 1ssociate a cursor aria%le !ith &ifferent Aueries at &ifferent times in your program execution# 'n other !or&s, a single cursor aria%le can %e use& to fetch from &ifferent result sets# Pass a cursor aria%le as an argument to a proce&ure or function# 3ou can, in essence, share the results of a cursor %y passing the reference to that result set# -mploy the full functionality of static PL/SQL cursors for cursor aria%les# 3ou can OP-0, +LOS-, an& (-$+2 !ith cursor aria%les !ithin your PL/SQL programs# 3ou can reference the stan&ar& cursor attri%utes 99 F'SOP-0, F(O,0D, F0O$(O,0D, an& FROW+O,0$ 99 for cursor aria%les# 1ssign the contents of one cursor 8an& its result set: to another cursor aria%le# Because the cursor aria%le is a aria%le, it can %e use& in assignment operations# $here are, ho!e er, restrictions on referencing this "in& of aria%le, a&&resse& later in this chapter# >#=;#; Similarities to Static +ursors One of the "ey &esign reAuirements for cursor aria%les !as that as much as possi%le the semantics use& to manage cursor o%4ects !oul& %e the same as that of static cursors# While the &eclaration of a cursor aria%le an& the syntax for opening it are enhance&, the follo!ing cursor operations are unchange& for cursor aria%les* $he +LOS- statement# 'n the follo!ing example ' &eclare a R-( +,RSOR type an& a cursor aria%le %ase& on that type# $hen ' close the cursor aria%le using the same syntax as for that of a static cursor* D-+L1R $3P- ar)cur)type 'S R-( +,RSOR/ ar)cur ar)cur)type/ B-7'0
??

+LOS- ar)cur/ -0D/

+ursor attri%utes# 3ou can use any of the four cursor attri%utes !ith exactly

the same syntax as for that of a static cursor# $he rules go erning the use an& alues returne& %y those attri%utes match that of explicit cursors# 'f ' ha e &eclare& a aria%le cursor as in the pre ious example, ' coul& use all the cursor attri%utes as follo!s* ar)curF'SOOP-0 ar)curF(O,0D ar)curF0O$(O,0D ar)curFROW+O,0$

(etching from the cursor aria%le# 3ou use the same (-$+2 syntax !hen

fetching from a cursor aria%le into local PL/SQL &ata structures# $here are, ho!e er, a&&itional rules applie& %y PL/SQL to ma"e sure that the &ata structures of the cursor aria%leEs ro! 8the set of alues returne& %y the cursor o%4ect: match that of the &ata structures to the right of the '0$O "ey!or&# $hese rules are &iscusse& in Section >#=;#>, @Rules for +ursor Baria%les@# Because the syntax for these aspects of cursor aria%les remain unchange&, ' !onEt co er them again in the remain&er of this section# 'nstea& ' !ill focus on the ne! capa%ilities a aila%le an& the change& syntax reAuire& for cursor aria%les# >#=;#? Declaring R-( +,RSOR $ypes an& +ursor Baria%les 5ust as !ith a PL/SQL ta%le or a programmer9&efine& recor&, you must perform t!o &istinct &eclaration steps in or&er to create a cursor aria%le* = +reate a reference& cursor $3P-# ; Declare the actual cursor aria%le %ase& on that type# $he syntax for creating a reference& cursor type is as follo!s* $3P- cursor)type)name 'S R-( +,RSOR M R-$,R0 return)type N/ !here cursor)type)name is the name of the type of cursor an& return)type is the R-$,R0 &ata specification for the cursor type# $he return)type can %e any of the &ata structures ali& for a normal cursor R-$,R0 clause, &efine& using the F attri%ute or %y referencing a pre iously9&efine& recor& $3P-# 0otice that the R-$,R0 clause is optional !ith the R-( +,RSOR type statement# Both of the follo!ing &eclarations are ali&* $3P- company)curtype 'S R-( +,RSOR R-$,R0 companyF/ $3P- generic)curtype 'S R-( +,RSOR/ $he first form of the R-( +,RSOR statement is calle& a strong type %ecause it attaches a recor& type 8or ro! type: to the cursor aria%le type at the moment of
?G

&eclaration# 1ny cursor aria%le &eclare& using that type can only %e use& !ith SQL statement an& (-$+2 '0$O &ata structures !hich match the specifie& recor& type# $he a& antage of a strong R-( $3P- is that the compiler can &etermine !hether or not the &e eloper has properly matche& up the cursor aria%leEs (-$+2 statements !ith its cursor o%4ectEs Auery list# $he secon& form of the R-( +,RSOR statement, in !hich the R-$,R0 clause is missing, is calle& a !ea" type# $his cursor aria%le type is not associate& !ith any recor& &ata structure# +ursor aria%les &eclare& !ithout the R-$,R0 clause can %e use& in much more flexi%le !ays than the strong type# $hey can %e use& !ith any Auery, !ith any ro!type structure 99 arying e en !ithin the course of a single program# >#=;#?#= Declaring cursor aria%les $he syntax for &eclaring a cursor aria%le is* cursor)name cursor)type)name/ !here cursor)name is the name of the cursor an& cursor)type)name is the name of the type of cursor pre iously &efine& !ith a $3P- statement# 2ere is an example of the creation of a cursor aria%le* D-+L1R/. +reate a cursor type for sports cars# ./ $3P- sports)car)cur)type 'S R-( +,RSOR R-$,R0 carF/ /. +reate a cursor aria%le for sports cars# ./ sports)car)cur sports)car)cur)type/ B-7'0 ### -0D/ 't is ery important to &istinguish %et!een &eclaring a cursor aria%le an& creating an actual cursor o%4ect 99 the result set i&entifie& %y the cursor SQL statement# $he cursor aria%le is nothing more than a reference or pointer# 1 constant is nothing more than a alue, !hereas a aria%le points to its alue# Similarly, a static cursor acts as a constant, !hereas a cursor aria%le points to a cursor o%4ect# $hese &istinctions are sho!n in (igure >#?# 0otice that t!o &ifferent cursor aria%les in &ifferent programs %oth refer to the same cursor o%4ect# (igure >#?* $he referencing character of cursor aria%les Declaration of a cursor aria%le &oes not create a cursor o%4ect# $o &o that, you must instea& use the OP-0 (OR syntax to create a ne! cursor o%4ect an& assign it to the aria%le#
?H

>#=;#G Opening +ursor Baria%les 3ou assign a alue 8the cursor o%4ect: to a cursor !hen you OP-0 the cursor# So the syntax for the OP-0 statement is no! mo&ifie& in PL/SQL Release ;#? to accept a S-L-+$ statement after the (OR clause, as sho!n %elo!* OP-0 cursor)name (OR select)statement/ !here cursor)name is the name of a cursor or cursor aria%le an& select)statement is a SQL S-L-+$ statement# (or strong R-( +,RSOR type cursor aria%les, the structure of the S-L-+$ statement 8the num%er an& &atatypes of the columns: must match or %e compati%le !ith the structure specifie& in the R-$,R0 clause of the type statement# (igure >#G offers an example of the "in& of compati%ility reAuire&# (igure >#G@ contains the full set of compati%ility rules# (igure >#G* +ompati%le R-( +,RSOR ro!type an& S-L-+$ list 'f cursor)name is a cursor aria%le &efine& !ith a !ea" R-( +,RSOR type, you can OP-0 it for any Auery, !ith any structure# 'n the follo!ing example, ' open 8assign a alue to: the cursor aria%le t!ice, !ith t!o &ifferent Aueries* D-+L1R$3P- emp)curtype 'S R-( +,RSOR/ emp)cur ar emp)curtype/ B-7'0 OP-0 emp)cur ar (OR S-L-+$ . (ROM emp/ OP-0 emp)cur ar (OR S-L-+$ employee)i& (ROM emp/ OP-0 emp)cur ar (OR S-L-+$ company)i&, name (ROM company/ -0D/ $hat last open &i&nEt e en ha e anything to &o !ith the employee ta%leI 'f the cursor aria%le has not yet %een assigne& to any cursor o%4ect, the OP-0 (OR statement implicitly creates an o%4ect for the aria%le# 'f at the time of the OP-0 the cursor aria%le alrea&y is pointing to a cursor o%4ect, then OP-0 (OR &oes not create a ne! o%4ect# 'nstea&, it reuses the existing o%4ect an& attaches a ne! Auery to that o%4ect# $he cursor o%4ect is maintaine& separately from the cursor or Auery itself# >#=;#H (etching from +ursor Baria%les 1s mentione& earlier, the syntax for a (-$+2 statement using a cursor aria%le is the same as that for static cursors* (-$+2 Rcursor aria%le nameU '0$O Rrecor& nameU/ (-$+2 Rcursor aria%le nameU '0$O R aria%le nameU, R aria%le nameU ###/
?>

When the cursor aria%le !as &eclare& !ith a strong R-( +,RSOR type, the PL/SQL compiler ma"es sure that the &ata structure8s: liste& after the '0$O "ey!or& are compati%le !ith the structure of the Auery associate& !ith cursor aria%le# >#=;#H#= Strong an& !ea" R-( +,RSOR types 'f the cursor aria%le is of the !ea" R-( +,RSOR type, the PL/SQL compiler cannot perform the same "in& of chec"# Such a cursor aria%le can (-$+2 into any &ata structures, %ecause the R-( +,RSOR type it is not i&entifie& !ith a ro!type at the time of &eclaration# 1t compile time, there is no !ay to "no! !hich cursor o%4ect 8an& associate& SQL statement: !ill %e assigne& to that aria%le# +onseAuently, the chec" for compati%ility must happen at run time, !hen the (-$+2 is a%out to %e execute&# 1t this point, if the Auery an& the '0$O clause &o not structurally match 8an& PL/SQL !ill use implicit con ersions if necessary an& possi%le:, then the PL/SQL runtime engine !ill raise the pre&efine& )M'SM1$+2 exception# >#=;#H#; 2an&ling the )M'SM1$+2 exception Before PL/SQL actually performs its (-$+2, it chec"s for compati%ility# 1s a result, you can trap the )M'SM1$+2 exception an& attempt to (-$+2 from the cursor aria%le using a &ifferent '0$O clause 99 an& you !ill not ha e s"ippe& any ro!s in the result set# - en though you are executing a secon& (-$+2 statement in your program, you !ill still retrie e the first ro! in the result set of the cursor o%4ectEs Auery# $his functionality comes in especially han&y for !ea" R-( +,RSOR types# 'n the follo!ing example, a centraliCe& real estate &ata%ase stores information a%out properties in a ariety of ta%les, one for homes, another for commercial properties, etc# $here is also a single, central ta%le !hich stores an a&&ress an& a %uil&ing type 8home, commercial, etc#:# ' use a single proce&ure to open a !ea" R-( +,RSOR aria%le for the appropriate ta%le, %ase& on the street a&&ress# -ach in&i i&ual real estate office can then call that proce&ure to scan through the matching properties* = Define my !ea" R-( +,RSOR type* ; $3P- %uil&ing)curtype 'S R-( +,RSOR/ ? +reate the proce&ure# 0otice that the mo&e of the cursor aria%le parameter is '0 O,$* G PRO+-D,R- open)site)list 5 8a&&ress)in '0 B1R+21R;, 6 site)cur)inout '0 O,$ %uil&ing)curtype: J 'S 8 home)type +O0S$10$ '0$-7-R *6 =/ 9 commercial)type +O0S$10$ '0$-7-R *6 ;/
10 11

/. 1 static cursor to get %uil&ing type# ./


?J

12 13 14 15 16

+,RSOR site)type)cur 'S S-L-+$ site)type (ROM property)master W2-R- a&&ress 6 a&&ress)in/ site)type)rec site)type)curF/

=JB-7'0 18 /. 7et the %uil&ing type for this a&&ress# ./ 19 OP-0 site)type)cur/ 20 (-$+2 site)type)cur '0$O site)type)rec/ 21 +LOS- site)type)cur/
22 23 24 25 26 27 28 29 30 31

/. 0o! use the site type to select from the right ta%le#./ '( site)type)rec#site)type 6 home)type $2-0 /. ,se the home properties ta%le# ./ OP-0 site)cur)inout (OR S-L-+$ . (ROM home)properties W2-R- a&&ress L'S- EFE OO a&&ress)in OO EFE/

-LS'( site)type)rec#site)type 6 commercial)type 32 $2-0 33 /. ,se the commercial properties ta%le# ./ 34 OP-0 site)cur)inout (OR 35 S-L-+$ . (ROM commercial)properties 36 W2-R- a&&ress L'S- EFE OO a&&ress)in OO EFE/ 37 -0D '(/ ?K-0D open)site)list/ ?L0o! that ' ha e my open proce&ure, ' can use it to scan properties# 'n the follo!ing example, ' pass in the a&&ress an& then try to fetch from the cursor, assuming a home property# 'f the a&&ress actually i&entifies a commercial property, PL/SQL !ill raise the )M'SM1$+2 exception 8incompati%le recor& structures:# $he exception section then fetches again, this time into a commercial %uil&ing recor&, an& the scan is complete#M;N M;N $he @prompt@ an& @sho!@ programs reference& in the example interact !ith users an& are not &ocumente& here# D-+L1R/. Declare a cursor aria%le# ./ %uil&ing)cur ar %uil&ing)curtype/ /. Define recor& structures for t!o &ifferent ta%les# ./ home)rec home)propertiesF/ commercial)rec commercial)propertiesF/ B-7'0 /. 7et the a&&ress from the user# ./ prompt)for)a&&ress 8a&&ress)string:/
?K

/. 1ssign a Auery to the cursor aria%le %ase& on the a&&ress# ./ open)site)list 8a&&ress)string, %uil&ing)cur ar:/ /. 7i e it a tryI (etch a ro! into the home recor&# ./ (-$+2 %uil&ing)cur ar '0$O home)rec/ /. 'f ' got here, the site !as a home, so &isplay it# ./ sho!)home)site 8home)rec:/ -D+-P$'O0 /. 'f the first recor& !as not a home### ./ W2-0 )M'SM1$+2 $2-0 /. (etch that same =st ro! into the commercial recor&# ./ (-$+2 %uil&ing)cur ar '0$O commercial)rec/ /. Sho! the commercial site info# ./ sho!)commercial)site 8commercial)rec:/ -0D/

>#=;#> Rules for +ursor Baria%les $his section examines in more &etail the rules an& issues regar&ing the use of cursor aria%les in your programs# $his inclu&es ro!type matching rules, cursor aria%le aliases, an& scoping issues# Remem%er that the cursor aria%le is a reference to a cursor o%4ect or Auery in the &ata%ase# 't is not the o%4ect itself# 1 cursor aria%le is sai& to @refer to a gi en Auery@ if either of the follo!ing is true* 1n OP-0 statement (OR that Auery !as execute& !ith the cursor aria%le# 1 cursor aria%le !as assigne& a alue from another cursor aria%le that refers to that Auery# 3ou can perform assignment operations !ith cursor aria%les an& also pass these aria%les as arguments to proce&ures an& functions# 'n or&er to perform such actions %et!een cursor aria%les 8an& to %in& a cursor aria%le to a parameter:, the &ifferent cursor aria%les must follo! a set of compile9time an& runtime ro!type matching rules# >#=;#>#= +ompile9time ro!type matching rules $hese are the rules that PL/SQL follo!s at compile9time* $!o cursor aria%les 8inclu&ing proce&ure parameters: are compati%le for assignments an& argument passing if any of the follo!ing are true* Both aria%les 8or parameters: are of a strong R-( +,RSOR type !ith
?L

the same Rro!type)nameU# Both aria%les 8or parameters: are of some !ea" R-( +,RSOR type, regar&less of the Rro!type)nameU# One aria%le 8parameter: is of any strong R-( +,RSOR type, an& the other is of any !ea" R-( +,RSOR type# 1 cursor aria%le 8parameter: of a strong R-( +,RSOR type may %e OP-0 (OR a Auery that returns a ro!type !hich is structurally eAual to the Rro!type)nameU in the original type &eclaration# 1 cursor aria%le 8parameter: of a !ea" R-( +,RSOR type may %e OP-0 (OR any Auery# $he (-$+2 from such a aria%le is allo!e& '0$O any list of aria%les or recor& structure# 'n other !or&s, if either of the cursor aria%les are of the !ea" R-( +,RSOR type, then the PL/SQL compiler cannot really ali&ate !hether the t!o &ifferent cursor aria%les !ill %e compati%le# $hat !ill happen at runtime/ the rules are co ere& in the next section# >#=;#>#; Run9time ro!type matching rules $hese are the rules that PL/SQL follo!s at run time* 1 cursor aria%le 8parameter: of a !ea" R-( +,RSOR type may %e ma&e to refer to a Auery of any ro!type regar&less of the Auery or cursor o%4ect to !hich it may ha e referre& earlier# 1 cursor aria%le 8parameter: of a strong R-( +,RSOR type may %e ma&e to refer only to a Auery !hich matches structurally the Rro!type)nameU of the R-$,R0 clause of the R-( +,RSOR type &eclaration# $!o recor&s 8or lists of aria%les: are consi&ere& structurally matching !ith implicit con ersions if %oth of the follo!ing are true* $he num%er of fiel&s is the same in %oth recor&s 8lists:# (or each fiel& in one recor& 8or aria%le on one list:, a correspon&ing fiel& in the secon& list 8or aria%le in secon& list: has the same PL/SQL &atatype, or one !hich can %e con erte& implicitly %y PL/SQL to match the first# (or a cursor aria%le 8parameter: use& in a (-$+2 statement, the Auery associate& !ith the cursor aria%le must structurally match !ith implicit con ersions the recor& or list of aria%les of the '0$O clause of the (-$+2 statement# $his is, %y the !ay, the same rule use& for static cursors# >#=;#>#? +ursor aria%le aliases 'f you assign one cursor aria%le to another cursor aria%le, those t!o cursor aria%les %ecome aliases for the same cursor o%4ect# $hey share the reference to the cursor
G<

o%4ect 8result set of the cursorEs Auery:# 1n action ta"en against the cursor o%4ect through one aria%le is also a aila%le to an& reflecte& in the other aria%le# $he follo!ing anonymous %loc" illustrates the !ay cursor aliases !or"* = D-+L1R; $3P- cur ar)type 'S R-( +,RSOR/ ? cur ar= cur ar)type/ G cur ar; cur ar)type/ H story fairy)talesF/ > B-7'0 J /. 1ssign cursor o%4ect to cur ar=# ./ K OP-0 cur ar= (OR S-L-+$ . (ROM fairy)tales/ L =< /. 1ssign same cursor o%4ect to cur ar;# ./ == cur ar; *6 cur ar=/ =; =? /. (etch first recor& from cur ar=# ./ =G (-$+2 cur ar= '0$O story/ =H => /. (etch secon& recor& from cur ar;# ./ =J (-$+2 cur ar; '0$O story/ =K =L /. +lose the cursor o%4ect %y referencing cur ar;# ./ ;< +LOS- cur ar;/ ;= ;; /. $his statement raises '0B1L'D)+,RSOR exceptionI ./ ;? (-$+2 cur ar= '0$O story/ ;G -0D/ $he follo!ing ta%le is an explanation of cursor aria%le actions#
Lines1ction=9HDeclare my !ea" R-( +,RSOR type an& cursor aria%le through line H#K+reates a cursor o%4ect an& assigns it to cur ar=#==1ssigns that same cursor o%4ect to the secon& cursor aria%le, cur ar;#=G(etches the first recor& using the cur ar= aria%le#=J(etches the secon& recor& using the cur ar; aria%le# 80otice that it &oesnEt matter !hich of the t!o aria%les you use# $he pointer to the current recor& resi&es !ith the cursor o%4ect, not any particular aria%le#:;<+loses the cursor o%4ect referencing cur ar;#;?Raises the '0B1L'D)+,RSOR exception !hen ' try to fetch again from the cursor o%4ect# 8When ' close& the cursor through cur ar;, it also close& it as far as cur ar= !as concerne&#:1ny change of state in a cursor o%4ect !ill %e seen through any

cursor aria%le !hich is an alias to that cursor o%4ect# >#=;#>#G Scope of cursor o%4ect $he scope of a cursor aria%le is the same as that of a static cursor* the PL/SQL %loc" in !hich the aria%le is &eclare& 8unless &eclare& in a pac"age, !hich ma"es the aria%le glo%ally accessi%le:# $he scope of the cursor o%4ect to !hich a cursor aria%le is assigne&, ho!e er, is a &ifferent matter#
G=

Once an OP-0 (OR creates a cursor o%4ect, that cursor o%4ect remains accessi%le as long as at least one acti e cursor aria%le refers to that cursor o%4ect# $his means that you can create a cursor o%4ect in one scope 8PL/SQL %loc": an& assign it to a cursor aria%le# $hen, %y assigning that cursor aria%le to another cursor aria%le !ith a &ifferent scope, the cursor o%4ect remains accessi%le e en if the original cursor aria%le has gone out of scope# 'n the follo!ing example ' use neste& %loc"s to &emonstrate ho! the cursor o%4ect can persist outsi&e of the scope in !hich it !as originally create&* D-+L1R/. Define !ea" R-( +,RSOR type, cursor aria%le an& local aria%le ./ $3P- cur ar)type 'S R-( +,RSOR/ cur ar= cur ar)type/ &o)you)get)it B1R+21R;8=<<:/ B-7'0 /. OO 0este& %loc" !hich creates the cursor o%4ect an& OO assigns it to the cur ar= cursor aria%le# ./ D-+L1Rcur ar; cur ar)type/ B-7'0 OP-0 cur ar; (OR S-L-+$ punch)line (ROM 4o"es/ cur ar= *6 cur ar;/ -0D/ /. OO $he cur ar; cursor aria%le is no longer acti e, OO %ut @the %aton@ has %een passe& to cur ar=, !hich OO &oes exist in the enclosing %loc"# ' can therefore OO fetch from the cursor o%4ect, through this other OO cursor aria%le# ./ (-$+2 cur ar= '0$O &o)you)get)it/ -0D/ 6.82.> Passing Cursor ;aria<les as ?rguments 3ou can pass a cursor aria%le as an argument in a call to a proce&ure or function# When you use a cursor aria%le in the parameter list of a program, you nee& to specify the mo&e of the parameter an& the &atatype 8the R-( +,RSOR type:# >#=;#J#= '&entifying the R-( +,RSOR type 'n your program hea&er, you must i&entify the R-( +,RSOR type of your cursor aria%le parameter# $o &o this, that cursor type must alrea&y %e &efine&#
G;

'f you are creating a local mo&ule !ithin another program 8see +hapter =H for more information a%out local mo&ules:, then you can also &efine the cursor type in the same program# 't !ill then %e a aila%le for the parameter# $his approach is sho!n %elo!* D-+L1R/. Define the R-( +,RSOR type# ./ $3P- cur ar)type 'S R-( +,RSOR R-$,R0 companyF/ /. Reference it in the parameter list# ./ PRO+-D,R- open)Auery 8cur ar)out O,$ cur ar)type: 'S local)cur cur ar)type/ B-7'0 OP-0 local)cur (OR S-L-+$ . (ROM company/ cur ar)out *6 local)cur/ -0D/ B-7'0 ### -0D/ 'f you are creating a stan&alone proce&ure or function, then the only !ay you can reference a pre9existing R-( +,RSOR type is %y placing that type statement in a pac"age# 1ll aria%les &eclare& in the specification of a pac"age act as glo%als !ithin your session, so you can then reference this cursor type using the &ot notation as sho!n %elo!* = +reate the pac"age !ith a R-( +,RSOR type &eclaration* ; P1+S17- company ? 'S 4 /. Define the R-( +,RSOR type# ./ 5 $3P- cur ar)type 'S R-( +,RSOR R-$,R0 companyF/ > -0D pac"age/ J 'n a stan&alone proce&ure, reference the R-( +,RSOR type %y prefacing the name of the cursor type !ith the name of the pac"age* K PRO+-D,R- open)company 8cur ar)out O,$ company#cur ar)type: 'S L B-7'0 10 ### ==-0D/ See +hapter => for more information on this feature# >#=;#J#; Setting the parameter mo&e 5ust li"e other parameters, a cursor aria%le argument can ha e one of the follo!ing three mo&es*
G?

'0 +an only %e rea& %y program O,$ +an only %e !ritten to %y program '0 O,$ Rea&/!rite in program Remem%er that the alue of a cursor aria%le is the reference to the cursor o%4ect an& not the state of the cursor o%4ect# 'n other !or&s, the alue of a cursor aria%le &oes not change after you fetch from or close a cursor# Only t!o operations, in fact, may change the alue of a cursor aria%le change, that is, the cursor o%4ect to !hich the aria%le points* 1n assignment to the cursor aria%le 1n OP-0 (OR statement 'f the cursor aria%le alrea&y pointe& to a cursor o%4ect, then the OP-0 (OR !oul&nEt actually change the reference# 't !oul& simply change the Auery associate& !ith the o%4ect# $he (-$+2 an& +LOS- operations affect the state of the cursor o%4ect, %ut not the reference to the cursor o%4ect itself, !hich is the alue of the cursor aria%le# 2ere is an example of a program !hich has cursor aria%les as parameters* PRO+-D,R- assign)cur ar 8ol&)cur ar)in '0 company#cur ar)type, ne!)cur ar)out O,$ company#cur ar)type: 'S B-7'0 ne!)cur ar)out *6 ol&)cur ar)in/ -0D/ $his proce&ure copies the ol& company cursor aria%le to the ne! aria%le# $he first parameter is an '0 parameter %ecause it appears only on the right9han& si&e of the assignment# $he secon& parameter must %e an O,$ 8or '0 O,$: parameter, %ecause its alue is change& insi&e the proce&ure# 0otice that the cur ar)type is &efine& !ithin the company pac"age# >#=;#K +ursor Baria%le Restrictions +ursor aria%les are su%4ect to the follo!ing restrictions/ Oracle may remo e some of these in future releases# +ursor aria%les cannot %e &eclare& in a pac"age since they &o not ha e a persistent state#
GG

3ou cannot use RP+s 8Remote Proce&ure +alls: to pass cursor aria%les from one ser er to another# 'f you pass a cursor aria%le as a %in& or host aria%le to PL/SQL, you !ill not %e a%le to fetch from it from !ithin the ser er unless you also open it in that same ser er call# $he Auery you associate !ith a cursor aria%le in an OP-09(OR statement cannot use the (OR ,PD1$- clause# 3ou cannot test for cursor aria%le eAuality, ineAuality, or nullity using comparison operators# 3ou cannot assign 0,LLs to a cursor aria%le# Data%ase columns cannot store cursor aria%le alues# 3ou !ill not %e a%le to use R-( +,RSOR types to specify column types in statements to +R-1$$1BL-s or +R-1$- B'-Ws# $he elements in a neste& ta%le, in&ex9%y ta%le, or aria%le array 8B1RR13: cannot store the alues of cursor aria%les# 3ou !ill not %e a%le to use R-( +,RSOR types to specify the element type of a collection# +ursor aria%les cannot %e use& !ith &ynamic SQL 8through use of the DBMS)SQL pac"age:# >#=? Wor"ing !ith +ursors $he follo!ing sections offer some practical applications of cursors# $hey are also &esigne& to %e programs you can put to use in your o!n en ironments !ith a fe! changes# $he follo!ing files on the companion &is" offer a&&itional examples* arcurs#&oc -xplanation of ho! to emulate a cursor aria%le !ith local mo&ules unAuein#&oc -xplanation of ho! to guarantee uniAue entry !ith cursors unAuein#ff +o&e reAuire& to guarantee uniAue entry !ith cursors >#=?#= Bali&ating (oreign Sey -ntry !ith +ursors 1 hefty percentage of our co&e can %e ta"en up !ith ali&ating the entry or selection of foreign "eys# +onsi&er the example of an application !hich maintains companies an& employees of that company# On the employee maintenance screen, ' !ant to let my user enter the name or partial name of the company that employs a person# 'f the user has i&entifie& a uniAue company, the form &isplays that name an& stores the company 'D on the null can as# 'f the userEs entry fin&s more than one match, a message is
GH

&isplaye&# 'f no matches are foun&, the entry is re4ecte&# 2o! shoul& ' implement this reAuirementT Well, the first thing that comes to the min&s of many programmers is the follo!ing* ,se a cursor !hich, !ith a single fetch, employs the +O,0$ %uilt9in to compute the total num%er of companies that match the enemy# $his is, perhaps, the most o% ious an& &irect solution to the reAuirement 99 !hen it is phrase& as follo!s* $o fin& out if the userEs entry has more than one match, count up 4ust ho! many matches there are# >#=?#=#= 'nefficiency of group functions in cursors $here are, ho!e er, t!o serious pro%lems !ith using the +O,0$ group function in my cursor*
$he cursor &oes far too much !or" on my %ehalf# By using +O,0$, the

cursor must scan through all recor&s 8or, ' hope, those i&entifie& %y the in&ex: an& count up the total num%er of matching recor&s# 3et, all ' really nee& to "no! is !hether more than one company matche& the entry# $he performance penalty on this +O,0$ coul& %e se ere if the Auery goes out o er a net!or" or if the userEs entry matches many of the recor&s# What if a user entere& a percent sign 8F:T 1ll recor&s !oul& then match# 1n application shoul& ne er punish a user for poorly thought9out &ata entry#
$he cursor &oes not &o enough for me# 'f the +O,0$9%ase& Auery &i& return a

alue of =, ' !oul& still ha e to go %ac" to the company ta%le an& S-L-+$ the 'D for that company !ith another cursor# 1s a result, ' !oul& ha e co&e& the same Auery t!ice# $his re&un&ancy intro&uces maintenance an& performance issues# 3ou shoul& use +O,0$ only !hen you nee& to "no! or &isplay the total num%er of matches for the userEs entry# 'n this scenario, ' &onEt really nee& that total/ ' nee& only to "no! if the total is greater than one 8i#e#, if there is more than one match:# ' can o%tain this "no!le&ge in a much more efficient an& straightfor!ar& manner# >#=?#=#; ,sing multiple fetches more efficiently ,se a cursor that, !ith multiple fetches, &etermines if there are at least t!o companies that match the entry# $his approach ta"es a %it more sophistication an& thought, %ut is al!ays a %etter performer an& offers more flexi%ility to programmers# $o employ the multiple9fetch techniAue, ta"e the follo!ing steps* = Declare a cursor !hich returns the company)i& of all companies that match the alue in the item* ; +,RSOR company)cur ? 'S 4 S-L-+$ company)i&
G>

5 6

(ROM company W2-R- company)name L'S- *company#company)name OO EFE/

J (etch t!ice against this cursor# 'f ' can fetch t!ice successfully 8company)cur F0O$(O,0D is (1LS- %oth times:, that means that there is more than one match for the company name# 'f ' can fetch only once %efore the F0O$(O,0D cursor attri%ute returns (1LS-, then ' ha e foun& a uniAue match# 'f the ery first fetch fails, then there is no match for the name# K Because my cursor returns the company)i&, ' &o not ha e to perform another select once ' ha e &etermine& that ' ha e a uniAue match# ' simply use the 'D that !as pro i&e& in the first fetch# $he proce&ure in the follo!ing example supports the foreign "ey ali&ation reAuirements !ith a &ou%le fetch against the cursor 8it is co&e& for Oracle (orms, %ut can %e a&apte& easily to other tool en ironments:* /. (ilename on companion &is"* f" al#fp ./ PRO+-D,R- ali&ate)company 8comp)name)inout '0 O,$ company#company)nameF$3P-, comp)i&)out O,$ company#company)i&F$3P-: 'S /. +ursor as explaine& a%o e ./ +,RSOR company)cur 'S S-L-+$ company)i&, company)name (ROM company W2-R- company)name L'S- comp)name)inout OO EFE/ /. Declare t!o recor&s against the same cursor# ./ company)rec company)curF/ &uplicate)rec company)curF/ B-7'0 /. Open an& perform the first fetch against cursor# ./ OP-0 company)cur/ (-$+2 company)cur '0$O company)rec/ '( company)curF0O$(O,0D $2-0 /. 0ot e en one match for this name# Display message an& re4ect# ./ M-SS178E 0o company foun& !ith name li"e @E OO comp)name)inout OO E@#E:/ +LOS- company)cur/ R1'S- (ORM)$R'77-R)(1'L,R-/ -LS/. OO (oun& one match# 0o! (-$+2 again, %ut this time (-$+2 into the OO &uplicate)rec recor&# $his is 4ust a @place hol&er@# ' &onEt OO nee& to see the contents of the recor&# ' 4ust nee& to "no! if
GJ

OO ' can successfully retrie e another recor& from the cursor# ./ (-$+2 company)cur '0$O &uplicate)rec/ '( company)curF0O$(O,0D $2-0 /. OO (oun& = match, %ut not secon&# ,niAueI 1ssign alues to OO the O,$ parameters an& close the cursor# ./ comp)i&)out *6 company)rec#company)i&/ comp)name)inout *6 company)rec#company)name/ +LOS- company)cur/ -LS/. OO 1t least t!o matches foun& for this name# ' &onEt "no! ho! OO many more an& ' &o not care# Re4ect !ith message# ./ M-SS17- 8E More than one company matches name li"e @E OO comp)name)inout OO E@#E:/ +LOS- company)cur/ R1'S- (ORM)$R'77-R)(1'L,R-/ -0D '(/ -0D '(/ -0D/ +all this proce&ure in the When9Bali&ate9'tem trigger so that any changes to the company name can %e ali&ate&# 2ere is an example of an actual call to ali&ate)company* ali&ate)company 8*employee#company)name, *employee#company)i&:/ 0otice that the first parameter 8the company name: is an '0 O,$ parameter# ' !ant to let the user enter 4ust a part of the name an& let the application figure out if that entry is enough to uniAuely i&entify a company# 'f a single match is foun&, the form replaces the partial entry !ith the full name# ' %elie e strongly that !e shoul& &esign our applications to allo! the user to enter the minimal amount of information necessary to get the 4o% &one# Our applications shoul& %e smart enough to ta"e a& antage of the &um%, %rute strength of our +P,s in or&er to lift some of the %ur&en off the user# >#=?#; Managing a Wor" Queue !ith S-L-+$ (OR ,PD1$1s &iscusse& earlier, a cursor !ith a S-L-+$###(OR ,PD1$- syntax issues a ro!9 le el loc" on each ro! i&entifie& %y the Auery# ' encountere& a ery interesting application of this feature !hile helping a client resol e a pro%lem# $he client offers a &istri%ution pac"age !hich trac"s !arehouse in entory# $he !or"
GK

Aueue screen assigns !arehouse floor pac"ers their next tas"s# $he pac"er opens the screen an& reAuests a tas"# $he screen fin&s the next unassigne& tas" an& assigns it to the pac"er# 1 tas" might in ol e collecting arious pro&ucts together for shipment or returning pro&ucts to the shelf# +ompletion of this tas" can ta"e any!here %et!een one an& ten minutes# When the tas" is complete&, the pac"er !ill commit the changes or close the screen, performing an implicit commit# (or the amount of time it ta"es a pac"er to finish the tas", that recor& must %e tagge& as @assigne&@ so that no other pac"er is gi en the same 4o% to &o# $he first attempt at implementing this feature in ol e& the use of a status flag# Whene er a pac"er !as assigne& a tas", the flag on that tas" !as set to 1SS'70-D an& the tas" recor& committe&# $he screen then exclu&es that tas" from the !or" Aueue# $he pro%lem !ith this approach is that the status ha& to %e committe& to the &ata%ase so that other users coul& see the ne! status# $his commit not only interrupte& the actual transaction in the screen, %ut also create& a num%er of hea&aches* What if the user ne er completes the tas" an& exits the screenT $he form !oul& ha e to &etect this scenario 8an& there are generally many !ays to cancel/exit: an& up&ate the status flag to 1B1'L1BL-, !hich in ol es yet another commit# Worse yet, !hat if the &ata%ase goes &o!n !hile the user is performing the tas"T $hat tas" !ill &isappear from the !or" Aueue until manual inter ention resets the status# My client nee&e& a mechanism %y !hich the tas" coul& %e flagge& as ,01B1'L1BL!ithout ha ing to perform commits, %uil& complex chec"s into the form, an& &e elop crash9reco ery gui&elines# $hey nee&e& a program that !oul& step through each of the open tas"s in priority until it foun& a tas" that !as unassigne&# $he S-L-+$###(OR ,PD1$- construct pro e& to %e the perfect ans!er, in com%ination !ith t!o Aueries against the tas" ta%le 99 an explicit cursor an& an implicit cursor using a (OR ,PD1$clause# $he function in the follo!ing example returns the primary "ey of the next unassigne& tas" using a cursor against the tas" ta%le to loo" through all open tas"s in priority or&er# $he tas"s returne& %y this first cursor inclu&e those !hich are assigne& %ut @in process@ 8an& shoul& therefore not %e assigne& again:# (or each tas" retrie e& from this cursor, the function then tries to o%tain a loc" on that recor& using the (OR ,PD1$-###0OW1'$ clause# 'f the S-L-+$ statement cannot o%tain a loc", it means that tas" is %eing han&le& %y another pac"er# So the function fetches the next tas" an& tries, once again, to o%tain a loc", continuing on in this fashion until a free tas" is foun& or the last tas" is fetche&# 0otice that the next)tas" function &oes not perform any commits, so it &oesnEt ha e to &o any "in& of complicate& clean9up# 't simply reAuests the loc" an& returns the primary "ey for that tas"# $he calling program can then offer this tas" to the pac"er !ho !ill issue the commit, freeing the loc", !hen she or he is &one !ith the tas"* /. (ilename on companion &is"* selup&t#sf ./ (,0+$'O0 next)tas" R-$,R0 tas"#tas")i&F$3PGL

'S /. +ursor of all open tas"s, assigne& an& unassigne& ./ +,RSOR tas")cur 'S S-L-+$ tas")i& (ROM tas" W2-R- tas")status 6 EOP-0E ORD-R B3 tas")priority, &ate)entere& D-S+/ /. $he recor& for the a%o e cursor ./ tas")rec tas")curF/ /. OO 1n exception for error OR19<<<HG* OO @resource %usy an& acAuire !ith 0OW1'$ specifie&@ ./ recor&)loc"e& -D+-P$'O0 PR17M1 -D+-P$'O0)'0'$ 8recor&)loc"e&, 9HG:/ /. OO Baria%les !hich &etermine !hether function shoul& continue OO to loop through the cursorEs recor&s# ./ foun&)unassigne&)tas" BOOL-10 *6 (1LS-/ more)tas"s BOOL-10 *6 $R,-/ /. $he primary "ey of the unassigne& tas" to %e returne& ./ return) alue tas"#tas")i&F$3P- *6 0,LL/ B-7'0 /. Open the cursor an& start up the loop through its recor&s ./ OP-0 tas")cur/ W2'L- 0O$ foun&)unassigne&)tas" 10D more)tas"s LOOP /. (etch the next recor&# 'f nothing foun&, !e are &one ./ (-$+2 tas")cur '0$O tas")rec/ more)tas"s *6 tas")curF(O,0D/ '( more)tas"s $2-0 /. OO 1 recor& !as fetche&# +reate an anonymous %loc" !ithin OO the function so that ' can trap the recor&)loc"e& OO exception an& still stay insi&e the cursor loop# ./ B-7'0 /. $ry to get a loc" on the current tas" ./ S-L-+$ tas")i& '0$O return) alue (ROM tas" W2-R- tas")i& 6 tas")rec#tas")i& (OR ,PD1$- O( tas")i& 0OW1'$/
H<

/. OO 'f ' get to this line then ' !as a%le to get a loc" OO on this particular tas"# 0otice that the S-L-+$ '0$O OO has therefore alrea&y set the functionEs return alue# OO 0o! set the Boolean to stop the loop# ./ foun&)unassigne&)tas" *6 $R,-/ -D+-P$'O0 W2-0 recor&)loc"e& $2-0 /. Recor& !as alrea&y loc"e&, so 4ust "eep on going ./ 0,LL/ -0D/ -0D '(/ -0D LOOP/ /. OO Return the tas" i&# 0otice that if an unassigne& tas" !as 0O$ OO foun&, ' !ill simply return 0,LL per &eclaration &efault# ./ +LOS- tas")cur/ R-$,R0 return) alue/ -D+-P$'O0 /. OO 7eneral exception han&ler for the function* if an error occurre&, OO then close the cursor an& return 0,LL for the tas" 'D# ./ W2-0 O$2-RS $2-0 +LOS- tas")cur/ R-$,R0 0,LL/ -0D/

H=

..........># Pac"ages

Contents=
$he Benefits of Pac"ages O er ie! of Pac"age Structure $he Pac"age Specification $he Pac"age Bo&y Pac"age Data Pac"age 'nitialiCation

1 pac"age is a collection of PL/SQL o%4ects that are pac"age& or groupe& together !ithin a special B-7'09-0D syntax, a "in& of @meta9%loc"#@ 2ere is a partial list of the "in&s of o%4ects you can place in a pac"age* +ursors Baria%les 8scalars, recor&s, ta%les, etc#: +onstants -xception names PL/SQL ta%le an& recor& $3P- statements Proce&ures (unctions Pac"ages are among the least un&erstoo& an& most un&erutiliCe& features of PL/SQL# $hat is a shame, %ecause the pac"age structure is also one of the most useful constructs for %uil&ing !ell9&esigne& PL/SQL9%ase& applications# Pac"ages pro i&e a structure in !hich you can organiCe your mo&ules an& other PL/SQL elements# $hey encourage proper structure& programming techniAues in an en ironment that often %efu&&les the implementation of structure& programming# Oracle +orporation itself uses the pac"age construct to exten& the PL/SQL language# 1ppen&ix +, Built9'n Pac"ages, contains &escriptions of many of these pre&efine& pac"ages# 'n fact, the most %asic operators of the PL/SQL language, such as the Q an& L'S- operators an& the '0S$R function, are all &efine& in a special
H;

pac"age calle& S$10D1RD# 'f Oracle %elie es that pac"ages are the !ay to go !hen it comes to %uil&ing %oth fun&amental an& complex programs, &onEt you thin" that you coul& %enefit from the sameT Pac"ages are, %y nature, highly mo&ular# When you place a program unit into a pac"age you automatically create a context for that program# By collecting relate& PL/SQL elements in a pac"age, you express that relationship in the ery structure of the co&e itself# Pac"ages are often calle& @the poor manEs o%4ects@ %ecause they support some, %ut not all, o%4ect9oriente& rules# (or example, pac"ages allo! you to encapsulate an& a%stract your &ata an& functions# $he PL/SQL pac"age is a &ecepti ely simple, po!erful construct# 3ou can in 4ust a fe! hours learn the %asic elements of pac"age syntax an& rules/ thereEs not all that much to it# 3ou can spen& &ays an& !ee"s, ho!e er, unco ering all the nuances an& implications of the pac"age structure# $his chapter 99 an& the next one fille& !ith examples of pac"ages 99 !ill help you a%sor% the features an& %enefits of the PL/SQL pac"age more rapi&ly# =>#= $he Benefits of Pac"ages Before !e explore all the aspects of !or"ing !ith pac"ages, letEs re ie! some of the most important %enefits of the pac"age* =>#=#= -nforce& 'nformation 2i&ing When you %uil& a pac"age, you &eci&e !hich of the pac"age elements are pu%lic 8can %e reference& outsi&e of the pac"age: an& !hich are pri ate 8a aila%le only !ithin the pac"age itself:# 3ou also can restrict access to the pac"age to only the specification# 'n this !ay, you use the pac"age to hi&e the implementational &etails of your programs# $his is most important !hen you !ant to isolate the most olatile aspects of your application, such as platform &epen&encies, freAuently changing &ata structures, an& temporary !or"aroun&s# =>#=#; O%4ect9Oriente& Design While PL/SQL &oes not yet offer full o%4ect9oriente& capa%ilities, pac"ages &o offer the a%ility to follo! many o%4ect9oriente& &esign principles# $he pac"age gi es &e elopers ery tight control o er ho! the mo&ules an& &ata structures insi&e the pac"age can %e accesse&# 3ou can, therefore, em%e& all the rules a%out an& access to your entities 8!hether they are &ata%ase ta%les or memory9%ase& structures: in the pac"age# Because this is the only !ay to !or" !ith that entity, you ha e in essence create& an a%stracte& an& encapsulate& o%4ect# =>#=#? $op9Do!n Design 1 pac"ageEs specification can %e !ritten %efore its %o&y# 3ou can, in other !or&s, &esign the interface to the co&e hi&&en in the pac"age 8the mo&ules, their names, an& their parameters: %efore you ha e actually implemente& the mo&ules themsel es# $his
H?

feature &o etails nicely !ith top9&o!n &esign, in !hich you mo e from high9le el reAuirements to functional &ecompositions to mo&ule calls# Of course, you can &esign the names of stan&alone mo&ules 4ust as you can the names of pac"ages an& their mo&ules# $he %ig &ifference !ith the pac"age specification is that you can compile it e en !ithout its %o&y# (urthermore, an& most remar"a%ly, programs that call pac"age& mo&ules !ill compile successfully 99 as long as the specification compiles# =>#=#G O%4ect Persistence PL/SQL pac"ages offer the a%ility to implement glo%al &ata in your application en ironment# 7lo%al &ata is information that persists across application components/ it isnEt 4ust local to the current mo&ule# 'f you &esigne& screens !ith SQL.(orms or Oracle (orms, you are pro%a%ly familiar !ith its 7LOB1L aria%les, !hich allo! you to pass information %et!een screens# $hose glo%als ha e their limitations 87LOB1L aria%les are al!ays represente& as fixe&9length +21R aria%les !ith a length of ;HG:, %ut they sure can %e useful# O%4ects &eclare& in a pac"age specification 8that is, isi%le to anyone !ith -D-+,$authority on that pac"age: act as glo%al &ata for all PL/SQL o%4ects in the application# 'f you ha e access to the pac"age, you can mo&ify pac"age aria%les in one mo&ule an& then reference those change& aria%les in another mo&ule# $his &ata persists for the &uration of a user session 8connection to the &ata%ase:# 'f a pac"age& proce&ure opens a cursor, that cursor remains open an& is a aila%le to other pac"age& routines throughout the session# 3ou &o not ha e to explicitly &efine the cursor in each program# 3ou can open it in one mo&ule an& fetch it in another mo&ule# 'n a&&ition, pac"age aria%les can carry &ata across the %oun&aries of transactions, %ecause they are tie& to the session itself an& not to a transaction# =>#=#H Performance 'mpro ement When an o%4ect in a pac"age is reference& for the first time, the entire pac"age 8alrea&y compile& an& ali&ate&: is loa&e& into memory 8the Share& 7lo%al 1rea MS71N of the RDBMS:# 1ll other pac"age elements are there%y ma&e imme&iately a aila%le for future calls to the pac"age# PL/SQL &oes not ha e to "eep retrie ing program elements or &ata from &is" each time a ne! o%4ect is reference&# $his feature is especially important in a &istri%ute& execution en ironment# 3ou may reference pac"ages from &ifferent &ata%ases across a local area or e en a !i&e area net!or"# 3ou !ant to minimiCe the net!or" traffic in ol e& in executing your co&e# Pac"ages also offer performance a& antages on the &e elopment si&e 8!ith potential impact on o erall &ata%ase performance:# $he Oracle RDBMS automatically trac"s the ali&ity of all program o%4ects 8proce&ures, functions, pac"ages: store& in the &ata%ase# 't &etermines !hat other o%4ects that program is &epen&ent on, such as ta%les# 'f a &epen&ent o%4ect such as a ta%leEs structure changes, for example, then all programs that rely on that o%4ect are flagge& as in ali&# $he &ata%ase then automatically recompiles these in ali& programs %efore they are use&#
HG

3ou can limit automatic recompiles %y placing functions an& proce&ures insi&e pac"ages# 'f program 1 calls pac"age& mo&ule B, it &oes so through the pac"ageEs specification# 1s long as the specification of a pac"age& mo&ule &oes not change, any program that calls the mo&ule is not flagge& as in ali& an& !ill not ha e to %e recompile&# $his chapter shoul& pro i&e you !ith all the information an& examples you nee& to put pac"ages to !or" imme&iately in your applications# 'f you are still unsure a%out pac"ages after rea&ing it, try out a couple of small pac"ages# $est those har&9to9 %elie e features li"e glo%al pac"age &ata to pro e to yourself that they really !or" as a& ertise&# -xamine carefully the examples in +hapter =K, O%4ect $ypes# Do !hate er you nee& to &o to incorporate pac"ages into e ery le el of your application, from &ata%ase ser er to client applications#

By Ste en (euerstein X Bill Pri%yl/ 'SB0 =9H>HL;9??H9L-

http*//%oo"s#%ianor#net/Oracle/

%ttp=//:::.comp.dit.ie/<t ierne@/"racle/PLSQL 129Introduction.pd0 %ttp=//:::.comp.dit.ie/<t ierne@/"racle/PLSQL 129Introduction.pd0


HH

Input arguments to cursor 'nput arguments are the alues that are passe& to cursor at the time of opening the cursor# $hese alues are passe& to parameters that are &e IIII http*//sri"anthtechnologies#com/ %oo"s/ora%oo"/ch=K#p&f http*//%a"s#gaC#ru/ora&oc/plsAl/to plsAl#htm http*//pu%li%#%oul&er#i%m#com/in focenter/i&shelp/ ===/in&ex#4spT
H>

topic6/com#i%m#esAlc#&oc/sii9=G9 GG==H#htm http*//pu%li%#%oul&er#i%m#com/in focenter/i&shelp/ ===/in&ex#4spT topic6/com#i%m#esAlc#&oc/sii9=G9 GG==H#htm

HJ

You might also like