Professional Documents
Culture Documents
These are the advantages of PL/SQL. Block Structures: PL SQL consists of blocks of code, which can be nested within each other. Each block forms a unit of a task or a logical module. PL/SQL Blocks can be stored in the database and reused. Procedural Language Capability: PL SQL consists of rocedural language constructs such as conditional statements !if else statements" and loo s like !#$% loo s". Better Performance: PL SQL engine rocesses multi le SQL statements simultaneousl& as a single block, thereb& reducing network traffic. Error Handling: PL/SQL handles errors or e'ce tions effectivel& during the e'ecution of a PL/SQL rogram. $nce an e'ce tion is caught, s ecific actions can be taken de ending u on the t& e of the e'ce tion or it can be dis la&ed to the user with a message.
Miscellaneous eatures
*f the T%+,-.TE statement is issued against a tem orar& table, onl& the session s ecific data is trucated. There is no affect on the data of other sessions. /ata in tem orar& tables is automaticall& delete at the end of the database session, even if it ends abnormall&. *nde'es can be created on tem orar& tables. The content of the inde' and the sco e of the inde' is that same as the database session.
0iews can be created against tem orar& tables and combinations of tem orar& and ermanent tables. Tem orar& tables can have triggers associated with them. E' ort and *m ort utilities can be used to transfer the table definitions, but no data rows are rocessed. There are a number of restrictions related to tem orar& tables but these are version s ecific.
Implicit cursors:
These are created b& default when /2L statements like, *,SE%T, +P/.TE, and /ELETE statements are e'ecuted. The& are also created when a SELE-T statement that returns )ust one row is e'ecuted.
Explicit cursors:
The& must be created when &ou are e'ecuting a SELE-T statement that returns more than one row. Even though the cursor stores multi le records, onl& one record can be rocessed at a time, which is called as current row. 3hen &ou fetch a row the current row osition moves to ne't row. Both im licit and e' licit cursors have the same functionalit&, but the& differ in the wa& the& are accessed.
Implicit Cursors:
3hen &ou e'ecute /2L statements like /ELETE, *,SE%T, +P/.TE and SELE-T statements, im licit statements are created to rocess these statements. $racle rovides few attributes called as im licit cursor attributes to check the status of /2L o erations. The cursor attributes available are 4#$+,/, 4,$T#$+,/, 4%$3-$+,T, and 4*S$PE,.
#or e'am le, 3hen &ou e'ecute *,SE%T, +P/.TE, or /ELETE statements the cursor attributes tell us whether an& rows are affected and how man& have been affected. 3hen a SELE-T... *,T$ statement is e'ecuted in a PL/SQL Block, im licit cursor attributes can be used to find out whether an& row has been returned b& the SELE-T statement. PL/SQL returns an error when no data is selected. The status of the cursor for each of these attributes are defined in the below table. Attributes 4#$+,/
$eturn %alue The return value is T%+E, if the /2L statements like *,SE%T, /ELETE and +P/.TE affect at least one row and if SELE-T 5.*,T$ statement return at least one row. The return value is #.LSE, if /2L statements like *,SE%T, /ELETE and +P/.TE do not affect row and if SELE-T5.*,T$ statement do not return a row.
&'ample SQL4#$+,/
4,$T#$+,/ The return value is #.LSE, if /2L statements like *,SE%T, /ELETE and +P/.TE at least one row and if SELE-T 5.*,T$ statement return at least one row. The return value is T%+E, if a /2L statement like *,SE%T, /ELETE and +P/.TE do not affect even one row and if SELE-T 5.*,T$ statement does not return a row. 4%$3-$+,T %eturn the number of rows affected b& the /2L o erations *,SE%T, /ELETE, +P/.TE, SELE-T
SQL4,$T#$+,/
SQL4%$3-$+,T
#or E'am le1 -onsider the PL/SQL Block that uses im licit cursor attributes as shown below1
DECLARE (a)_)o*+ umbe)(,%& BEGIN "PDATE employee SET +ala)y - +ala)y . !///& I0 S1L2NOT0O"ND T3EN
4bm+_output5put_l6 e(7No e o8 t9e +ala)6e+ *9e)e up4ate47%& ELSI0 S1L20O"ND T3EN (a)_)o*+ :- S1L2ROWCO"NT& 4bm+_output5put_l6 e(7Sala)6e+ 8o) 7 ;; (a)_)o*+ ;; 7employee+ a)e up4ate47%& END I0& END&
*n the above PL/SQL Block, the salaries of all the em lo&ees in the 6em lo&ee7 table are u dated. *f none of the em lo&ee7s salar& are u dated we get a message 8,one of the salaries where u dated8. Else we get a message like for e'am le, 8Salaries for 9::: em lo&ees are u dated8 if there are 9::: rows in 6em lo&ee7 table. htt 1// ls;l(tutorial.com/ ls;l(cursors.htm
&'plicit Cursors
.n e' licit cursor is defined in the declaration section of the PL/SQL Block. *t is created on a SELE-T Statement which returns more than one row. 3e can rovide a suitable name for the cursor. T"e General Synta' for creating a cursor is as given belo(:
C"RSOR cu)+o)_ ame IS +elect_+tateme t& cursor_name A suitable name for the cursor. select_statement A select query which returns
multiple rows.
*n the above e'am le we are creating a cursor 6em =cur7 on a ;uer& which returns the records of all the
em lo&ees with salar& greater than >:::. <ere 6em =tbl7 in the table which contains records of all the em lo&ees. ?" .ccessing the records in the cursor1 $nce the cursor is created in the declaration section we can access the cursor in the e'ecution section of the PL/SQL rogram.
$%
0ETC3 cu)+o)_ ame INTO (a)6able_l6+t&
3hen a cursor is o ened, the first row becomes the current row. 3hen the data is fetched it is co ied to the record or variables and the logical ointer moves to the ne't row and it becomes the current row. $n ever& fetch statement, the ointer moves to the ne't row. *f &ou want to fetch after the last row, the rogram will throw an error. 3hen there is more than one row in a cursor we can use loo s along with e' licit cursor attributes to fetch all the records. Points to remember while fetching a row1 B 3e can fetch the rows in a cursor to a PL/SQL %ecord or a list of variables created in the PL/SQL Block. B *f &ou are fetching a cursor to a PL/SQL %ecord, the record should have the same structure as the cursor. B *f &ou are fetching a cursor to a list of variables, the variables should be listed in the same order in the fetch statement as the columns are resent in the cursor. Aeneral #orm of using an e' licit cursor is1
DECLARE (a)6able+& )eco)4+& c)eate a cu)+o)& BEGIN OPEN cu)+o)& 0ETC3 cu)+o)& p)oce++ t9e )eco)4+& CLOSE cu)+o)& END&
7 ;;
*n the above e'am le, first we are creating a record 6em =rec7 of the same structure as of table 6em =tbl7 in line no ?. 3e can also create a record with a cursor b& re lacing the table name with the cursor name. Second, we are declaring a cursor 6em =cur7 from a select ;uer& in line no @ ( C. Third, we are o ening the cursor in the e'ecution section in line no D. #ourth, we are fetching the cursor to the record in line no E. #ifth, we are dis la&ing the first=name and last=name of the em lo&ee in the record em =rec in line no 9:. Si'th, we are closing the cursor in line no 99.
Attributes 4#$+,/
4,$T#$+,/
4%$3-$+,T
4*S$PE,
$eturn values &'ample T%+E, if fetch statement returns at least one row. -ursor=name4#$+,/ #.LSE, if fetch statement doesn7t return a row. T%+E, , if fetch statement doesn7t -ursor=name4,$T#$+,/ return a row. #.LSE, if fetch statement returns at least one row. The number of rows fetched b& the fetch statement -ursor=name4%$3-$+,T *f no row is returned, the PL/SQL statement returns an error. T%+E, if the cursor is alread& o en in the rogram -ursor=name4*S,.2E #.LSE, if the cursor is not o ened in the rogram.
*n the above e'am le we are using two cursor attributes 4*S$PE, and 4,$T#$+,/. *n line no C, we are using the cursor attribute 4*S$PE, to check if the cursor is o en, if
the condition is true the rogram does not o en the cursor again, it directl& moves to line no E. *n line no 99, we are using the cursor attribute 4,$T#$+,/ to check whether the fetch returned an& row. *f there is no rows found the rogram would e'it, a condition which e'ists when &ou fetch the cursor after the last row, if there is a row found the rogram continues. 3e can use 4#$+,/ in lace of 4,$T#$+,/ and vice versa. *f we do so, we need to reverse the logic of the rogram. So use these attributes in a ro riate instances.
*n the above e'am le, in line no 9: we are using 4#$+,/ to evaluate if the first fetch statement in line no E returned a row, if true the rogram moves into the while loo . *n the loo we use fetch statement again !line no 9>" to rocess the ne't row. *f the fetch statement is not e'ecuted once before the while loo the while condition will return false in the first instance and the while loo is ski ed. *n the loo , before fetching the record again, alwa&s rocess the record retrieved b& the first fetch statement, else &ou will ski the first row.
0OR )eco)4_ ame IN cu+)o)_ ame LOOP p)oce++ t9e )o*555 END LOOP&
Let7s use the above e'am le to learn how to use for loo s in cursors.
!= DECLARE $= C"RSOR emp_cu) IS >= SELECT 86)+t_ ame# la+t_ ame# +ala)y 0ROM emp_tbl& ?= emp_)ec emp_cu)2)o*type& ,= BEGIN @= 0OR emp_)ec 6 +ale+_cu) A= LOOP B= 4bm+_output5put_l6 e(emp_cu)586)+t_ ame ;; 7 7 ;;emp_cu)5la+t_ ame C= ;; 7 7 ;;emp_cu)5+ala)y%& !/= END LOOP& !!=END& !$= E
*n the above e'am le, when the #$% loo is rocessed a record 6em =rec7of structure 6em =cur7 gets created, the cursor is o ened, the rows are fetched to the record 6em =rec7 and the cursor is closed after the last row is rocessed. B& using #$% Loo in &our rogram, &ou can reduce the number of lines in the rogram. *)T&: *n the e'am les given above, we are using backward slash 6/7 at the end of the rogram. This indicates the oracle engine that the PL/SQL rogram has ended and it can begin rocessing the statements.
PL/SQL $ecords
What are records?
%ecords are another t& e of datat& es which oracle allows to be defined as a laceholder. %ecords are com osite datat& es, which means it is a combination of different scalar datat& es like char, varchar, number etc. Each scalar data t& es in the record holds a value. . record can be visualiFed as a row of data. *t can contain all the contents of a row.
Declaring a record:
To declare a record, &ou must first define a com osite datat& eG then declare a record for that t& e. The Aeneral S&nta' to define a com osite datat& e is1
TYPE )eco)4_type_ ame IS RECORD (86)+t_col_ ame colum _4atatype#
+eco 4_col_ ame colum _4atatype# 555%& record_type_name H it is the name of the com osite t& e &ou want to define. first_col_name, second_col_name, etc.,- it is the names the fields/columns within
There are different wa&s &ou can declare the datat& e of the fields. 9" Iou can declare the field in the same wa& as &ou declare the fieds while creating the table. ?" *f a field is based on a column from database table, &ou can define the field=t& e as follows1
col_name table_ ame5colum _ ame2type&
B& declaring the field datat& e in the above method, the datat& e of the column is d&namicall& a lied to the field. This method is useful when &ou are altering the column s ecification of the table, because &ou do not need to change the code again. *)T&: Iou can use also %type to declare variables and constants.
)eco)4_ ame )eco)4_type_ ame&
The Aeneral S&nta' to declare a record of a uer(defined datat& e is1 The following code shows how to declare a record called employee_rec based on a user( defined t& e.
DECLARE TYPE employee_type IS RECORD (employee_64 umbe)(,%# employee_86)+t_ ame (a)c9a)$($,%# employee_la+t_ ame employee5la+t_ ame2type# employee_4ept employee54ept2type%& employee_+ala)y employee5+ala)y2type& employee_)ec employee_type&
*f all the fields of a record are based on the columns of a table, we can declare the record as follows1
)eco)4_ ame table_ ame2ROWTYPE&
The advantages of declaring the record as a %$3TIPE are1 9" Iou do not need to e' licitl& declare variables for all the columns in a table.
?" *f &ou alter the column s ecification in the database table, &ou do not need to u date the code. The disadvantage of declaring the record as a %$3TIPE is1 9" 3hen u create a record as a %$3TIPE, fields will be created for all the columns in the table and memor& will be used to create the datat& e for all the fields. So use %$3TIPE onl& when &ou are using all the columns of the table in the rogram. *)T&: 3hen &ou are creating a record, &ou are )ust creating a datat& e, similar to creating a variable. Iou need to assign values to the record to use them. The following table consolidates the different wa&s in which &ou can define and declare a l/s;l record.
Synta' TIPE record=t& e=name *S %E-$%/ !column=name9 datat& e, column=name? datat& e, ..."G col=name table=name.column=name4t& eG
/&namicall& define the datat& e of a column based on a database column. /eclare a record based on a user(defined t& e. /&namicall& declare a record based on an entire row of a table. Each column in the table corres onds to a field in the record.
record=name table=name4%$3TIPEG
*f &ou used 4%$3TIPE to declare a record, &ou can assign values as shown1
)eco)4_ ame5colum _ ame :- (alue&
*f 4%$3TIPE is used to declare a record then &ou can directl& assign values to the whole record instead of each columns se aratel&. *n this case, &ou must SELE-T all the columns from the table into the record as shown1
SELECT < INTO )eco)4_ ame 0ROM table_ ame FW3ERE clau+eG&
Lets see how we can get values from a record. The Aeneral S&nta' to retrieve a value from a s ecific field into another variable is1
(a)_ ame :- )eco)4_ ame5col_ ame&
The following table consolidates the different wa&s &ou can assign values to and from a record1 Synta' record=name.col=name 1J valueG
+sage To directl& assign a value to a s ecific column of a record. To directl& assign a value to a s ecific column of a record, if the record is declared using 4%$3TIPE.
record=name.column=name 1J valueG
SELE-T col9, col? *,T$ record=name.col=name9, To assign values to each field of a record=name.col=name? #%$2 table=name record from the database table. K3<E%E clauseLG SELE-T M *,T$ record=name #%$2 table=name To assign a value to all fields in the K3<E%E clauseLG record from a database table. variable=name 1J record=name.col=nameG To get a value from a record column and assigning it to a variable.
/- )+T Parameter: The $+T arameters are used to send the $+TP+T from a rocedure or a function. This is a write(onl& arameter i.e, we cannot ass values to $+T aramters while e'ecuting the stored rocedure, but we can assign values to $+T arameter inside the stored rocedure and the calling rogram can recieve this out ut value. The Aeneral s&nta' to create an $+T arameter is
CREATE FOR REPLACEG PROCED"RE p)oc$ (pa)am_ ame O"T 4atatype%
The arameter should be e' licit& declared as $+T arameter. 0- .* )+T Parameter:
The *, $+T arameter allows us to ass values into a rocedure and get out ut values from the rocedure. This arameter is used if the value of the *, arameter can be changed in the calling rogram. B& using *, $+T arameter we can ass values into a arameter and return a value to the calling rogram using the same arameter. But this is ossible onl& if the value assed to the rocedure and out ut value have a same datat& e. This arameter is used if the value of the arameter will be changed in the rocedure. The Aeneral s&nta' to create an *, $+T arameter is
CREATE FOR REPLACEG PROCED"RE p)oc> (pa)am_ ame IN O"T 4atatype%
The below e'am les show how to create stored rocedures using the above three t& es of arameters. E'am le91 +sing .* and )+T parameter: Let7s create a rocedure which gets the name of the em lo&ee when the em lo&ee id is assed.
!= CREATE OR REPLACE PROCED"RE emp_ ame (64 IN N"MBER# emp_ ame O"T N"MBER% $= IS >= BEGIN ?= SELECT 86)+t_ ame INTO emp_ ame ,= 0ROM emp_tbl W3ERE empID - 64& @= END& A= E
3e can call the rocedure 6em =name7 in this wa& from a PL/SQL Block.
!= DECLARE $= empName (a)c9a)($/%& >= C"RSOR 64_cu) SELECT 64 0ROM emp_64+& ?= BEGIN ,= 0OR emp_)ec 6 64_cu) @= LOOP A= emp_ ame(emp_)ec564# empName%& B= 4bm+_output5putl6 e(7T9e employee 7 ;; empName ;; 7 9a+ 64 7 ;; empH)ec564%& C= END LOOP& !/= END& !!= E
*n the above PL/SQL Block *n line no @G we are creating a cursor 6id=cur7 which contains the em lo&ee id.
*n line no NG we are calling the rocedure 6em =name7, we are assing the 6id7 as *, arameter and 6em ,ame7 as $+T arameter. *n line no DG we are dis la&ing the id and the em lo&ee name which we got from the rocedure 6em =name7. E'am le ?1 +sing .* )+T parameter in procedures:
!= CREATE OR REPLACE PROCED"RE emp_+ala)y_6 c)ea+e $= (emp_64 IN emptbl5empID2type# +ala)y_6 c IN O"T emptbl5+ala)y2type% >= IS ?= tmp_+al umbe)& ,= BEGIN @= SELECT +ala)y A= INTO tmp_+al B= 0ROM emp_tbl C= W3ERE empID - emp_64& !/= I0 tmp_+al bet*ee !//// a 4 $//// T3EN !!= +ala)y_6 out :- tmp_+al < !5$& !$= ELSI0 tmp_+al bet*ee $//// a 4 >//// T3EN !>= +ala)y_6 out :- tmp_+al < !5>& !?= ELSI0 tmp_+al = >//// T3EN !,= +ala)y_6 out :- tmp_+al < !5?& !@= END I0& !A= END& !B= E
The below PL/SQL block shows how to e'ecute the above 8em =salar&=increase8 rocedure.
!= DECLARE $= C"RSOR up4ate4_+al 6+ >= SELECT empID#+ala)y ?= 0ROM emp_tbl& ,= p)e_+al umbe)& @= BEGIN A= 0OR emp_)ec IN up4ate4_+al LOOP B= p)e_+al :- emp_)ec5+ala)y& C= emp_+ala)y_6 c)ea+e(emp_)ec5empID# emp_)ec5+ala)y%& !/= 4bm+_output5put_l6 e(7T9e +ala)y o8 7 ;; emp_)ec5empID ;; !!= 7 6 c)ea+e4 8)om 7;; p)e_+al ;; 7 to 7;; emp_)ec5+ala)y%& !$= END LOOP& !>= END& !?= E
&'ception 1andling
*n this section we will discuss about the following, 9" 3hat is E'ce tion <andling. ?" Structure of E'ce tion <andling. @" T& es of E'ce tion <andling.
Aeneral PL/SQL statments can be used in the E'ce tion Block. 3hen an e'ce tion is raised, $racle searches for an a ro riate e'ce tion handler in the e'ce tion section. #or e'am le in the above e'am le, if the error raised is 8e'=name9 8, then the error is handled according to the statements under it. Since, it is not ossible to determine all the ossible runtime errors during testing fo the code, the 83<E, $thers8 e'ce tion is used to manage the e'ce tions that are not e' licitl& handled. $nl& one e'ce tion can be raised in a Block and the control does not return to the E'ecution Section after the error is handled. *f there are nested PL/SQL blocks like this.
DELCARE Decla)at6o BEGIN +ect6o
DECLARE Decla)at6o +ect6o BEGIN EIecut6o +ect6o EDCEPTION EIcept6o +ect6o END& EDCEPTION EIcept6o +ect6o END&
*n the above case, if the e'ce tion is raised in the inner block it should be handled in the e'ce tion block of the inner PL/SQL block else the control moves to the E'ce tion block of the ne't u er PL/SQL Block. *f none of the blocks handle the e'ce tion the rogram ends abru tl& with an error.
-) ".pes o+ Exception,
There are @ t& es of E'ce tions. a" ,amed S&stem E'ce tions b" +nnamed S&stem E'ce tions c" +ser(defined E'ce tions
*,0.L*/=-+%S$%
3hen &ou erform an invalid o eration on a cursor like closing a cursor, fetch data from a cursor that is not o ened.
,$=/.T.=#$+,/
3hen a SELE-T...*,T$ clause does not return an& row from a table. 3hen &ou SELE-T or fetch more than one row into a record or variable. 3hen &ou attem t to divide a number b& Fero.
T$$=2.,I=%$3S
OE%$=/*0*/E
or &'ample: Su ose a ,$=/.T.=#$+,/ e'ce tion is raised in a roc, we can write a code to handle the e'ce tion as given below.
BEGIN EIecut6o +ect6o EDCEPTION W3EN NO_DATA_0O"ND T3EN 4bm+_output5put_l6 e (7A SELECT555INTO 464 END&
ot )etu)
a y )o*57%&
EDCEPTION_INIT (eIcept6o _ ame# E))_co4e%& BEGIN EIecut6o +ect6o EDCEPTION W3EN eIcept6o _ ame T3EN 9a 4le t9e eIcept6o END&
or &'ample: Lets consider the roduct table and order=items table from s;l )oins. <ere roduct=id is a rimar& ke& in roduct table and a foreign ke& in order=items table. *f we tr& to delete a roduct=id from the roduct table when it has child records in order=id table an e'ce tion will be thrown with oracle code number (??E?. 3e can rovide a name to this e'ce tion and handle it in the e'ce tion section as given below.
DECLARE C96l4_)ec_eIcept6o EDCEPTION& PRAGMA EDCEPTION_INIT (C96l4_)ec_eIcept6o # H$$C$%& BEGIN Delete 0ROM p)o4uct *9e)e p)o4uct_64- !/?& EDCEPTION W3EN C96l4_)ec_eIcept6o T3EN Dbm+_output5put_l6 e(7C96l4 )eco)4+ a)e p)e+e t 8o) t96+ p)o4uct_6457%& END& E
c) User0de+ined Exceptions
. art from s&tem e'ce tions we can e' licit& define e'ce tions based on business rules. These are known as user(defined e'ce tions. Ste s to be followed to use user(defined e'ce tions1 Q The& should be e' licitl& declared in the declaration section. Q The& should be e' licitl& raised in the E'ecution Section. Q The& should be handled b& referencing the user(defined e'ce tion name in the e'ce tion section. or &'ample: Lets consider the roduct table and order=items table from s;l )oins to e' lain user(defined e'ce tion. Lets create a business rule that if the total no of units of an& articular roduct sold is more than ?:, then it is a huge ;uantit& and a s ecial discount should be rovided.
DECLARE 9uJe_Kua t6ty EDCEPTION& C"RSOR p)o4uct_Kua t6ty 6+ SELECT p5p)o4uct_ ame a+ ame# +um(o5total_u 6t+% a+ u 6t+ 0ROM o)4e)_tem+ o# p)o4uct p W3ERE o5p)o4uct_64 - p5p)o4uct_64&
Kua t6ty o)4e)_tem+5total_u 6t+2type& up_l6m6t CONSTANT o)4e)_tem+5total_u 6t+2type :me++aJe 'ARC3AR$(,/%& BEGIN 0OR p)o4uct_)ec 6 p)o4uct_Kua t6ty LOOP Kua t6ty :- p)o4uct_)ec5u 6t+& I0 Kua t6ty = up_l6m6t T3EN me++aJe :- 7T9e umbe) o8 u 6t+ o8 p)o4uct 7 ;; 7 6+ mo)e t9a $/5 Spec6al 46+cou p)o(64e45 Re+t o8 t9e )eco)4+ a)e +L6ppe45 7 RAISE 9uJe_Kua t6ty& ELSI0 Kua t6ty M up_l6m6t T3EN (_me++aJe:- 7T9e umbe) o8 u 6t 6+ belo* t9e END I0& 4bm+_output5put_l6 e (me++aJe%& END LOOP& EDCEPTION W3EN 9uJe_Kua t6ty T3EN 4bm+_output5put_l6 e (me++aJe%& END& E
$/&
46+cou t l6m6t57&
$AI&E1A
LICA"I2/1E$$2$ 3 )
$A.S&3APPL.CAT.)*3&$$)$ is a built(in rocedure in oracle which is used to dis la& the user(defined error messages along with the error number whose range is in between (?:::: and (?:EEE. 3henever a message is dis la&ed using %.*SE=.PPL*-.T*$,=E%%$%, all revious transactions which are not committed within the PL/SQL Block are rolled back automaticall& !i.e. change due to *,SE%T, +P/.TE, or /ELETE statements". %.*SE=.PPL*-.T*$,=E%%$% raises an e'ce tion but does not handle it. %.*SE=.PPL*-.T*$,=E%%$% is used for the following reasons, a" to create a uni;ue id for an user(defined e'ce tion. b" to make the user(defined e'ce tion look like an $racle error. The Aeneral S&nta' to use this rocedure is1
RAISE_APPLICATION_ERROR (error_number, error_message);
Q The Error number must be between (?:::: and (?:EEE Q The Error=message is the message &ou want to dis la& when the error occurs. Ste s to be folowed to use %.*SE=.PPL*-.T*$,=E%%$% rocedure1 9. /eclare a user(defined e'ce tion in the declaration section. ?. %aise the user(defined e'ce tion based on a s ecific business rule in the e'ecution section.
@. #inall&, catch the e'ce tion and link the e'ce tion to a user(defined error number in %.*SE=.PPL*-.T*$,=E%%$%. +sing the above e'am le we can dis la& a error message using %.*SE=.PPL*-.T*$,=E%%$%.
DECLARE 9uJe_Kua t6ty EDCEPTION& C"RSOR p)o4uct_Kua t6ty 6+ SELECT p5p)o4uct_ ame a+ ame# +um(o5total_u 6t+% a+ u 6t+ 0ROM o)4e)_tem+ o# p)o4uct p W3ERE o5p)o4uct_64 - p5p)o4uct_64& Kua t6ty o)4e)_tem+5total_u 6t+2type& up_l6m6t CONSTANT o)4e)_tem+5total_u 6t+2type :- $/& me++aJe 'ARC3AR$(,/%& BEGIN 0OR p)o4uct_)ec 6 p)o4uct_Kua t6ty LOOP Kua t6ty :- p)o4uct_)ec5u 6t+& I0 Kua t6ty = up_l6m6t T3EN RAISE 9uJe_Kua t6ty& ELSI0 Kua t6ty M up_l6m6t T3EN (_me++aJe:- 7T9e umbe) o8 u 6t 6+ belo* t9e 46+cou t l6m6t57& END I0& Dbm+_output5put_l6 e (me++aJe%& END LOOP& EDCEPTION W3EN 9uJe_Kua t6ty T3EN )a6+e_appl6cat6o _e))o)(H$!//# 7T9e umbe) o8 u 6t 6+ abo(e t9e 46+cou t l6m6t57%& END& E