Professional Documents
Culture Documents
lntroduction
ln general, an apprication can be thought
of as a set of programs or
modules that communicate with each "other.
Tl" ..r"irnication consists
of messagel passed between the modures. rn
orderlolrr.n a system to
work reliably, the message system must have.uioin
plperties:
I Reliability given message shourd be guaranteed to
{ be derivered
aqired recipient or iecipients, anj the message shourd
lllf
delivered only once.
be
ENQUEUE Operation
ENQUEUE insefts a message into a given queue. Along with the messaBe
data itself (which can be either an object type or RAW data) is the routing
information, which specifies how the message is to be inserted and who
the intended recipients are. The routing information can optionally include
the following:
DEQUEUE Operation
DEQUEUE retrievei a from a specified queue. rf there are no
lnessage
messages/ then DEeUEUE wi1 brock untir
, r"ri"g" i, ,"iriuu"o, or untir
the operation rimes out. DEeUEUE has the foilowifrg
opaioni,
Queues
There are two types of queues: user queues and exception queues. A user
queue contains normal messages. lf a message expires (is not dequeued
before the expiration date), it is moved to an exception queue, which
contains messages that had an error.
Queue Tables
Queues are stored in a queue table. A queue table by default contains one
exception queue, although it can contain more if desired. Queue tables are
created first, then the queues within them are enabled for ENQUEUE and
DEQUEUE operations.
Agents
An agent is a user of a queue. A producing agent (or producer) is someone
who inserts messages into a queue, and a consuming agent(or consumer) is
someone who dequeues messages. The same agent can act as both a
producer and a consumer.
Time Manager
The time manager is an Oracle background process that is used to manage
message expiration, along with the delay and retry operations. lf this
process is not started, then these features are not available.
NOTE
ln order to start the time manager, set the
AQ_TM_PROCESSES i n it.ora parameter to
1. The default value is 0, indicating that no
time manager processes should be started. A
value of 1 indicates that one process should
be started. As of Oracle] release 8.0.3, there
can be at most one time manager process.
Queue Operations
The DBMS_AQ package implements some supporting types as ',vell as the
ENQUEUE and DEQUEUE operations. The adnrinistration operations for
queues (creating and droppinB queues and queue tables, for example) are
implemented in the DBMS_AQADM package.
Supporting Types
DBMS_AQ defines several supporting types, which are used for subsequent
calls. The types are listed in Table 17-2, and described in the following
sections. These types consist of index-by tables, and PL/SQL records.
SYS.AQ$_AGENT
This type identifies an agent, which can serve as a producer or consumer of
a queue. lt is implemented as a PL/SQL record, and defined as
name VARCHAR2(30),
address VARCHAR2(30),
protocol NUMBER);
where the name field contains the name of the agent. As of Oracle8
Release 8.0, the address and protocol fields are unused and are reserved
for future use.
AQ$_RECTPTENT_L|ST_T
This type is a list of agents that can receive a message. lt is paft of the
message properties, and thus is used for both the ENQUEUE and
Chapter l7: Oracle Advanced Queuing 657
MESSAGE_PROPERTIES T
The MESSAGE-PROPERTIES-T type is used in both the ENeUEUE and
DEQUEUE operations, and describes the options available for a given
message. lt is a PUSQL record, defined as follows:
ENQUEUE_OPTtONS_T
This type is used to specify the options for the ENQUEUE operation, other
than those of the message itself. lt is defined as a PL/SQL record:
DEQUEUE_OPTIONS_T
This record is used to specify the options for the DEQUEUE operation, as
opposed to the options in the message itself. lt is defined with
Enumerated Constants
Many of the fields for the supporting types in DBMS-AQ are enumerated
constants. The fields are defined as BINARY-INTEGER, and DBMS-AQ
defines the appropriate values. When setting these options, they need to be
prefixed with the package name-DBMS-AQ.IMMEDIATE, for example.
The following table lists all of the enumerated constants, their values, and
where they are used.
ENQUEUE
DBMS-AQ.ENQUEUE can accept a message payload that is either an
object type or RAW. lt is defined as follows:
PROCEDURE ENQUEUE (
queue-name I N VARCHAR2,
enqueue-options I N ENQU EU E-OPTIONS-T,
mess age-p ro perties I N M ESSAC E-P ROPE RTI ES-T,
payload lN message-tYPe,
msgid OUT RAW);
DEQUEUE
DBMS-AQ.DEQUEUE is also overloaded to accept either a RAW or object
type message. lt is defined with
Chapter l7: Oracle Advanced Queuing 667
PROCEDURE DEQUEUE (
queue_name I N VARCHAR2,
dequeue_options I N DEQU EU E_OPTIONS_T,
message_properTies OUT MESSACE PROPERTIES T,
payload OUT messa ge_type,
msgid OUT RAW);
Queue Administration
ln this section, we will examine the DBMS_AQADM packages, and the
privileges required to use queues. We will also examine the data dictionary
views relevant to queues.
568. OracleS PUSQL programming
DBMS_AQADM Subprograms
The DBMS-AQADM package defines subprograms to adminisrer
queues
and queue tables. Each of the subprograms islescribed in
this section.
CREATE_QUEUE_TABLE
DROP_QUEUE_TABLE
This procedure drops the specified queue table. All the queues in the
table
must be stopped and then dropped before the table ."n b" dropped.
The syntax is
Chapter l7: Oracle Advanced Queuing 67 I
CREATE_QUEUE
CREATE_QUEUE creates a queue in the specified queue table. The queue
name must be unique within the current schema, and both enqueue and
dequeue operations on the queue are disabled by default. After the queue is
created, it must be enabled using START_QUEUE. The syntax for
CREATE_QUEUE is
PROCEDU RE CREATE-QU EU E(
queue_name lN VARCHAR2,
queue_table I N VARCHAR2,
queue_type lN BINARY_INTECER DEFAULT NORMAL_QUEUE,
max retries lN NUMBER DEFAULT 0,
retry_delay lN NUMBER DEFAULT 0,
retention time lN NUMBER DEFAULT 0,
dependency_tracking I N BOOLEAN DEFAULT FALSE,
comment lN VARCHAR2 DEFAULT NULL,
auto cammit lN BOOLEAN DEFAULT TRUE);
672 Oracle8 PUSQL Programming
DROP_QUEUE
DROP_QUEUE drops an existing queue from its containing queue table.
The qr.reue rnust h.tve been stopped with STOP_QUEUE prior to beine
dropped. All of the qLrelre data is deleted as part of the drop operatiorr.
DROP_QUEUE is defined with
674 Oracle8 PUSQL Programming
PROCEDURE DROP-QUEUE(
queue_name I N VARCHAR2,
auto commir lN BOOLEAN DEFAULT TRUE);
ALTER_QUEUE
This procedure is used to modify certain properties of a queue. only the
max_retries, retry_delay, and retention_time properties can be modified. to
change other properties, the queue must be dropped and recreated. The
syntax for ALTER_QUEUE follows, and the parameters are described in the
following table.
START_QUEUE
START QUEUE is used to enable a queue for enqueue and/or dequeue
operations. A queue must be started after it is created. Only dequeues are
allowed on an exception queue, so enabling an exception queue for
enqueue has no effect. The queue is started when this procedure returns,
even if the transaction is rolled back. START QUEUE is defined with
PROCEDU RE START-QU EU E(
queue_name I N VARCHAR2,
enqueue lN BOOLEAN DEFAULT TRUE,
dequeue lN BOOLEAN DEFAULT TRUE);
sToP_ QUEUE
STOP QUEUE is used to disable enqueue and/or dequeue operations for
the specified queue. A queue cannot be stopped if there are oLrtstanding
transactions against it. The queue is stopped when this procedure returns,
even if the current transaction is rolled back. STOP_QUEUE is defined with
PROCEDURE STOP-QUEUE(
queue,,nanle I N VARCHAR2,
67 5 OracleS PUSQL programming
ADD_SUBSCRIBER
ADD-SUBSCRIBER will add a default subscriber ro a queue. This is only
valid on queues which can have multipre consumers. ADD suBSCRIBER
takes effect immediately, and the current transaction is committed. The
user
must have been granted access to this queue with CRANT TypE ACCESS.
The syntax is
REMOVE_SUBSCRIBER
This procedure will remove the specified subscriber from the specified
queue. lt takes effect immediately, and the current transaction is
committed. As paft of the remove, all references to the subscriber are
deleted from existing messages. The user must have been granted access to
this queue with CRANT_TYPE_ACCESS. The syntax is
QUEUE_SUBSCRIBERS
This function will return a PL/SQL table of the subscribers for a given
queue. The syntax is
GRANT-TYPE_ACCESS
CRANT-TYPE-ACCESS is used to enable a given user to perform queue
administrative operations. Unless this is done, the user cannot execute
CREATE-QU EU E-TAB LE, CREATE-QU EU E, ADD-SU BSCRI B ER, ANd
REMOVE SUBSCRIBER. lt is defined with
START_TIME-MANAGER
This procedure enables the time manager process. The AQ-TM-PROCESS
init.ora parameter must have been set to 1 first, which starts the process at
database startup time. The time manager is started when this call returns,
even if the current transaction is rolled back. START TIME-MANACER
takes no arguments and is defined with
Queue Privileges
ln order to use the DBMS-Ae or DBMS_AeADM package, there are
certain steps which must be performed by the system administrator.
There are two roles which must be granted, foilowed by access to the
AQ object types.
AQ_ADMINISTRATOR ROLE
The role AQ-ADMINtsrRAToR RoLE is predefined by oracle. tt contains
all the necessary cRANTs to allow the grantee EXECUiE permission on
DBMS-AQ and DBMS_AQADM. This role shourd be granted to users who
will need to administer queues.
AQ_USER_ROLE
The AQ-USER-ROLE role, on the other hand, just granrs EXECUTE on
DBMS-AQ. This role should be granted to users who will need to enqueue
and dequeue messages, but not adminrster queues.
one message. The name of this view is aq$gueue_ table_name, and has the tr
$
4:
€n';
tti;.
{
4
4
q
1
t"
1 Chapter l7: Oracle Advanced Queuing 579
d
t
*
*1
Column Datatype Description
queue VARCHAR2(30) Name of the queue
$
l: containing this message
t msg_id RAW(16) Message identifier
4
L
corr id VARCHAR2(30) Correl ation identifier
t NUMBER Priority of this message
;1 msg_priority
msg_state VARCHAR2(9) State of this messagHne
'tl
Y,
of READY, DELAYED,
.i PROCESSED, or EXPIRED
.ii
enq-user-id NUMBER
issued the enqueue
enq-txn-id VARCHAR2(30) Transaction lD of the
enqueue
deq_time DATE Time this message was
dequeued
deq-user id NUMBER User lD of the usei who
issued the dequeue
DB S/USER_QUEUE_TABLES
The ntains information abouiall the queue tables
in th e_tables contains information about the
current user's queue tables. They both have the following
structure:
Extended Examples
ln this section, we features of Advanced Queuing
will examine many of the
through a series of examples. The examples illustrate the following features:
I Browsing a queue
I Using exce,lption queues
I Dropping queues
once this is done, we can proceed to create queue tables and queues. The
following script will create and start all of the queues used in these
examples.
BEGIN
-- Create a simple table, with all of the defaults. This will a11ow
-- FIFO queues, with no message grouping. or multiple consllmers.
DBMS_AQADM . CREATE-QUEUE_TABLE (
queue_table =>'SimpleQTab',
queue3ayJ.o.ad_type =>'Messageobj,,
comment => 'Si-mp1e Queue fable,);
-- Create a simple queue contained within SimpleeTab. Again, use
-- the default parameters.
DBMS-AQADM. CREATE_QUEUE (
queue_name =>'SimpfeQ',
queue_table =>'Sj-mpleQTab',
comment => 'Simple Queue, ) ;
queue_name =>'ExceptionQ',
queue_table =>'SimpleQTab',
queue_tltpe => DBMS_AQADM. EXCEPTION_QUEUE,
conment => 'Exception Queue') ;
BEGIN
-- Create a priority queue tab1e, by specifying the sort order.
-- This queue has no message grouping or multi-ple consumers.
DBMS-AQADM, CREATE-QUEUE _TABLE (
queue_name =>'PriorityQ',
qr:eue-table =>' PriorityQTab',
comment => 'Pri-ority Queue');
e_QTimeOut EXCEpTTON;
PRAGMA EXCEPTION_INIT(e-QTimeouI, _25228) ;
BEGIN
FOR v_Counter IN 1. . c_NumMessages LOOP
-- Create a messaqe to enqueue.
v_Message:=
MessageObj(,Message , ll v_Counter, v_Counter * 10,
'abcdefghijklmnopqrstuwrnqzz,, SYSDATE + v_Counter) ;
queue_name =>,Simpfee,,
enqueue_options => v_EnqueueOptj_ons,
messageJropert i es => .v_Mes sagepropert j_es,
payload => v_Messag'e,
msgid => v_MsgID);
END LOOP;
Clearing a Queue
We can adapt the second portion of the above exampre into a procedure
that will delete all the messages in a queue, by simply dequeuing until
there are none left:
e_QTimeOut EXCEpTION;
PRAGMA EXCEPTTON_rNIT (e_eTimeOut, _252281 ;
BEGIN
-- Loop until there are no more messages to d.equeue.
BEGIN
LOOP
-- Dequeue the first message into v_Messaqe, waiting a maximum
-- of 1 second.
v_DequeueOptions.waj_t := 1;
DBMS-AQ. DEQUEUE (
queue_name =>,Simplee,,
dequeue_options => v_Dequeueoptions,
mes sag'ejropert ies = > v_Mes saqepropert j_ es,
payload => v_Messag,e,
msgid => v_MsgID);
END LOOP;
EXCEPTION
WHEN e_eTimeout THEN
-- End of the queue reached.
NULL;
END;
e_QTimeout EXCEpTION;
PRAGMA EXCEPTTON-IN]T(e-QTimeout, -25228) ;
BEGTN
FOR v_Counter IN 1 . . c_Nr.unMessages LOOP
Chapter l7: Oracle Advanced Queuing 587
queue-name =>'PriorityQ',
enqueue-options => v-EnqueueOptions,
messagejroperties => v-MessageProperties,
payload => v-Messagle,
msgid => v-MsgID);
END LOOP;
queue-name =>'PriorityQ'
dequeue options => v-Dequeueoptions,
messageiroperties => v-MessageProperties,
payload -> v-Message'
msgid => v-MsgID);
Note the difference in output between the simple queue and priority
queue. The priority queue dequeues by priority, resulting in a reverse list
from the simple queue.
v-Message MessageObj i
v-Enqueueop t i ons DBMS-AQ . ENQUEUE-OPT I ONS-T ;
v_Deqr-reueOpt j- ons DBMS-AQ . DEQUEUE-OPT IONS-T ;
v_Me ss ag'eProper t i e s DBMS_AQ . MES SAGE-PRoPERT I ES-T ;
v_MsgID naw(16);
v_TigerMsglD RAW(16);
e_QTj-meOut EXCEPTION;
PRAGMA EXCEPTION-INIT (e-QTimeout, -25228) ;
BEGIN
-- Initialize the array of correl-ation identifiers.
-- There will be a total- of 5 different correl-ation IDs, with two
-- messages getting each one.
FOR v_Counter IN 1..c-NurMessages LOOP
IF MoD(v-Counter, 5) = 1 THEN
v-Correl-ations (v-Counter) : = 'Lion' ;
ELSIF MOD(v-Counter, 5) = 2 THEN
v-Correlations (v-Counter) : = 'Tiger' ;
ELSIF MoD(v-Counter, 5) = 3 THEN
v-Correlations (v-Counter) i='Bear' ;
ELSIF MoD(v-Counter, 5) = 4 THEN
v-Correfations (v-Counter) : = 'Fish' ;
ELSE
v-Correlations (v-Counter) :='Horse' i
END IF;
END LOOP;
queue-name =>'SimPleQ',
enqueue-options => v-EnqueueOptions,
590 Oracle8 PUSQL Programming
queue_name =>'Simp1ee,,
dequeue_options => v_DequeueOptions, i
messageJropertj_es => v_Messageproperties,
payload => v_Messag.e,
msgid => v_MsgID);
Browsing a Queue
By setting the dequeue_mode in the dequeue options to BROWSE, you can
examine the contents of a queue without actually removing the elements.
This technique can be used to search a queue for a particular message, for
example. The SearchQueue function does exactlf that:
RETURN RAW AS
692 Oracle8 PUSQL programming
v_Messaqe MessageObj;
v_Dequeueop t i ons DBMS_Ae . DEeUEUE_OPTf ONS_T
;
v_Me s s ag,eproper t i es DBMS_Ae . ME S SAGE_PROPERTI
ES_T ;
v_MsgrD RAW(16);
e_QTimeOut EXCEpTTON;
PRAGMA EXCEPTTON_INrT (e_eTimeout, _25228) ;
BEGTN
-- Loop until there are no more messages to dequeue, or we have
-- found the desired message.
BEGIN
LOOP
-- Dequeue (in browse mode) the first messagre into v_Messag.e,
-- waiting a maxi-mum of 1 second. Since we are browsing, the
-- messag.e will not be removed from the queue.
v_DequeueOptions.wait := 1;
v_DequeueOgt ione . dequeue_rnode : = DBMS_Ae . BROWSE ;
DBMS_AQ. DEQUEUE (
e_QTimeout EXCEPTION;
PRAGMA EXCEPT]ON-]NIT (e-QTimeOut, -25228) ;
BEGIN
FOR v_Counter IN 1..c_NurMessages LOOP
-- Create a message to enqueue.
v_Message :=
MessageObj('Message, ll v_Counter, v_Counter * 10,
'abcdefghijklmnopqrsturzwxyz,, SYSDATE + v_Counter) ;
e_QTimeOut EXCEpTION;
PRAGMA EXCEPTION_IN]T(e-QTimeout, _25228) ;
BEGIN
-- Enqueue 3 messag.es with the exception queue set.
FOR v_Counter IN 1. . c_NumMessages LOOP
-- Create a message to enqueue.
v_Messag'e :=
MessageObj(,Message , ll v_Counter, v_Counter * 10,
,
abcdefgrhijklmnopqrstuvrlrqrz,, SYSDATE + v_Counter) ;
Chapter l7: Oracle Advanced eueuing 695
-- Enqueue it.
v_MeasageProperties. exception_queue , ExceDt,ione,
DBMS-AQ. ENQUEUE
! = i
(
queue_name =>,Simplee,,
enqueue_options => v_EnqueueOptions,
messageJroperties => v_Messageproperties,
payload => v_Message,
msgid => v_MsgfD);
END LOOP;
-- Verify that there are three messages in the normal queue, and
-- none i-n the exception queue.
SELECT COUNT(*)
INTO v_Normal_Count
FRoM aqgSimpleeTab
WHERE queue = UppER(,Simp1eq,);
SELECT COUNT(*)
INTO v_ExceptionCount
FROM aq$SinpleeTab
WHERE queue = UppER(,Exceptione, );
DBMS_OUTPUT.pUT('After initial_ enqueues, count(simple) =,
v_Normal_Count) ;
I
DBMs-ourpur.pur LTNE(', count(exception)
=, | | v_Exceptioncount) ;
-- Dequeue the first message, then rollback. This will_ rollback the
-- dequeue, and increase the attempts field j_n the message
-- properties. since the max-retries for simpleQ is 0, this wi_1]
-- move the message to the exception queue.
v_DequeueOptions.wait := 1;
DBMS_AQ. DEQUEUE (
queue_name =>,Simplee,,
degueue_options => v_DequeueOptions,
messageJroperties => v_Messageproperties,
payload => v_Message,
msgi-d => v_MsgID) ;
ROLLBACK;
-- verify that there are two messaqes in the normal queue, and one
-- in the exception queue.
SELECT COUNT(*)
fNTO v_Normal-Count
596 OracleS PUSQL programming
FROM aq$SimpleeTab
WHERE qudue = UppER('Simpleq,);
SELECT COUNT(*)
INTO v_ExceptionCount.
FROM aqgSimpleeTab
WHERE queue = UppER(,Exceptj-one, ) ;
DBMS-OUrPUT.PUT('After dequeue and rol1back, count(simple)
=, I I
v_NormalCount);
DBMS_OUTPUT.PUT_LINE(,, count(exception) =, | | v_ExceptionCount) ;
-- Now we can get the message from the excepti-on queue. Note that
-- we have to use the message rD, since the state of this messagre is
-- EXPTRED, and the dequeue wir-r not normally return any messages
-- with a state other than READy.
v_DequeueOptions.msgid : = v_MsgID;
DBMS-AQ. DEOUEUE (
queue_name =>,Exceptione,,
dequeue_options => v_DequeueOptions,
messag.eJroperties => v_Messageproperties,
payload => v_Message,
msgid => v_MsqfD);
v_Message. Print (,After exception dequeuing, ) ;
-- verify that there are tu/o messages in the normaf queue, and none
-- in the exception queue.
SELECT COUNT(*)
INTO v_Normal_Count
FROM aqgsimpleeTab
WHERE queue = UppER(,Simpleq,);
SELECT COUttrl*1
fNTO v_Exceptioncount.
FROM ag$SimpleeTab
WHERE queue = UppER(,Exceptione, ) ;
DBMS_OUTPUT.PUT(.,After exception dequeue, count(simpl-e) = , I I
y_Normal_Count ) ;
DBMS_OUTPUT. PUT_LINE (,, count (exception)
=, I I
v_Exceptj-onCount ) ;
Dropping Queues
The following script will stop all of the queues, drop them, and drop their
contai ning queue tables.
BEGIN
DBMS-AQADM. STOP-QUEUE ( ' Priori tyQ' ) ;
DBMS_AQADM. DROP-QUEUE ( ' PriorityQ' ) ;
DBMS_AQADM. DROP_QUEUE_TABLE ( ', Priori tyqtab', ) ;
END;
Surnmarrf
ln this chapter, we have examined the Oracle Advanced Queuing system.
This robust implementation provides a queuing system built into the
database, ratherthan with a separate product. Thus, allof the advantages of
Oracle are supplied for Advanced Queuing. We have discussed the
operations necessary for the use and administration of queues, with their
supporting PL/SQL packages. ln the next chapter, we will examine
additional DBMS packages available with Oracle: DBMSJOB and
UTL FILE.
700 OracleS PUSQL Programming
long with the other DBMS packages that we've seen so far,
PL/SQL provides DBMSJOB and UTL_FlLE. The
DBMSJOB package, available with PL/SQL 2.2 and higher,
allows stored procedures to be run periodically by the
system, without user intervention. The UTL_FILE package,
available with PL/SQL 2.3 and higher, adds the ability to read and write to
operating system files. These packages extend PL/SQL and provide
functions that are available with other third-generation languages.
Database Jobs
With PL/SQL2.2 and higher, you can schedule PL/SQL routines to
run at specified times. This is done with the DBMSJOB package,
which implements job queues. A job is run by submitting it to a job queue,
along with parameters specifying how often the job should be run.
lnformation about currently executing jobs, and the success or failure of
previously submitted jobs, is available in the data dictionary. For more
information about database jobs, see the Server Administrator's Guide,
release7 .2 or laler.
Oracle Advanced Queuing, available with PL/SQL 8.0 and
described in Chapter 17, enhances the queuing capabilities of
PL/SQL well beyond what DBMSJOB provides.
Background Processes
An Oracle instance is made up of various processes running on the system.
Different processes are in charge of running different aspects of the
database, such as reading database blocks into memory, writing blocks
back to disk, and archiving data to offline storage. These processes are
described in Chapter 22.|n addition to the processes that manage the
database, there are processes known as the SNP processes. SNP processes
implement database snapshots, and also job queues.
SNP processes run in the background, like other database processes.
Unlike other database processes, however, if an SNP process fails, Oracle
restarts it without affecting the rest of the database. lf other database
processes fail, this generally brings down the database. Periodically, an
SNP process will wake up and check for a job. lf a joh is due to be run, the
SNP process will execute it and then go back to sleep. A given process can
be running only one job at a time. ln OracleT, there can be a maximum of
ten SNP processes (numbered SNPO through SNPg), so a maximum of ten
Chapter l8: Database Jobs and File l/O 70 I
Default Range of
Parameter Value Values Description
JOB_QUEUE_PROCESSES 0 0..10 How many processes
to start.
JOB_QUEUE_INTERVAL 60 1..3600 lnterval between
wake-ups of the
process. The process
will sleep for the
specified number of
seconds before
checking for a new
job.
JOB_QUEUE_KEEP_ FALSE TRUE, Controls whether an
CONNECTIONS FALSE SNp process closes
any remote database
connections it makes.
lf TRUE, then all
connections will be
kept until the process
is shut down. lf
FALSE, then the
connections are kept
only as long as there
are jobs to execute.
Running a Job
ng it to a job queue, or forcing
to a job queue, an SNp process
s job can then be run
immediately, it is run only once.
SUBMIT
A job is submitted ro the job queue with the suBMlr procedure. sUBMlr is
defined as
V JOBNUM
JOB NUMBERS The job number is assigned to the job when it is first
submitted. Job numbers are generated from the sequence SYS.JOBSEQ.
Once a job number is assigned to a job, it will never change unless the job
is removed and then resubmitted.
CAUTION
Jobs can be exported and imported, like
other database objects. This does not
change the job number. lf you try to import
a )pb whose number already exists, you will
receive an error and the job cannot be
imported. ln this case, simply resubmit the
job, which will generate a new job number.
704 OracteS pUSeL programming
CAUTION
Once the job is submitted, it will be run by
one of the SNp processes in the
background. ln order to see the results, be
sure to code a COMMTT at the end of the
job procedure.
COMMIT;
END Templnsert;
BEGIN
DBMS-JOB. SUBMIT ( :v-,JobNum,'Tellrl)lnsert (next-date) i', sysdate,
'sysdate + (5/ (24*60*60) )') ;
END;
then the job will automatically remove itself from the job queue (by setting
p-NextDate to NULL) when the sequence number is greater than 15.
Because the job can return the value of next-date and broken, a job can
remove itself from the queue when desired.
fhe what parameter is a VARCHAR2 character string. As a result, any
character literals srat should be used in the call to the job procedure should
be delimited by two single quotes. The procedure call should also be
terminated with a semicolon. For example, we could call Register with the
following what string:
'Register(10006,,,MUS", 470) ;'
EXECUTION INTERVALS The first time the job will be run after the
SUBMIT call is given by the next-dafe parameter. Just before the job itself is
executed, the function given by intervalis evaluated. lf the job is
successful, the result returned by intervalbecomes the new next date. lf the
job is successful and intervalevaluates to NULL, the job is deleted from the
queue. The expression given by intervalis passed as a character string, but
should evaluate to a date. Some common expressions and their effecti are
described here:
lntervalValue Result
'SYSDATE + 7' Exactly seven days from the last
execution. lf rhe job is initially
submitted on Tuesday, then the next
run will be the following Tuesday. lf
the second run fails, and it then runs
successfu I ly on Wednesday,
subsequent runs will be on
Wednesdays.
,
N EXT-DAY(TRU NC(SYSDATE), Every Friday at noon. Note the use
,,FRIDAY")
+ ]2 of the two single quotes around the
literal 'FRIDAY' within the string.
SYSDATE + 1124 Every hour.
RUN
The DBMSJOB.RUN procedure will run a job immediately. lt is defined
with
RU N(iob lN BINARY_INTECER);
The job must already have been created by calling suBMlr. Regardless of
the current status of the job, it is run immediately by the current process.
Note that the job is not run by an SNP background process.
I
Broken Jobs
oracle will automatically attempt to run a job again if it fails. The job will
be run again starting one minute after the first failure. lf that attempt also
fails, the next attempt is two minutes later. The interval doubles each time,
to four minutes, then to eight, and so on. lf the retry interval exceeds the
execution interval specified for the job, the execution interval is used. once
the job fails 16 times, it is marked as broken. Broken jobs will not be run
again automatically.
You can run a broken job with RUN, however. lf that call succeeds,
then the failure count is reset to zero and the job is marked as not broken.
The BRoKEN procedure can also be used to change the status of a job. lt is
defined with
Removing a Job
A job can be removed from a jobjueue explicitlv with the REN1OVE
procedure,
where the only parameter is the job number. lf rhe next_dare for a job
evaluates to NULL (either because the job has set iI or interval evaluates to
NULL), then the job will be removed after it has finished executing. lf the
job is currently running'when REMovE is cailed, it will be r."rnoued from
the queue after it has finished.
Altering a Job
The parameters for a job can be altered after the job has been submitted.
This is done using one of the following procedures:
NOTE
A job can change its environment by issuing
the ALTER 5855/ON command through the
DBMS_SQL package. lf this is done, it will
only affect the current execution of the job,
not future executions. The DBMS_SQL
package is described in Chapter 15.
File I/O
As we have seen, PL/SQL does not have input and output capability
built into the language itself, but does have this functionality
through supplied packages. l/O to the screen has been implemented with
the DBMS_OUTPUT package, described in Chapter 14. PL/SQL 2.3 extends
l/O to text files, with the UTL_FILE package. There is no way to output
directly to a binary file with this version of UTL_FlLE. This restriction will
likely be lifted in future versions of PLISQL.
OracleB allows binaryfilesto be read by using BFlLEs, which are a
special form of external LOBs. BFILEs are discussed, along with the
other LOB types, in Chapter 21.
This section describes how UTL FILE works. Three complete examples
at the end of the section demonstrate the package.
Security
Client-side PL/SQL has a package similar to UTL_FlLE, known as TEXT_IO.
There are different security issues on the clientthan on the server, however.
Files created with the client-side TEXT_IO package can be placed
anywhere on the client, subject to operating system privileges. There are
no privileges associated with PL/SQL or the database itself for client-side
file l/O.
710 OracteS pUSeL programming
re UTL_FILE_DIR = /rmp
UTL_FILE_DfR = /home/oracle/output_fi1es
ln order to access a fire with url_FrLE, the directory
filename are passed as separate
----'/ name and the
he
directory name.is compaied aga
nd,
then the operation is allowed.lf
EN is
not accessible, an error is returned
tories
are not allowed, unress the subdirectory is arso risted
expricitry as
accessibre. civen the preceding ,.."*ibre directories,
Tabre 1B_3
describes legal and illegal direclory/ ilename pairi- --'
NOTE
Even if the operating system is not case
sensitive, the comparison between the
specified directory and the accessible
directories is always case sensitive.
UTL_FILE_DIR = * I
I
then database permissions are disabled. This
makes all directories
accessible to UTL FILE.
r9
rri
CAUTION
Turning off database permissions should be
used very carefully. Oracle does not
recommend that you use this option in
.:.( production systems, since it can circumvent
operating systern permissions. ln addition,
do not Ltse "." (the current directory on Unix
systems) as part of the accessible directories
list. Always use explicit directory paths.
is necessary for other users to access these files outside of UTL_FrLE, then
the system administrator should change the permissions on the files.
WARNING
It is also good security practice to prohibit
write operations on directories in the
accessible directory list. The only user who
should be given write permission on
accessible directories should be the Oracle
user. lf'users are allowed write permission,
they can create symbolic links to other
directories, and thus circumvent operating
system privi lege checki ng.
FOPEN
FOPEN opens a file for input or output. A given file can be opened for input
only or output only at any time. A file can't be used for both input and
output simultaneously. FOPEN is defined with
FUNCTION FOPEN(/ocation lN VARCHAR2,
filename lN VARCHAR2,
open_mode lN VARCHAR2)
RETURN FILE TYPE;
Chapter l8: Database f obs and File l/O 7 I 3
The directory path specified must already exist-FopEN will not create
it. lt will, however, overwrite an existing file if the mode is,w,. The
parameters and return value for FOPEN are described in the following
table. FOPEN can raise any of the following exceptions:
T UTL_FILE.INVALID_PATH
T UTL-FILE.INVALID-MODE
I UTL FILE.INVALID OPERATION
I UTL-FILE.INTERNAL ERROR
is raised.
filename VARCHAR2 Name of the file to be opened.
lf the mode is 'w', any existing
file is overwritten,
open-mode VARCHAR2 Mode to be used. Valid values
are
'r' : Read text
'w': Write text
'a': Append text
This parameter is not case
sensitive. lf 'a' is specified and
the file does not exist, it is
created with'w' mode.
return value url FILE.FILE TYPE File handle to be used in
subsequent functions.
FCLOSE
When you are finished reading from or writing to a file, it should be closed
with FCLosE. This frees the resources used by urL_FILE to operate on the
file. FLCOSE is defined wiih
Chapter l8: Database Jobs and File l/O 7 I 5
where the only parameter is the file handle. Any pending changes that have
yet to be written to the file are done before the file is closed. lf there is an
error while writing, UTL_FILE.WRITE_ERROR is raised. lf the file handle
does not point to a valid open file, UTL_FILE.INVALID_FILEHANDLE
is raised.
IS OPEN
This boolean function returns TRUE if the specified file is open, FALSE if
not. lS OPEN is defined as
FCLOSE ALL
FCLOSE_ALL will close all open files. lt is meant to be used for cleanup,
especially in an error handler. The procedure is defined as
PROCEDURE FCLOSE-ALL;
and does not take any parameters. Any pending changes will be flushed
before the files are closed. Because of this, FCLOSE_ALL can raise
UTL_FILE.WRITE_ERROR if an error occurs during the write operation.
CAUTION
FCLOSE ALL will close the files and free the
resources used by UTL_FILE. However, it
does not mark the iiles as closed-lS OPEN
will still return TRLTE after an FCLOSE ALL.
Any read or write operations on files alter
FCLOSE ALL w'ill fail unless the file is
reopened w'ith FOPEN.
7 l5 Oracte8 pUSeL programming
File Output
Five procedures are used to
output
NEW_L|NE, PUTF, and FFLUSFi. p
very much like their counterparts
in
discussed in Chapter 14. The
maxim
1,023 bytes.
PUT
PUT will output the specified string to the specified
have been opened foi write op"rr,"i"*. pur fire. The fire shourd
is defined with
PROCEDU E pUT (fi te_hand I e
R
I N Ft LE_TypE,
buffer tN VARCHAR2);
raised.
NEW_LINE
one or more line terminators to
the specified file. tt
il?H"ilfinw'ires is
PUT LINE
PUT-LINE outputs the specified string to the specified file, which must have
been opened for write operations. After the string is output, the
platform-specific newline character is output. pur LrNE is defined with
buffer lN VARCHAR2);
PUTF
PUTF is similar to pUT, but it ailows the output
string to be formatted.
PUTF is a limited version of the C function printfT",id
h", ,ynau* ,irnit"r,o
printf0. pUTF is defined with
PROCEDURE pUTF(file handle tN FtLE_TypE,
format lN VARCHAR2,
argl lN VARCHAR2 DEFAULT NULL,
arg2 tN VARCHAR2 DEFAULT NULL,
arg3 tN VARCHAR2 DEFAULT NULL,
arg4tN VARCHAR2 DEFAULT NULL,
arg5 tN VARCHAR2 DEFAULT NULL);
DECLARE
v_OutputFile UTL_FILE. F,ILE TypE ;
v_Name VARCHAR2(10) := ,Scott,;
BEGIN
v_OutputFile := UTL_FfLE.FOPEN(. . . ) ;
UTL_FILE . PUTF (v_OutputFi le,
,Hi there!\nMy name
is %s, and I am a ?s major.\n,.
v_Name, ,Computer Science,) ;
FCLOSE (v_OutpurFile );
END;
Hr 't'nere I
My name is Scott, and I am a Computer Science ma_jor..
FFLUSH
The data clutput with PUT, PUT_LINE, PUTF, or NEW_LINE is normally
buffered. When the buffer is full, it is then physically output to the file.
FFLUSH forces the buffer to be immediately written to the specified file. lt
is defined with
File lnput
GET_LINE is used to read from a file, rather than to write to it. One line of
text is read from the specified file and returned inthe bufferparameter.
The newline character is not included in the return string; CET-{-tNE is
defined with
When the last line is read from the file, No_DATA_FouND is raised.
lf the line does not fit into the buffer supplied parameter,
VALUE-ERRoR is raised. Reading an empty line "i "n
will".tu"l
return an empry
string (NULL). lf an operating system error occurs during the read,
urL-FILE.READ_ERROR is raised. The maximum size o] the input line
is 1 ,O22 bytes. The parameters are described here:
Examples
Debug Package
We can implement the Debug package using UTL_F|LE, as follows:
END Debug;
END IF;
/* Open the fil-e for writing. */
v_DebugHandl-e := UTIJ_FILE.FOPEN(p_NewDir, p_NewFi1e,,w, ) ;
v_DebugDir 3= p_NewDir;
EXCEPTION
WHEN UTL_FTLE. INVALTD_PATH THEN
RAISE_APPLICATION_ERROR(-2O1OO,,Reset: Invalid PaIh, ) ;
WHEN UTL-FILE. INVALID_MODE THEN
RAISE_APPLICATTON_ERROR(-20101,'Reset: Invalid Mode, ) ;
WHEN UTL-F]LE. INVALfD_OPERATION THEN
722 OracleS PUSQL Programming
PROCEDITRE Close IS
BEGIN
UTL_FILE . FCLOSE (v_DebugHandle ) ;
END Close;
BEGTN \
v_DebugrDir:='/tmp';
v_DebugFile :='debug.out' ;
D^-^l .
END Debug;
This version of Debug behaves the same as the other versions we have
examined in Chapters 13 and i 4, with some minor changes. Debug.Reset
takes the name and location of the debug file as parameters-if they are not
specified, the output file defaults to /tmp/debug.out. All debugging
statements will add a line to this file. We've also added a new procedure,
Debug.Close. This procedure should be called to close the debugging file.
Although Debug.Debug flushes the output file, the file slrould still be
closed to free the resources associated witlr it.
TIP
Note the exception handlers for the various
routines. They identify which errors were
actually raised, and by which procedures.
This is a good technique to follow when
using UTL_FlLE. Otherwise, you would have
to trap errors with a WHEN OTHERS
handler.
Student Loader
The LoadStudents procedure will insert into students based on the
'contents of the file that is passed to it. The file is comma delimited,
which means that each record is contained on one line, with commas used
to separate the fields. This is a common format for text files. LoadStudents
is created with:
-- Available online as loadstud.sql
CREATE OR REPLACE PROCEDURE LoadStudents (
Chapter l8: Database f obs and File l/O 723
BEGIN
-- Open the specified fife for reading.
v_FileHandle : = UTL_FILE. FoPEN (p-Fi1eDir, p-F'ileName , 'r' );
COMMTT;
EXCEPTTON
-- Handle the UTL FILE exceptions meaningfully,
-- that the file is properly closed. and make sure
WHEN UTL_FILE. TWAITD-OPERATTON THEN
UTL_FrLE. FCLOSE (v_FileHandle)
;
RAISE_APPLTCATION ERROR (
-20 051,,
*HEN
rnvalid File Handle,)
iRR.R
''L_FTLE.READ
UTL_FTLE. '";;"utt"uents:
FCLOSE (v_FileHandle );
RAfSE_APPLICATION ERROR ( -2 0053,
LoadStudents: Read Error, ) ;
WHEN OTHERS THEN
UTL_FILE . FCLOSE (v_FileHand]e ) ;
RAISE;
END
a
LoadStudents;
NOTE
LoadStudenfs uses the student_sequence
sequence number to determine the student
lD. lf this sequence has not been initialized,
it could return a value which is already in
students. ln this case, the primary key
constraint for students would be violated.
Printing Transcripts
We first saw PrintTranscript in Chapter 13. Now that we know how to use
UTL_FILE, we can complete the procedure. We first need the Calculate
GPA procedure:
CURSOR c ClassDetails IS
SELECT classes.num_credits, rs. grade
FROM classes, registered-students rs
WHERE classes.department = rs.department
AND classes. course = rs. course
AND rs.student_id = p_StudentlD;
v-NumericGrade NUMBER;
v_TotalCredits NUMBER := O;
v_TotalGrade NUMBER := 0;
BEGIN
FOR v ClassRecord in c ClassDetails LOOP
-- Determine the numeric value for the grade.
726 Oracle8 PUSQL Programming
v_StudentGPA NUMBER;
v_StudentRecord studentstROWTypE;
v_FileHandle UTL_FILE . Ff Lr'._TypE;
v_NumCredits NUMBER;
CURSOR c_CurrentClasses IS
SELECT *
FROM registered students
WHERE student_id = p_StudentlD;
BEGIN
-- Open the output fife in append mode.
v_FifeHandle := UTL_FILE.FOPEN(p_FifeDir, p_Fi1eName,,w, I ;
SELECT *
INTO v_StudentRecord
\.
Chapter l8: Database Jobs and File !/O 727
FROM students
WHERE 1p = p_StudentID;
v-Cl-assesRecord.course, 7 ),
LPAD (v-NumCredits, 7),
LPAD (v-CfassesRecord. grade, 5) ) ;
END LOOP;
-- Determine the GPA.
CalculateGPA (p-StudentID, v-StudentcPA) ;
EXCEPTION
-- Handle the UTL-FILE exceptions meaningfully, and make sure
-- that the fife is properly closed.
728 Oracte8 PUSeL programming
10002 cs to2 B
10002 Hrs 101- B
10002 ECN 203 A
10002 cs 101 A
10009 Hrs l-01 D
10009 MUS 410 B
10009 Hrs 301 c
10009 MUS 410 B
8 rows selected.
and we call Printrranscript for students 10002 and 10009, we get the
following two output files:
CS IO2
TS 101 4 B
ECN 203 3 A
cs 101 4 A
Hrs 101 4 D
MUS 410 3 B
HIS 301 4 C
MUS 410 3 B
Summarl
We have examined two more utility packages in this chapter: DBMSJOB
and UTL_FILE. Database jobs allow procedures to. be automatically run by
the database at predefined times. UTL_FILE adds file l/O capability to
PLiSQL, subject to security issues on the server. Each of these utilities
provides usefulfunctionality that is not inherent in the language.
732 OracleS PUSQL Programming
The Oracle web server is more complicated than traditional web servers
and also more powerful. Here, we will examine the components of the web
server and how they interact with each other and the Oracle database. A
full discussion of the web server and the interfaces to it is beyond the scope
of this book. For more information on administering the web server and more
.details, see the online documentation available when you install the server.
The components of Oracle's WebServer program are illustrated in
Figure 19-1. The server consists of the following components, which are
listed below and described in the following sections:
I Web listener
I CCI (Common Catewav lnterface)
Chapter l9: Oracle's WebServer program
73 3
Web Listener
CCI
r Executable aF,-b I f wd-l
Programs
Er'."'J t"''ry,
wRB^y//
\ener
Other Cartridges
simply reading a static text file on the operating system. With CCl, the web
pages can be created dynamically. The CCI is often used to implement
HTML forms.
PUSQL AGENT The PLISQL agent is the final link in the process
between a client browser and the oracle server. The agent executes a call
to an Oracle stored procedure. This procedure creates a dynamic HTML
page as output, and the agent passes the output back to the client through
the listener. The agent can use either the CCI or WRB interface.
such as the user name and password, along with the database SID or
SQL*Net connect string. This information is stored in a database
connection descriptor (DCD). The fields contained in a DCD are described
in Table 19-1.
You can administer DCDs from the web server Administration page
created when you installthe web server. This allows you to create and
modify DCDs online. Or you can directly modify the fields in a DCD by
Field Description
username Oracle user to which to connect. Any stored
procedures called with this DCD must be owned by
this user.
password Password for this user.
ORACLE HOME Root for the Oracle software on the server's
operating system.
ORACLE SID Database SlD, if the DCD specifies a local database.
SQL*Net V2 SQL*Net version 2 connect string if the DCD
connect string specifies a remote database.
owa-error-page Absolute path to an HTML page, which the web
agent can return in case of an operating system or
database error. Note that this is not a virtual path for
the web server-it is a direct operating system path.
owa_valid-ports List of valid ports on which the listener will respond.
Different ports can be specified in the URL.
owa_log_dir Log directory where the PL/SQL agent will write a log
file. This file can be used to diagnose errors, as well
as log activities
owa-nls-lang NLS-LANC environment for the Oracle session. This
is specified in the same format as it would be for a
standard Oracle connection, such as AMERICAN-
AMERICA.USZASCII. For more information on
NLS LANC, see the Oracle Server Reierence.
editing the configuration file on the server file system. For more information
on DCDs and these files, see Oracle's WebServer documentation.
With the CCI interface, however, the PL/SQL agent must complete both
stages of the connection for each request. This is necessary because each
CCI request will spawn a new process, which must begin anew. But the
WRBX process remains alive, which means that only stage 2 is required.
since stage 1 is the most time consuming, using the WRB interface is
significantly faster and is thus recommended.
HTP. headClose;
HTp. bodyopen;
HTP. print (p_Greeting) ;
HTp. bodyClose;
HTP . htmlc1ose,.
END he11o;
The calls to the HTP package will generate the actual HTML code, as
described in the next section, "pVSeL Web Toolkit.,, ln order to call this
procedure from a URL, the following steps have to be done:
where host and port arc the machine and port on which the listener is
running' The listener will parse the URL given to it and will direct further
processing based on the components of the URL, each of which can
be
retrieved with the appropriate CCI environment variable. This is described
in the following table:
CGI Environment
URL Component Variable Explanation
/example/owa SCRIPT NAME This tells the listener that the
DCD example should be
used. Because the WRB
specified /example/owa as a
virtual path, the web agent
will process the remainder
of the URL.
738 OracleS PUSQL Programming
CGI Environment
URL Component Variable Explanation
hello PATH rNFo This identifies the procedure
to be called. The web agent
will expect this procedure to
produce HTML output using
the web toolkit packages.
p-creering= QUERY_STRINC This identifies the procedure
Welcome! parameters, if specified.
Note that the name of the
parameter is specified along
with the value. lf there is
more than one parameter,
they should be separated by
question marks.
When we call hello from this URL in a web browser, the output is
displayed in Netscape Navigator 3.0 as shown in Figure i9-2.rhe HTML
that hello generates is as follows:
<HTML>
<HEAD>
<TITLE>He11o Worfd I< /TfTLE>
</HEAD>
<BODY>
Welcome !
< /BODY>
< /HTML>
NOTE
Cenerated HTML pages, like any HTML
page, can be vielwed in a variety of different
browsers. Figure 19-2, for example,
uses Netscape Navigator version 3.0.
Other figures in this chapter show
different browsers.
Chapter l9: Oracle's WebServer program
Tlg
NOTE
The purpose of the web toolkit is to generate
HTML. We will examine the toolkit and the
HTML it generates. We will not, however,
discuss the meaning of the HTML code
itself. For more information on HTML, see
the O rac I e Webserver doc u me ntat i on.
7 40 OracteS pUSeL programming
Package Description
HTP Hypertext procedures. This package contains
procedures that generate many.Jrron
HTML tags.
HTF Hypertext functions. This package contains
the
same functionality as HTp, but t'he subprograms
are
implemented as functions rather than procedures.
OWA* Th,is package contains internal procedures
that are
called by.the PLlSQl- agent itseif. They are
not
meant to be called externally.
OWA UTIL Useful utility functions for manipulating
dates and
dynamic SQL, as well as getting the vaiue
of CCI
environment variables.
OWA_OPT-LOCK* Allows you to impose optimistic locking
strategies
to prevent lost updates.
OWA-PATTERNX Functions that implement regular expression
pattern
matching.
OWA TEXT* Procedures, functions, and datatypes
that allow you
to manipulate large text strings. OWn_pnfTERN
uses OWA_TEXT internal ly.
OWA IMACE Utilities for manipulating server_side image
maps.
OWA-COOKIE Utilities for manipulating HTML cookies.
HTP procedures, except that they return a string with the tag. This string
could then be output with HTP.PRINT, if desired.
The contents of the HTP and HTF functions can be broken into
categories, which are listed in Table 19-3. ln the following sections,
we will examine a sample from each of these categories. For complete
documentation on the syntax and parameters for eich of the funciions,
see the online documentation for the Oracle Web Toolkit.
Printing
The printing procedures are contained in the HTp package only, not HTF.
The main procedure is PRINT, which is used to output aline oi HTML
code. lts argument is passed back through the listener to the client as part
of the page. lt is overloaded with the following definitions:
where cbuf, dbuf, and nbuf contain a value to be output. rf you pass a date
or number, it will be converted to a character string using the default
format. PRINT will output a newline character after the string passed. The
other procedures in this category (P, PRN, pRlNTS, ps) function similarly.
PRN doesn't include the newline, and pRTNTS can substitute for special
characters. The PrintDemo procedure illustrates how to use pRINT:
Category Subprograms
Printing* p, print, prn, prints, ps
Constants bodyOpen, bodyClose, htmlOpen, htmlClose,
headOpen, headClose
Head base, isindex, linkrel, linkrev, meta, title
Body address, anchor, anchor2, area, base, basefont,
bgsound, big, blockquoteOpen, blockquoteClose, br,
center, centerOpen, centerClose/ comment, dfn, div,
fontOpen, fontClose, header, hr, img, img2, line,
listingOpen, listingClose, mailto, mapOpen,
mapClose, nl, nobr, para, paragraph, plaintext,
preOpen, preClose, s, small, strike, sub, sup, wbr
List di rl istClose, d i rl istOpen, d I istClose, d I istDef,
dlistOpen, dlistTerm, listHeader, listltem,
menulistClose, menulistOpen, olistClose, olistOpen,
ulistClose, ulistOpen
Character format cite, code, emphasis, em, keyboard, kbd, sample,
strong, variable
Physical format bold, ital ics, teletype
Form formOpen, formClose, formCheckbox, formHidden,
formlmage, formPassword, formRadio, formReset,
formSubmit, formText, formSelectOpen,
formSe ectOption, formSe lectC lose, formTextarea,
I
formTextarea2, formTextareaOpen,
formTextareaOpen 2, formTextareaC ose I
+ The printing subprograms are available as procedures in the HTP package only. All other
subprograms are available as either procedures (HTp) or functions (HTF).
Chapter l9: Oracle's WebServer Program 7 43
NOTE
PrintDemo contains a call to OWA UTlt.
signature. This procedure prints a line at the
bottom of the paige with the current date,
along with a link to view the PL/SQL source.
For more information, see the section
"OWA_UTIL" later in this chapter.
Constants
There are four constants in the HTF package, which are described in the
following table. There are also equivalent HTP procedures, which will
print them.
Head
The subprograms in this category generate tags that are valid in the header
of an HTML page. As such, they must appear between the HTP.headOpen
and HTP.headClose calls. These tags include information such as the title of
the page. The BodyDemo example in the next section illustrates some of
the head tags.
Body
Body tags are used in the main portion of the HTML page. lt is good style to
enclose the body in <BODY> and </BODY> tags, which are generated by
HTP.bodyOpen and HTP.bodyClose. The subprograms in this category can
do things such as insert images, anchors, and listings. All of these calls can
be found in both the HTP and HTF packages. The BodyDemo procedure
illustrates several of the body tags:
HTP. bodyOpen;
HTP.print('This page demonstrates several of the tags ,);
HTP.print('avai-l-able for formatting the text in the body ,);
HTP.print('of a web page, and for inserting additional ,);
HTP.print('tags.' | | Hrr.para) ;
HTP.header(2,'Links' ) ;
HTP.pri-nt('Here are some links to check out. These are ,);
HTP. print ( 'generated using the HTP. anchor procedure . , ) ;
HTP. para;
HTP. anchor \' / /www . oracl-e . com/ ' , 'Oracle Corporation, ) ;
HTP . para;
HTP. anchor (' / /www . osborne. com/oracle/ index. htm, ,
'OracIe Press' ) ;
HTP. para;
HTP.anchor ('/ /www.platinum. com/ ' , 'pl-at.inum Corporation, ) ;
HTP . para;
. Chapter l9: Oracle's WebServer program
I45
HTP.header(2,,Formats, ) ;
HTP.print(HTF.centeropen | | ,fhese lines are centered, using ,);
END Lr.
The HTML that BodyDemo generates is given next, and the page itself
(in Netscape Navigator 4.0) is shown in Figure 19-3.
<HTML>
<HEAD>
<TfTLE>Body tags demo< /TITLE>
< /HEAD>
<BODY>
This page demonstrates several of the taqs
availabl-e for format.ting the t.ext in the body
of a web page, and for inserting additional
tags . <P>
<H2>Links</H2>
Here are some links to check out. These are
generated using the HTp.anchor procedure.
<P>
<A HREF= " / /vww . oracle. com/ ,,>Oracle Corporation</A>
<P>
<A HREF- " / / www . osborne . com/oracle / index. htm" >Orac1.e press< /A>
<P>
.O " / /www. platj-num. com/ ,'>platinum Corporation< / A>
<P> "*"U=
<H2>Format s< /H2>
<CENTER>These l_ines are centered, using
<BR>
the HTF.centeropen and HTF.centerclose functions.
</CENTER>
<STRfKE>Here,s some strikethrough text.</STRIKE>
</BODY>
< /HTML>
7 46 OracleS PUSQL programming
Thb p.g! d6@r@.r 3*d.l of thr tag, rmil.bl. fd foddiaB th. tdir thc bod5r of a web
pig., ed fd i@.tting.ddition l Eg..
f .hkg
Orulc Cftprat@
Oracla Pre55
Plaliqh Cmdatim
Formets
Th.r. Iiru. dc c.d!.r.4 uriag
tb. HTF cciltoF@ ddlffF.cffitcloe; i&cti@s
H-d..-.ddLthldb+.t*
List
There are of lists available in HTML. Each list consists
of a set of ine, with a formafting tag (such as a bullet or
number) i svailable lists are de"scribed here:
. . .!iro
typically start with a !ist open,tag, followed by the list items
(delimited by a list item tag), then a list c-iose tag. The
ListDemo package
Chapter l9: Oracle's WebServer Program 7 47
illustrates different types of lists. The package is below, and Figure 19-4
shows the output of an ordered list in Microsoft lnternet Explorer 3.0.
-- AvaLla.ble online as liatdemo.eql
CREATE OR REPI,ACE PACKAGE I,iSTDEMO AS
- PROCEDUF.E Go;
PROCEDURE Showlist (p-ListT\pe IN CIIAR) ;
EII\ID LiStDemo;
v_ListOpen : = HTF..menulistOpen,.
v_ListC]ose : = HTF.menulistCl_ose;
ELSIF p_ListT\@e = ,D' THEN
v_Titl-e := ,Directory List,,.
v_ListOpen : = HTF. dirlistOpen;
v_ListCl-ose : = HTF. di_rlistClose,.
END IF;
HTP.htmlOpen;
HTP. headopen,.
HTP . title (v_Title ) ;
HTP. headclose;
HTP. bodyOpen;
-- Output the list itself.
HTP . p (v_ListOpen) ;
FOR v_NamesRec IN c_Names LOOP
HTP. listltem (v_NamesRec . name ),.
END LOOP;
(v-Listclose ) ;
Tt"'n
-- Output the choices.
ShowChoices,-
HTP. bodyOpen;
HTP.header(2, ,Welcome to the list demo,);
ShowChoi-ces,.
OWA_UTIL. signature (, ListDemo. Go' ) ;
HTP. bodyClose;
HTP. htmlClose t
END Go;
END ListDemo;
Chapter l9: Oracle's WebServer Program 7 49
Character Format
The character format tags specify how characters should be formatted. They
do not specify exact characteristics, however. Rather, each browser is free
to render the style how it chooses. For example, the STRONG tag is usually
rendered as bold text, but some browsers could choose to have the text
blink. Specific formattinB tags are described in the next section, "Physical
Format." The following example illustrates some character format tags. The
.lg-5.
output from CharDemo in NCSA Mosaic 3.0 is shown in Figure
HTP . bodyOpen;
HTP.header(2,'This page demonstrates character formatting
tags. ') ;
750 OracleS PUSQL programming
HTP.para;
HTP.cite(,This text is a citation, usually rendered as
italics. ,) ;
HTP.parat
HTP.code(,This text is code, usually rendered as
a monospace
font. ' ) ;
HTP. para;
HTP.stronq('This text is strong., usually rendered as
HTP. para;
bold.,);
Physical Format
The physical format tags specify the physical attributes
of the text. There are
three subprograms in this category: riolo, rrAlrc, and
TELETYPE. BOLD
Form
The form tags are used to implement HTML forms. A form can accept input
from the user, in the form of CUI elements such as text entry fields, and
check boxes. This input is passed to the seryer using the POST method. The
Web agent automatically detects this protocol and passes the entered data
to a PVSQL procedure. As an example, consider the FormDemo package:
-- Aveilab].e oal-Lue as fomdoo.sql
CREATE OR REPLACE PACKAGE FoTmDemo AS
- PROCEDTIRE GO;
pRocEDuRE process(p_Checkbox rN VARCHAR2 DEFAULT ,off,,
p_Password IN VARCIIAR2 DEFAULT NttLL,
p-Radio rN DEFAULT NULL);
EtiID FormDemo, 'ARCHAR2
PROCEDURE SboICForn IS
BEGIN
HTP. li.ne;
-- First open the form, specifying the process procedure as the
-- target URL.
HTP.formOpen(curl => c_OWAPath I I'FormDemo.Process, ),.
HTP. bodyopen;
HTP.header(2,'Form Resul_ts:, ) ;
HrP.p('p_Checkbox = , ll p_checkbox ll urr.nt;;
HTP.p('p_Password = , ll p_password ll HTF.n1);
HrP.p('p_nadio =, ll p_Radio ll Hrr.para);
ShowForm;
OWA_UTTL. signature ( ,FormDemo. process ,
) ,.
HTP. bodyClose;
HTP . htmlClose;
END Process;
PROCEDT'RE G'o Ig
BEGIN
HTP. htmlOpen;
HTP . headOpen;
HTP. title ( 'Forms Demo, ) ;
HTP. headClose;
Chapter l9: Oracle's WebSerryer Program 753
HTP. bodyOpen;
ShowForm;
OWA-UTIL. signature (' FormDemo. Go' ) ;
HTP. bodyClose;
HTP . htmlClose;
END Go;
END FornDemo;
TIP
It is a good idea to have defaults for all of
the parameters accepted by an action
procedure. lf the user does not enter a value
for a form entry, then that parameter will not
be passed. lf there is no default, then an
error will be raised and'the procedure call
will not be successful.
Table
The table formatting subprograms are used to create HTML tables. Tables
consist of rows and columns, each of which can contain any formatted
HTML. The TableDemo procedure demonstrates the use of iome of the
table formatting procedures. The listing follows, and Figure 19-Z shows the
output in Netscape 4.O.
HTP. bodyOpen;
HTP.tableopen(cborder =>,BORDER=1, );
-- Loop over the students, and for each one output two table
-- illl:-ll1:l-Tl ::i::11:l "n''
I first_name last_name I
ID +---------+-----------------+
I major I current_credits I
-- +----+---------+- ------+
FOR v_StudentRec in c_students LOOP
HTP. tableRowopen;
HTP. tableData (crowspan => 2,
cvalue => HTF.bold(v_StudentRec. ID) );
HTP. tableData (ccolspan => 2,
756 OracleS PUSQL programming
calign ,CENTER'
,
cvalue v_StudentRec.first_name ll
I
v_Student.Rec . last_name ),.
HTP. tab1eRowClose;
HTP. tableRowopen;
HTP. tableData ( cvalue 'Major: , ll v_studentRec.najor)
HTp . tab.l:eData ( cvalue 'Credits: , I I
v_StudentRec . current_credi ts ) ;
HTP. tableRowCIose;
END LOOP;
HTP. tableclose;
OWA_UTIL. signature ( , TableDemo , ) ;
HTP. bodyClose;
HTP. htmlClose;
END TableDemo,.
OWA_UTIL
The OWA_UTIL package adds additional functionality. lt is wriften using
the HTP and HTF packages. There are three different sets of subprograms
in OWA-UTIL, which are described in the following sections:
I HTML Utilities
I Dynamic SQL Utilities
I Date Utilities
TIP
ln order to use the OWA-|JT|L package, the
Protect-OWA-Pkg parameter must be set to
FALSE in the OWA configuration for the
Web Request Broker. For more information,
see the online documentation.
HTML Utilities
The following table lists the subprograms available in this cateSory. The
functionality ranges from outputting a signature to displaying an Oracle
table as an HTML table. These subprograms are described in Table 19-5,
Subprogram Description
signature P';l!;:,lT:r;ffii,::;'#'fy3xjJ""Jffiaru:n
on August 9, 1995 09:30." A link to show the PL/SQL
source can also be included.
showsource Outputs the source of the supplied package or
procedure. lf a packaged procedure is specified, then
the entire package is output.
Subprogram Description
showpage Outputs (using DBMS_OUTPUT)the last page which
was generated using the Web Toolkit. This ii useful to
test the output of procedures in Sel*plus or
SQl-Station. For more information, see the section
"Development Environments for OWA procedures,' at
the end of this chapter.
get_cgi_env Returns the value of the specified CCI environment
variable. lf this variable is not set, then this function
returns NULL.
print_cgi_env Outputs the values of all the CCI environment
variables. This is useful for debugging.
mime header Used to change the default MIME header which the
Agent returns. This procedure must be called before
any HTP.PRINT or HTP.PRN calls; otherwise, the
Web Agent will return the default header.
redirect url Specifies that WebServer visit a different URL. As the
generated code is part of the header, this must be
called before any HTP:PRINT or HTp.pRN calls.
status line Sends a standard HTTP status code to the client. As
the generated code is part of the header, this must be
called before any HTP.PR|NT or HTp.pRN calls.
header close Explicitly closes the header. This must be called
before any HTP.PRINT or HTp.pRN calls if
MIME_HEADER, REDI RECT_U RL, or STATUS_LI NE
has not been called with the bclose_header parameter
set to TRUE.
get_owa_ Returns the full service path (including the DCD) for
service_path the currently executing procedure.
tableprint Prints.the contents of a database table as either an
HTML table or preformatted text.
who_called_me Returns information about the pLlSeL object which is
executing,.including the name and type of object.
HTP . bodyOpen;
HTP.p(',This page demonstrates several 0f the HTML ut.ilities ,);
HTP.p('in rhe oWA_UTrL packagre.' | | Hrr.para);
HTP.header(2,,print_cgi_env, ) ;
HTP.p('The foll_owing is generated by , );
HTP . bold ( ' OWA_UTIL. print_cgi_env, ) ;
Hrp.p(,:, ll Hrr.nry;
OWA_UTIL . print_c gi_env ;
HTP.header(2,,tableprint, );
HTP.p('The following table (containing information from ,)
,..
HTP.p('registered_students) is generated by, ) ;
HTP. bold ( ' OWA_UTrL . tableprint , ) ;
HrP.p(':' llHrn.nry;
v_Temp := OWA_UTIL.tableprint(
ctable =>,registered_students,,
cattributes =>,BORDER=1.,
ntable_tlpe => OWA_UTTL. html_table,
cclauses => ,ORDER By student_id, ) ;
HTP.p('Here is the same data, as a preformatted table instead:,),.
HTP. n1;
v_Temp := OWA_UTfL.tableprint (
ctable =>,registered_students,,
cattributes =>'BORDER=1,
7 50 OracleS PUSQL programming
TIP
Because Bl N D_VARIABLES uses
DBMS_SQL for its processing, do not
include a semicolon in the string that
is input.
CELLSPRINT This procedure wilr format the results of the query into
an HTML table. lt is overloaded to accept either a query as a string,'or a
cursorprepared with BIND_VAR|ABLES. lt can also scroll through"ihe result
set of the query, by returning selected rows only.
PROCEDITRE ShonForilr IS
BEGIN
HTP. line;
HTP.p('Enter a query in the box be1ow, and select the ');
HTP.p('output t]4)e, then cl-ick "Submit". If you choose ');
HTP.p('the pickfist, then your query shoufd be of the ');
HTP.p('following form:' \ ;
HTP. n1;
HTP.p('Column 1: Resul-t returned for this item' | | Hrr.nf);
HTP.p('Column 2: String displayed for this item' l] Hrr.nfl;
HTP.p('Column 3: NULL or non-NULL. If non-NULL, the ');
HTP.p('current field will be flagged as selected.');
HTP . para;
-- Fi-rst open the form, specifying the Process procedure as .the
-- target URL.
HTP. f ormopen (curf => c-OWAPath | | 'Dlmarnj-cDemo. Process' ) ;
HTP. formTextArea (cname => 'p_Query' ,
nrows => 5,
nccrlumns => 40) ;
HTP. n1;
HTP.p('Output tlpe:' I ;
HTP.p('HTML Table') ;
Hrp. rormRaur" ,:1il:.=1,,y;Ifi!, ,
HTP. formSubmlt;
END ShowForm;
HTP. bodyOpen;
ShowForm;
OWA_UT] L. s j-gnature ( ,ftrmamicDemo. Go,
);
HTP . bodyClose;
HTP. htmlCl_ose;
END Go;
HTP. bodyOpen;
v_CursorID : = OWA_UTfL . bind_variabfes (p_euery) ;
HTP.p('Output from query ,);
HTP.bold(p_Query) ;
Hrp.p(,:, I I urr.para);
IF p_T\@e = ,tabfe, THEN
HTP.tableOpen(cborder =>,BQRDER=1, ) ;
OWA_UTTL. cellsprint (v_CursorlD ) ;
HTP. tableClose;
ELSE
HTP.formOpen(curl => c_OWAPath | 'Ulmamicoemo. Listprocess , );
I
HTP. formsubmit;
HTP. f ormcl_ose;
END IF;
ShowForm;
Chapter l9: Oracle's WebSeryer Program 7 63
HTP. bodyOpen;
HrP.p('you picked' | | p_value I l, .' I ;
ShowForm;
OWA_UTIL. signature (, DynamicDemo. Listprocess, ) ;
HTP. bodyClose;
HTP. htmlcfose;
END ListProcess;
END [mamicDemo;
Date Utilities
The date utilities in oWA-UTIL implemenr two different features to help
you manage date values in Web pages. The CALENDARPRINT procedure
will output a calendar (as an HTML table) based on the results of a query,
while the cHoosE-DATE procedure will generate code to accept a date as
a day, month, and year.
I Column 1: DATE value used to correlate the returned data with the
displayed calendar.
I Column 2: Text, if any, to be printed for this date.
I Column 3: lf this column is present, then the second column will
be displayed as a link, with destination indicated by column 3. lf
there are only two columns, then the values will be displayed as
text only.
754 OracleS PUSQL Programming
BEGIN
HTP. htmlopen,
HTP. headOpen;
HTP. title ( 'ResuIts' ) ;
HTP. headClose;
HTP. bodyOpen;
HTP.p('You picked ');
HTP . p (TO_CIIAR (OWA_UTIL. todate (p_Dateval ))) ,-
HTP. n1;
OWA_UTIL . signature (' DateDemo . Process ' ) ;
HTP . bodyClose;
HTP . htmlClose;
END Process;
HTP. bodyopen;
HTP.p('Welcome to the Date demo. Here"s a calendar, '\;
HTP.p('created with' | | urr.boi-d('OWA_UTfL.calendarprint, ));
HrP.p(':' ll srr.nr);
OWA_UTIL calendarprj-nt (
.
'SELECT * FROM calendar OR-DER BY today');
HTP.para;
HTP.p('Enter a year, month, and day bel-ow, and then press');
HTP.p(' submit:' | | Hrr.nfl ;
HTP.formOpen(curl => c_OWAPath I I 'DateDemo.Process');
OWA_UTIL.choose_date(p_narne =>'p_DateVal' ) ;
HTP. formSubmit;
HTP. formClose;
OWA_UTfL. signature ( 'DateDemo. Go' ) ;
HTP. bodyClose;
HTP. htmlClose;
END Go;
END DateDemoi
Chapter l9: Oracle's WebSeryer Program 7 67
OWA_IMAGE
The OWA_IMACE package provides a way to handle image maps. An
image mapis a graphic on a'web page. Any graphic can be used as an
anchor for a link, but an image map is sensitive to the location within the
graphic where you click. Based on the x and y coordinates within the
graphic, the web server can return different URLs. Unlike other web
servers, which process image maps by using a separate CCI program, the
Oracle web server can handle them internally. A procedure that references
the OWA_IMACE package is used as the target of an image map to handle
the x and y coordinates. OWA_IMACE defines one datatype, POINT,
which contains the x and y values. Two functions are provided to retrieve
these values, defined with
PROCEDURE ShowBoxes IS
BEGIN
HTP.p('C1ick anlrwhere on the lmag'e below. | | Htr.para);
768 OracleS PUSQL Programming
PROCEDURE Go IS
BEGIN
HTP. htmlOpen;
HTP. headOpen;
HTP:title ( 'Tmagemap test' ) ;
HTP. headclose;
HTP. bodyOpen,-
ShowBoxes;
HTP. bodyCJ-ose,.
HTP. htmlClose;
END Go;
HTP. htmlOpent
HTP. headOpen;
HTP. title ( 'Imagemap resul-ts' );
HTP . headcl-ose;
HTP. bodyopen;
HTP.print('Processed. x='ll,r_* ll 'andy=, llt__v) ;
HTP.print('. This means that you selected ,the , | | v_Co1or);
HTP.print(' box., | | Hrr.para) ;
ShowBoxes;
HTP. bodyclose;
HTP . htmlclose;
END Process;
END Imagemap;
NOTE
ln order to set this up on your system, copy
the boxes.gif file (found on the CD) to an
image directory on your web server and
specify the path in c_lmagePath.
ln order to set up the image map, you create a form with one clickable
image. The target of this image is lmageMap.Process. The form is created
by the ShowBoxes procedure. The boxes.gif image is simply four boxes of
different colors. The results of calling lmageMap.Go and clicking on the
blue box (in Netscape Navigator 4.0) are shown in Figure 19-9.
OWA COOKIE
OWA_COOKIE allows you to manage HTML cookies. A cookie is a piece
of data stored on the client, rather than the server. Cookies can be used to
maintain state between calls to the server. ln normal processing, the client
is not aware that the cookie exists. However, many browsers do have a
setting that enables the user to be notified of cookie transmissions and,
optionally, to refuse them.
770. OracleS PUSQL Programming
{+:ilfla-#Eifdi#g
B+k .:n,
:rd Fdoad Home Seitch GddE ftir* Securit! I rii
Datatypes
The HTTP specification for cookies stipulates that a cookie is a name-value
pair. The value can be set or retrieved for a given name. The name and
value are limited to 4,096 bytes, and multiple values can be stored with
one name. To implernent this, the OWA_COOKIE package defines the
following datatypes:
name VARCHAR2(4096),
vals VC_ARR,
num_vals INTECER);
SEND
The SEND procedure is used to pass a cookie to the client for storage. lt is
defined with
SEND must be called from the HTTP header of a page, as illustrated by the
example at the end of this section. SEND will generate an HTTP header line
that looks like:
The only required parameters are name and value.lf the others are not
specified, the appropriate clause is not generaled. expires specifies the time
when the cookie will expire. lt cannot be retrieved after this time. lf it is not
specified, the cookie expires when the client session is ended (that is, when
the browser is closed).
GET
The GET function returns a cookie with the specified narne. lf there is no
data on the client for the requested name, num_vals in the returned cookie
will be zero. lt is defined with
GET ALL
CET-ALL wiil return all the name-value pairs of the cookies retrieved from
the browser, in the order in which they were sent. lt is defined with
772 Oracle8 PUSQL programming
REMOVE
REMOVE forces the expiration of an existing cookie. Like SEND, it
must be
called from the HTTp header. lt is defined r,iith
Example
The CookieDemo procedure demonstrates the use of owA cooKlE.
-- Available onlLne ae cookie.sql
CREATE oR REPLACE :FjiOcnounn cookieDemo (
p_NewVal rN NUIBER DEFAULT NULL) AS
-- Set c_OwApath to the virtual path (including the DCD) where
-- the Oracle Web Agent is installed.
c_OWAPath CONSTANT VARCHAR2 (50) :=, /example/owa/,
;
HIP . t.i!-l\-C!ien;
nr:.lriii:;
HTa ,--l
t i"e-'come to the cookie demo, using the owA_cooKIE
HTP.prin!(,packag,e. / I I ffrr.para) ') ;
;
IF p_Neh\-a1 IS NOT NULL THEN
HTp.print(,The cookie va1ue has been reset to ,);
HTP.bold(p_NewVal);
HTp.prinr(,., | | Hrr.para);
ELSIF .,'_Cookie.num_val-s > 0 THEN
HTP.print (,The cookie value is now ,) ;
HTp.bold(v_Cookie.val_s (1) ) ;
HTp.prinr(,., | | urr.para);
ELSE
HTP.print ( ,The cookie va]ue has been set to zero. ,
END TF; );
HTP. para;
HTP.print (,C1ick ') ;
HTP.anchor(c_Owapath I l,CookieDerno.,,here,
HTP'print(' to increment the va1ue, or enter ) a; new vafue
HTP.print(, the box below and cl-ick Submit to reset it.,); in,);
HTP . para;
Development Environments
for OVVA Procedures
Developing stored procedures fcir the Oracle web agent is much the same
as for other stored procedures: you have a choice oidevelopment
envi ron ments. However, two envi ron ments-seL*pl us and sel-station,
described in the following sections-have utilities that are useful for these
types of procedures.
OWA_UTIL.SHOWPAGE
The output from a procedure meant to be called through the web agent can
normally be seen only in a web browser. Thus tools ru".h Sel*pius are
less useful. However, the oWA_UTrL.sHowpACE procedure ", will echo
the HTML output from the last procedure using DBMS_ourpUT. The
following SQL*PIus session shows how to ur"lt,
SQIJ> exec BodyDeno
PLlSQL procedure successful_1y completed.
SQl-Station Coder
You can also execute OWA procedures from SQL-Station Coder. The
procedure execution window has three execute buttons. The first will
execute the procedure normally. The next two buttons, however, are used
to call a procedure with the Web Agent, as shown in Figure 19-10. The
"Web execute" button will call a browser on the client and pass it the
ql *l iffi ''i-rLr.-FF-..Fb
ql*lsl !!!lplsl Fl xl.+l \l r lElcl El_rl El
|['.r*, lr-
Q Peckase jl
Qfl Frocedure
F 6 sunrorhln ll
!i
I
'el-"-,"] )
Q! rerLo 1e_rRttTrNG tN ,
; 'Crnro
, 3 fuF"t","n.*.
, 3 GFeterenced Er
, S Prvrleges
E Q! clt't c 6.tsc nt vr+Rrr+t
F Ql PFTNTDEN0 tl
:l
!
Execute Frocedure llvouqh 0rele's \tJeh Serier mm1 D0001
correct URL to execute the procedure with the supplied parameters, using
the CET method. The "Cenerate URL" button will allow you to see (and
optionally edi0 the generated URL and copy it to the clipboard. By using
SQl-Station Coder in this manner, you can create web-enabled procedures
the same way you create normal procedures. For more information on
SQl-Station Coder, see Chapter 13 and the SQl-Station online
documentation.
Summary
ln this chapter, we have discussed Oracle's WebServer program and
examined how PL/SQL is an integral part of it. Through the PLlSeL web
agent, a PL/SQL stored procedure can generate HTML output. This allows
you to create dynamic web pages, based on data in the database. We have
discussed the packages in the web toolkit that aid in this, including the
OWA_UTIL package. The chapter concluded with a discussion of
development environments useful for web agent procedures.
780 OracleS PUSQL programming
Client H Shadow
Process Process
There are several things to note about this environment, which illustrate
some requirements for using external procedures:
Required Steps
ln order to call an external procedure, you must complete the following
steps:
cc -c -o /home/utils/stringlib.so outstr.c
which will create the shared library/home/utils/stringlib.so. The command
for doing this on other operating systems will likely vary-consult your
operating system andlor compiler documentation for more information.
784 OracleS PUSQL Programming
TIP
On Unix systems, the makefile
$ORActE_HOME/rdbms/demo/demo rdbms
.mk contains targets for linking shared
libraries. Ihe extproc_nocallback target wi ll
build a library that doesn't make callbacks
to the database, and the extproc_callback
target will build a library that does make
callbacks. (Callbacks are discussed later in
this chapter, in the section "Callbacks to the
Database.") See this makefile for
i nstructions and examples.
listener.ora This file specifies the parameters for the listener. lt should
look something like the following:
listener =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = ipc)
(KEY = <<LISTENER_KEY>>)
)
)
Chapter 20: External Procedurer
785
(CONNECT-DATA =
(SID = <<EXTPROC_SID>>)
)
NOTE
A single listener (or set of listeners) can
listen both for external w
database connections.
configuration fi les can
databas riptions. For more
informa parameters for
listener. ora, see fhe NetB
Adm i n i strator's Gu ide.
$ lsnrctl start
LSNRCTL for Solaris: Version g.0.3 .0. O _ Production on I2-AIJG-97
01:03 :55
Alias LTSTENER
Version TNSLSNR for Solaris: Veision g.0.3.0.0
- Production
Chapter 20: External Proceduret
TgT
The database does not verify that the operating system shared library
actually exists at this point. However, if it does not, you will receive an
error when trying to call a procedure declared to use the library.
788 OracteS pUSeL programming
LIBRARY This is the only required clause, and it is used to specify the
library that represents the operating system shared library containing the C
procedure. This library must either be in the current schema, or you must
have EXECUTE privileges on it.
LIBRARY stringlib
NAME "OutputString,,
PARAMETERS (p_Path sTRfNG,
p_Message STRfNG);
3 END;
4/
PLlSQL procedure successfully completed.
SQL> exit
Disconnected from OracfeS Server Release 8.0.3 .0.0 - Production
With the Partitioning and Objects options
PLlSQL Release 8.0.3.0. O - Production
$ cat /tmp/output.txt
Heflo World!
Parameter Mappings
One of the main issues when communicating between two languages is
how to convert between datatypes. This is true with external procedures as
well: you need to specify how the PLISQL datatypes used for the
parameters in the wrapper procedure map to the C datatypes used for the
parameters in the external procedure. Besides the datatypes themselves,
there are other issues that need to be resolved:
1A standard C datatype.
2The size of this type can vary, depending
on the operating system and compiler. Thus it is
not always portable.
3An Oracle-defined datatype that is defined in the header
file oratypes.h. Each platform
defines this type such that it meets its definition, ensuring that it is portable.
4An Oracle-defined datatype that is defined in the header
file oci.h. This type is used only
in the OCI functions that manipulate LOBs in the database.
LIBRARY stringlib
NAME "OutputString2',
PANAUETTRS (p-PaLh STRIIiIG,
D_Message STRIIIG,
g_Nrurlines MT);
Parameter Modes
The parameters for the wrapper procedure (and hence for the external
procedure) can be of any PVSQL mode-lN, OUT, or lN OUT. lf the
parameter is OUT or lN OUT, then the associated C parameter must be
passed by reference rather than by value, regardless of the datatype. The
only exception to this rule is external datatype srRlNC, which is passed by
reference regardless of the associated parameter mode. OutputString3
Chapter 20: External Proceduret
797
p_Path IN VARCHAR2,
p_Message IN VARCHAR2,
p_Numlines IN BINARY_INTEGER,
D_Numlineawritten OIII IiIATI'RAL) AS EXTERNAL
LIBRARY stringli-b
NAME "Outputstring3"
PARAMETERS (p_Path STRING.
p_Message STRING,
p_Nrunlines INT,
p_lihlnlinesWrLtten IIB2 ) ;
798 Oracle8 PUSQL Programming
Parameter Properties
Along with the datatype, the pARAMETERS crause is used to specify
additional information, known as propertie.s, for each parameter. Each
property maps to another parameter in the external procedure, but not the
wrapper procedure. The available properties are described below, and their
supported datatypes in Table 20-3.
parameter is OUT or lN OUT, then its return value must not exceed
MAXLEN.
num_times-ind == OCI-IND-NULL) {
*num-fines-written = 0;
return;
)
800 OracleS PUSQL Programming
LIBRARY stringlib
NAME "Outputstring4"
PARAMETERS (p_Path STRTNG,
p_Path IIIDICATOR,
p_Message STRING.
p_Mes5age INDfCATOR,
p_Nurnlines TNT,
p_ilnrmlJin€3 MDIeATOR,
p_Numlineswritten UB2 ) ;
External Functions
and Packaged Procedures
ln addition to external procedures, you can create external functions.
External procedures and functions can be contained in packages, and thus
take advantage of packages features such as overloading.
FILE *fife_handle;
ub2 counter;
*retvaf_ind = OCI_IND_NULL;
return O;
]
LIBRARY stringllb
NAME',Outputstring5,,
PARAMETERS (p-Path STRTNG,
p_Path TNDICATOR,
p_Message STRING,
p_Message INDfCATOR,
p_Numlines fNT,
p_Numl,ines fNDICATOR,
RETURN TIUDTCATOR,
RETI'RN T'82 ) ;
Overloading
Wrapper procedures (or functions) can be in packages,
as weil as
standalone. rn this case, the wrapper procedure
,r..'o"rri uu in ,rru package
body, with a forward decraration in the package
he"aer, as normar. The
debug-extproc package rater in this chapter iriustrates
tnirl"inniqr".
RESTRICT_REFERENCES
/ you can assert the
llow it to be used in a SeL statement.
' il:l ;?"",j','J5,l:;,
external
ffi;Eiil,,
function violates the
pragma, internar errors can resurt.
Service Routines
service routines are used to raise exceptions in the database, allocate
memory, and retrieve OCI handles to execute SQL statements. All of
the
service routines take a context as one of their parameters. ln C, the
context
is of type oClExtproccontext, and is indicated by the coNTEXT
keyword
in the parameter list. The WlrH CONTEXT clause is also required.
OClExtProcRaiseExcp
This service routine raises a piedefined exception, similar to the
RAI5E
statement. The C prototype is defined with
OcfExtProccontext *context i
char *path;
short path_ind;
char *messag.e,.
short message_ind;
int num times;
short num_times_ind;
short *retval_ind; {
FILE *file_handle;
804 O;acle8 PUSQL programming
ub2 counter;
LIBRARY stringlib
NAME,'OutputString6,,
WTTH COIITEKT
PARAMETERS (COTEEXT,
p_path STRTNG.
p_path INDTCATOR,
p_Message STRING,
p_Message INDfCATOR,
p.Nr.unlines fNT,
p_Numlines fNDfCATOR,
RETURN INDICATOR,
RETURN UB2);
Chapter 20: External Procedurer
805
OC I ExtProcRaiseExcpWith Msg
This service routine is similar to RAtsE_APPLlcATloN_ERRoR. Unlike
oClExtProcRaiseExcp, it allows you to pass a user-defined message along
with the error. The error number should be between 20,000 and )o,ggg,
just like RAISE_APPLICATION_ERROR. The protorype is
int OCIExtProcRaiseExcpWj_thMsg (
with_context, error_number, error_message, 1en)
OclExtProccontext *with context;
size t error_number;
text *error_messaqe;
size t 1en;
FfLE *file_handle;
ub2 counter,.
OciExtProcGetEnv
This service routine is defined with
You can use the returned environment, service context, and error handles
in subsequent OCI calls that execute SQL statements. These handles can be
used only for callbacks-they cannot be used for standard OCI calls. For
more information on the oCl handles and their use, see lhe programmer,s
Guide to the Oracle Call tnterface.
Restrictions
There are several restrictions to keep in mind when issuing sel statements
within an external procedure. The following kinds of statements are not
allowed:
NOTE
ln order to use this method, your operating
system must support a debugger that allows
yott to attach to a running process. For
example, on many Unix systems you can
use the gdb debugger.
extproc_func_error EXCEPTITIN ;
END startup_extproc_agent ;
END debug_extproc;
t. Make sure that your C program is compiled and linked into the
shared library with debug symbols. on Unix systems, this is usually
done by passing the -g flag to the compiler.
2. ln a SQL*PIus or other connection to the database, call
debug_extproc"startup_extproc_agent, Although there is no actual
C procedure associated with this wrapper procedure, extproc is
started. No errors are signaled because of the exception handlers in
startu p_extproc_agent.
3. Determine the operating system process lD of extproc. On Unix,
this can be done with a ps command.
4. Start the debugger, and attach to the running process determined in
step 3.
Guidelines
There are several things to keep in mind when using external procedures:
Restrictions
Currently (as of Oracle8 version 8.0) exterrral procedLtres have the
fol lowi ng restrictions:
Summany
ln this chapter, we have discussed externar procedures,
which ailow a
rocedure. We discussed the issues
ping pL/SeL datatypes to C
also reviewed several methods for
will examine
another new oracres feature, Loa, tr"lg"J[l]:$:'we
.ff.
I I6 OracleS PUSQL programming
What Is a LOB?
A LoB is s_imply a database fierd that holds a rarge amount
of data, such as
file or long rexr documenr. What oracL datatype is besr
1 Frphi: ro store
this kind of information? ln OracleT, AR2 field can hold up to
can hold up to 2 gigabytes,
such as the fact that there
atabase table. ln addition, the only
ONC RAW data piecewise is the
racle 7.3.
oracle8 provides a solution. LONC and LoNC RAW corumns
are
still available (with the same restrictions), but there is a new
flltype.tamily available-rhe LoB famiry. There are four different kinds of
LoBs, which are designed for different kinds of data:
cLoB, Ncloe,
BLOB, and BFILE' These datatypes are described in
Tabre 2i-i.
since the data is stored within the database, CLoBs,
NCLoBs, and
BLoBs are coilectively known as internal LoBs. BFTLEs
are kn'wn as
external LOBs. LOBs have the following characteristics:
Objects can have LOB attributes, and methods can take LOBs as
arguments. However, an object cannot have an NCLOB attribute,
although a method can take an NCLOB argument.
I LOBs can be used as bind variables.
LOB Storage
Unlike LONC or LONC RAW data, LOB data is not stored inline in a
database table. Rather, it is stored in a separate location, and a IOB locator
is stored in the original table. The locator serves as a pointer to the actual
data, which can be stored in a different tablespace with different storage
parameters from the table, if desired. The storage for the LOB data can be
specified in the CREATE TABLE statement using the LOB storage clause.
This clause can specify a different tablespace and/or ditferent storage
NOTE
BFlLEs, like CLOBs, BLOBs, and NCLOBs,
are also manipulated through LOB locators.
However, the storage for BFILE data is in a
file outside Oracle's control. For more
information on BFlLEs, see fhe section
"Manipulating BFlLEs" later in this chapter.
LOBs in DML
DML statements are used to manipulate entire LoBs. you can UpDATE a
LoB to a new value, for example. LoBs can be manipulated piecewise
using the DBMS-LOB package, described in detail later in this chapter, in
the section "DBMS-LOB Routines". All of the DBMS LoB routines use a
LOB locator to manipulate the data.
Chapter 2l: Large Obiects I |9
lobdemo
6f"bd;D
\@ )
(
=---:>/
blob data
ln this case, a NULL value is inserted in the column, rather than a LOB
locator. There is no actual storage allocated for the lob data, since there is
no locator to point to it. Because of this, you cannot use DBMS-LOB on a
NULL value. The row must be updated to a valid locator first.
One way of doing this is with the EMPTY-BLOB0 and EMPTY-CLOBO
functions. These functions take no arguments, and return a valid LOB
locator. DBMS-LOB can then be used to populate the LOB data. For
example, consider the following INSERT statement:
820 OracleS PUSQL Programming
NOTE
The empty parenthesis are required for
EMPTY_BLOB0 and EMPTY CLOB0.
After executing the above two statements, the lobdemo tabie will look
like Figure 21-2. After the column has been initialized, you can sELECTthe
lob locator into a PL/SQL variable and use it with DBMS LOB.
Alternativelf , you could use the RETURNINC clause on the INSERT to
retrieve the locator directly.
BFILEs are not initialized with EMPTY_CLOB() or EMpTy_gLOBfl;
rather, the BFILENAME function is used instead. This is described in the
fol lowing section, "Man ipulating BFI LEs".
Example
The follor,ving example illustrates some DML statements which manipulate
LOBs. Note that without DBMS_LOB, only the entire LOB can be
lobdemo
c_>o
FIGURE 2l-2. lobdemo table after insefts
Chapter 2l: Large Objects 82 I
referenced. Also, a SELECT from a LOB column will return the locator, not
the data itself.
-- Retrieves the locator for the newly updated value, not the
-- value itsel_f .
SELECT blob col-
INTO v_BLOBlocator
FROM ]obdemo
WHERE key = 26'
END;
Manipulating BFILEs
The main characteristic of BFILEs is that they are stored outside the
database. Like other kinds of LoBs, you use a locator to manipulate the file.
However, there are several things to note about BFILEs:
Directories
ln order to access an external file, the oracle server needs to know the
location of the file on the operating system. This is done through a new
type of data dictionary object called a directory. The directory is a logical
alias for an actual file system path. A directory is created with the CREATE
DIRECTORY starement:
where dir name is the name of the new directory, and os_path specifies a
cornplete path of a directory on the operating system. For example, the
following statement creates a directory which points to the operating
system di rectory "/home/uti ls":
contains information about all directories which the current user can
access. The structure of these views is described below.
Dropping Directories
Directories are dropped with the DROP DIRECTORY command:
BFILEs in DML
similarto internar LoBs, BFTLEs can be manipurated in
DML. However, in
order to do anything significant (such as reading piecewise
from the file)
you must use the DBMS-LOB package or the dcr interface.
This statement will copy both the locators and the data from lobdemo to
fobdemo2. This behavior is known as copy semantics, since there will be
two sets of the data after the operation. Copy semantics apply to DML
operations on internal LOBs-DML operations on external LOBs use
reference semantics. With reference semantics, only the LOB locator is
copied. For example, consider the following PL/SQL block:
After executing the above biock, both lobdemo and lobdemo2 will
contain a row that points to the same operating system fiie. This situation is
illustrated by Figure 21-3.
then filel can still be accessed from the locator stored in lobdemo2.
826 OracteS pUSeL programming
lobdemo
DBMS_LOB Routines
Five subprograms in DBMS_LoB are used to read LoB
values or return
information about a LoB value. None of these routines modifies
a LoB
value. The routines are
COMPARE
CETLENCTH
Chapter 2l: Large Objects g}l
INSTR
READ
SUBSTR
APPEND
COPY
ERASE
LOADFROMFILE
TRIM
WRITE
FILECLOSE
FILECLOSEALL
FILEEXISTS
FILECETNAME
FILEISOPEN
FILEOPEN
APPEND
Use this routine to append the contents of
a source LoB to the destination
LoB' The source LoB^': unchanged. AppEND is
overroaded to accept
binary or character LOBs with th"e following
definitions:
PROCEDURE APPEND(
dest_lob tN OUT BLOB,
src_lob tN BtOB);
PROCEDURE APPEND(
dest_lob tN OUT CIOB CHARACTER SET
ANy_CS;
src lob tN cLoB CHARACTER sET dest-loby"cH-ARSET);
COMPARE
This function is used to compare two entire
LOB values or parts of two LOB
values. lt will return zero if the LOB values are
identical or non-zero
if they
are not. COMPARE is overloaded to accept
all four types of LOBs with the
fol lowi ng defi n itions:
Chapter 2l: Large Objects 829
FUNCTION COMPARE(
lob_l lN BLOB,
lob_2 tN BLoB,
amount lN INTECER := 4294967295,
.1,
offset_/ lN INTECER:=
offset_2lN INTECER := 1)
RETURN INTECER;
PRACMA RESTRICT_REFERENCES(compare, WNDS, RNDS, WNPS, RNpS);
FUNCTION COMPARE(
lob_l lN CIOB CHARACTER SET ANy CS,
lob_2 lN CIOB CHARACTER SET lob_l%CHARSET,
amount lN INTECER := 4294967295,
offset_/ lN INTEGER:= 1,
offset_2lN INTECER := .l)
RETURN INTECER;
PRACMA RESTRICT-REFERENCES(compare, WNDS, RNDS, wNps, RNps);
FUNCTION COMPARE(
file_l lN BFILE,
file_2 lN BFILE,
AMOUNT IN INTEGER,
offset_/ lN INTECER:= 1,
offset_2lN INTECER := 1)
RETURN INTECER;
PRACMA RESTRICT_REFERENCES(compare, WNDS, RNDS, WNPS, RNpS);
Note that COMPARE can only be used to compare to LoB values of the
same type, such as two BLoBs, two BFlLEs, and so on. The parameters and
return value for COMPARE are described in the foilowing table:
COPY
coPY is used to copy all or part of a source LoB to a destination LoB.
rf
the specified offset for the destination LoB is beyond the enJ
of the data
currently in this LoB, zero-byte characters (for tilogr) or spaces (for
cLoBs and NCLoBs) are inserted. lf the destination offset is less
than the
current length of the destination LoB, the current data is overwritten.
lf the
specified amount is greater than the length of the source LoB,
then the
entire source LoB is copied and no erroi is raised. copy
can be used to
copy data between like LOBs only. lt is defined with
PROCEDURE COPY (
PROCEDURE COPY (
tsEGTN
-- Retrieve source fob locator.
SELECT cfob cof
INTO v_Lob1
FROM lobdemo
WHERE key = 1-
NOTE
Th,il gxample uses the LOBprint
procedure,
which is defined later in this seciion.
tt'ur.,
DBMS_LOB.READ and DBMS_OUT\Ui
to
echo a character LOB to the sireen.
ERASE
You can use this function to erase
either an entire LoB or a poftion
rhe portion of the LoB that i' u,."r"J i, of it.
frii"i;i; ;#; ttf8u, NCL.B)
N?,:1h". the length of the LCjg remains
the same. To
e LOB value, you can use the TRIM
procedure.
PROCEDURE ERASE (
lob_loc tN OUT BLOB,
amount lN OUT tNTECER,
offsef lN INTECER:= 1);
Chapter 2l: Large Obiects 833
PROCEDURE ERASE (
FILECLOSE
This routine is used to close a BFILE that has been opened using FILEOPEN.
The syntax is
where file loc is the locator for the BFILE to be closed. The FileExec
procedure in the section "LOADFROMFILE" later in this chapter
denronstrates Fl LECLOSE.
FILECLOSEALL
This routine is used to closb all BFILEs currently open in the session. lt is
useful in an exception handler, to ensure that the files are closed before
returning the error (similar to UTL_FILE.FCLOSEALL). lt is defined with
PROCEDU RE FI LECLOSEALL;
834 OracleS PUSQL Programming
FILEEXISTS
This function is used to see if the specified file actually exists and is
readable on the file system. FILEEXISTS is defined with
where file-loc is the locator for the desired BFILE. lf the file exists and is
readable, FILEEXISTS returns 1, otherwise it returns 0. A NULL is returned if
file_loc is NULL, does not have the necessary directory and operating
system privileges, or if there is an operating system error.
FILEGETNAME
Civen a BFILE locator, the FILECETNAME procedure will return the
directory and filename associated with the locator when it was initialized
(with BFILENAME). lt is defined with
PROCEDU RE FI LECETNAME(
file_loc lN BFILE,
di r_al i as OUT VARCHAR2,
fi lename OUT VARCUAR2);
where file-loc is the BFILE locator, and dir-alias and filename will contain
the directory and filename, respectively. The maximum length for dir_alias
is 30, and the maximum length for filename is 2000.
FILEISOPEN
This function is used to determine whether a given BFILE has been opened
(with FILEOPEN) for the given locator. lt is defined with
Chapter 2l: Large Objects 835
where file_loc is the BFILE locator for the desired file. lf the file has been
opened with this locator, the function returns 1, otherwise it returns 0.
FILEISOPEN just checks the status of the given locator passed to iu if it
returns 0 another locator could have the same external file open.
FILEOPEN
This function is used to open a BFILE for processing. rt is defined with
PROCEDURE FILEOPEN(
file_loc lN OUT BFILE,
open_mode lN BINARY_INTECER := FtLE_READONLy);
where file_loc is the locator for the desired file. The open_mode is used to
indicate the desired mode for the BFILE, sirlilar to UTL FILE. As of oracleB
Release 8.0, however, the only avail.rble nrode is read-only. This is
indicated by passing the constant DBNIS_LOB.FILE_READONLy for
open-mode. Future versions of or.rcle8 rvill likely include additional
modes and additional constants in DBNIS_LOB for specifying them.
INVALID_ARCVAL is raised if you pass a value other than
DBMS_LOB. Fl LE_READON LY for open_mode.
The FileExec procedure in the section "LoADFROMFTLE', rater in this
chapter demonstrates Fl LEOPEN.
GETLENGTH
INSTR
The DBMS LOB.INSTR function is similar to the INSTR function defined in
package STANDARD for CHAR and VARCHAR2 character strings. lt is
used to find the position of the nth occurrence of a pattern in a given LOB.
INSTR is overloaded to accept all four types of LOBs:
Chapter 2l: Large Obiects 837
FUNCTION INSTR(
lob_loc lN BLOB,
pattern lN RAW,
offset lN INTECER := 1,
nth lN INTECER := 1);
PRACMA RESTRICT REFERENCES(instr,
WNDS, RNDS, WNPS, RNPS);
FUNCTION INSTR(
lob loc lN BFILE,
pattern lN RAW,
offset lN INTECER := 1,
nfh lN INTECER := 'l);
PRACMA RESTRICT-REFERENCES(i nstr,
WNDS, RNDS, WNPS, RNPS);
FUNCTION INSTR(
lob loc lN CLOB CHARACTER SET ANY-CS,
pattern lN VARCHAR2 CHARACTER SET lob-loc%CHARSET,
offset lN INTECER := 1,
nth lN INTECER := 1);
PRACMA RESTRICT-REFERENCES(i nstr,
WNDS, RNDS, WNPS, RNPS);
The parameters and return value for INSTR are described in the
following table:
LOADFROMFILE
PROCEDU RE LOADFROMFILE(
dest_lob lN OUT BLOB,
src_lob lN BFtLE,
amount lN INTECER,
dest_offset lN INTECER := 1;
src_offset lN INTECER := 1);
v_Fifelocator BFfLE;
v_CLOBLocator CLOB;
v_SQLCursor INTEGER;
v_Start.Point INTEGER := 1;
v_EndPoint INTEGER;
v_SQlStatemenr VARCLAR2 (32000) ;
v_Statement.Length TNTEGER;
V-RC INTEGER;
BEGfN
-- Initialize the characLer focator for writing. Note that we
-- have to sefect a CLOB from a table FOR UPDATE. This
locks
-- t.he row; and is a requirement for LOADFROMFILE.
SELECT clob col
TNTO v_CLOBLocator
FROM lobdemo
WHERE key = -1
FOR UPDATE;
-- Clean up.
DBMS-LOB. FILECLOSE (v-FiIelocauor) i
DBMS_SQL. CLOSE_CURSOR (v_SQLCursor ) i
EXCEPTTON
WHEN OTHERS THEN
-- Cfose the cursor and fil-e, and reraise.
FILECLOSE ( v-Fi leLocator ) t
DBITIS_LOB .
DBMS_SQL . CLOSE_CURSOR ( v_SQLCursor ) ;
DATCF.
END FiLeExec;
Assuming that you have created a directory statements which contains the
following file:
-- Availa.ble online as inserts.sql
INSERT INTO temp_table (num_co], char_co1)
VALUES (1, 'hello')
BEGTN
Fj-IeExec(,STATEMENTS,,,i,nserts.sqt,,,
/, ) ;
END,.
READ
READ is used to return a portion a given offset. lf
du
the end of the l_OB is reached
s returned as zero,
and NO DATA_FOUND is raised to accept all four
LOB types with:
Datatype
Parameter Description
lob_loc BLOB, CLOB, LOB from which to read the data.
NCLOB, BFILE
amount BINARY INTECER Number of bytes (BLOB, BFILE) or
characters (CLOB, NCLOB)to read.
The actual number of bytes or
characters read is returned.
offset INTECER Offset in bytes (BLOB, BFILE)or
characters (CLOB, NCLOB) into
lob_loc to start the read, starting at 1.
buffer VARCHAR2, RAW Output buffer to receive the data.
SUBSTR
DBMS_LOB.SUBSTR beh.rves jrrst like tlre SUBSTR defined in package
STANDARD. lt is Lrsedto r€.tLrnr.r portion of .r LC)8, sinrilarto READ.
SUBSTR is overloaded to.rccept.rllfour kinds of LOBs lvith:
844 OracteS pUSeL programming
TRIM
TRIM is used to remove data from the end of a LoB. Unlike ERASE, which
replaces portions of a LoB with spaces or NULLs, TRIM deletes the data,
and shortens the internal length. rt is overloaded to accept both BLoBs
and CLOBs with
where lob-loc is a locator for the LoB to be trimmed , and newlen is the
new length of the LOB. Any data past newlen will be deleted. lf newlen is
greater than the size of the LoB, the error , oRA-22g26: specified trim
length is greater than current LoB value's length" is raised. lf lob_locis
NULL, then VALUE-ERROR is raised. However, if you cail TRIM on an
empty LoB, no error is raised and the LoB is unchanged. The following
example illustrates the behavior of TRIM.
WRITE
DBMS-LoB.wRrrE is used to write data into a
section of a LoB. rt will
overwrite any existing aa11i1 the range specified.
rf the offseiis beyond the
lgls,h of the destination LoB, then ,p"".", or zerobytes are inserted as
filler. WRIrE is overloaded to accept both cloBs
and NCLoBs with
PROCEDURE WRTTE(/ob_loc tN OUT BLOB,
amiunttN Bt NARY_INTECER,
o/fset lN |NTECER,
buffer lN RAW);
Exceptions Raised by
DBMS LOB Routines
Table 27-2 descibes the exceptions that can be raised by the DBMS-LOB
routines. For more information, see the descriptions of the individual routines
in the previous sections. Except where noted, all these exceptions are defined
in DBMS LOB.
DBMS LOB
Equivalent
OCI Function Function Description
OClLobAppend0 APPEND Appends the contents of one
LOB value to another LOB
OClLobAssign0 N/A Assigns one LOB locator to
another
OClLobCharSetForm0 N/A Returns the character set form
for a given LOB
OClLobCharSetld0 N/A Returns the character set lD for
a given LOB
OClLobCopy0 COPY Copies a portion of a source
LOB into a destination LOB
OClLobErase0 ERASE Erases part of a LOB from a
specified offset
OClLobGetlength0 CETLENCTH Returns the length of a LOB or
BFILE
OClLoblsEqual0 N/A Checks if two LOB locators
point to the same LOB value
OCILobLocatorlslnit0 N/A Checks if a given LOB locator is
initialized
OClLobLocatorSize0 N/A Returns the size of a LOB locator
OClLobRead0 READ Reads a specified portion of a
source LOB or BFILE into a
supplied buffer
OClLobTrim0 TRIM Truncates a LOB
OClLobwriteO WRITE Writes data from a buffer into a
LOB starting at a given offset,
overwriting existing data
OClLobFileOpen0 FILEOPEN Opens a BFILE
OClLobFilelsOpen0 FILEISOPEN Returns TRUE if a BFILE is open
DBMS LOB
Equivalent
OCI Function Function Description
OClLobFileExists0 FI LEEXI STS Checks whether a BFILE exists
OClLobFileCloseO FILECLOSE Closes a BFILE
OClLobFileCloseAll0 FILECLOSEALL Closes all BFILEs currently open
OClLobFileSetNameO N/A Sets the name of a BFILE
in a locator
OClLobFilecetName0 FILECETNAME Returns the name of a BFILE
N/A COMPARE Compares portions of two
LOB values
N/A INSTR Used to pattern match within
a character LOB
N/A SUBSTR Returns a specified portion of a
LOB value
N/A LOADFROMFILE Copies a BFILE into a CLOB
or BLOB
PUSQL at Work:
Copying LONG Data into a LOB
As we have seen in this chapter, LoBs offer many advantages over oracleT
LONG and LONC RAW types. As a result of these, you may want to
convert existing data in LONC columns to an equivalent LOB. The
Long2lob procedure is designed to do exactly that, entirely in pLlSeL.
850 Oracle8 PUSQL programming
Long2lob uses DBMS_seL to fetch the LONG data piecewise, and then
DBMS_LOB ro insert it piecewise into rhe LOB. (See Chapter 15
for
information on DBMS_seL.)The procedure is defined as follows:
EXCEPTION
WHEN OTHERS THEN
-- Clean up, and reraise the error.
DBMS-SQL. CLOSE-CURSOR ( v-CursorID ) ;
RAISE;
END Long2lob;
key NUMBER,
longr_col LONG
);
INSERT INTO fong-tab (key, long-col)
VALUES (100,
'abcdef ghi jkfmnopqrstuvwxyZABCDEFGHIJKL}INOPQRSTlt\'/WZYZabcdef qihi jklmn
opqrstu\ vxyzABCDEFGHIJKLMNOPQRSTLIVWZYZabcdefghiiklmrropqrstu\,^r'/xyzABC
DEFGHIJKLMNOPQRSTLIWZYZabcde fghij klmnopqrs tu\/wT'yzABCDEFGHIJKLMNOPQR
STtryWZYZabcdefghij klmnopqrstu\TwxyzABCDEFGHI.IKLMNOPQRSTUVU/ZYZabcde fg
hi j klmnopqrstu\ vxyzABCDEFGHIJKLMNOPQRSTUWZYZabcdef ghi j klmnopqrs tuv
wxyZABCDEFGHI.TKLMNOPQRSTUI/WZYZabcdefghi j klmnopqrstuvwxyzABCDEFGHIJK
LMNOPQRSTUVWZYZabcdef ghi j klmnopqrstuv\^/xyzABCDEFGHI'-IKLMNOPQRSTU\JWZYZ
abcdef ghi j klmnopqrstur,'wxyzABCDEFGHI,fKLMNOPQRSTUWZYZabcdef ghi j klmno
pqrs tu!'wxyzABCDEFGHIJKLMNOPQRST'Ln4\iZYZabcdef ghi j klnnopqrs tuvwxyzABCD
EFGHI JKLMNO PQRSTWWZYZ abc de f gh i j klmnopqr s tuvwxyzABCDEFGHI JKLMNOPQRS
TrJWIZYZabcdefqhi j klmnopqrs tu\/wxyzABCDEFGHIJKLMNOPQRSTII-JWZYZabcde fgh
i j klnnopqrs tuvwx\.zABCDEFGHIJKLMNOPQRSTWWZYZabcde fghi j klmnopqrs tuvwxy
zABCDEFGHI.IKLMNOPQRSTUVWZYZabcdefqhij klmnopqrstuvuD.yzABCDEFGHIJKLMNOP
QRSTL'VWZYZabcdefqhijklmnopqrstuvwxlzzABcDEFGHIJKI,IOJOPQRSTTJVINZYZ');
We can move the data from long-col into lobdemo by calling Long2lob
with the following:
Summaty
ln this chapter, we have examined the oracle8 implementation
of LoBs
(large objects). The four different types
of LoBs-CLoBs, NCLoBs, BLoBs,
and BFILEs-are used to store,diffeient types of data, which
can be up to 4
gigabytes in length. Data can be stored internar to oracre,
anJ thus be
managed by the database, or it can be stored external to
oracle, and thus
ing system. We also examined the
SQL interface to manipulate LOB
e will look at improving the
ons.
856 OracleS PUSQL Programming
NOTE
On some systems (such as Windows 3.1) an
Oracle instance consists of a single process
only. This process is responsible for all
database administration, in addition to
serving as a shadow process. The shared
pool behaves the same, however.
Processes
When an instance is started, a number of Oracle background processes are
started. These processes communicate with each other via shared memory,
known asthe SCA (system global area). All of the Oracle processes can
Chapter 22: Performance and Tuning 857
Other
Oracle
Processes
User User
Process Process
read and write to various data structures in the SCA. Each process is in
charge of a different aspect of running the database. Some of these
processes are described in Table 22-1. A full discussion of how these
processes work is beyond the scope of this book; for more information, see
Oracle Server Concepts. Here, we will examine user and shadow processes.
Process Description
Database Writer (DBWR) Writes changed information from the buffer
cache in the SCA to the database files.
Process Monitor (PMON) Cleans up after failed user processes, such as
releasing locks and rolling back any
uncommitted SQL statements.
System Monitor (SMON) Performs instance recovery (if necessary) when
the instance is started. Also responsible for
freeing temporary segments and coalescing free
space in the SCA.
Recover (RECO) Resolves fai I ures with d istributed transactions.
RECO is only present when the Distributed
Option is used.
Log Writer (LCWR) Writes the redo log buffer to the redo log on disk.
LCWR and DBWR work together to ensure that
all committed information is properly written
before the commit is successful.
Archiver (ARCH) Copies full redo logs to an offline storage device,
such as a tape drive. ARCH is only running when
the database is in ARCHIVELOC mode.
Snapshot Refresh (SNp) Refreshes table snapshots and runs database
jobs (see Chapter .lB).
Shadow Process Manages the information transfer between the
user process and other database resources.
User Process Runs a user application, sending SeL
statements and PL/SQL blocks to the database.
Dispatcher Process Allows multiple user processes to share a single
shadow process, as part of the multithreaded
server. The user processes connect to the
dispatcher, which in turn passes information on
to the shadow process. The connections
between the user and dispatcher process must
use SQL*Net version 2.
per user process. With the multithreaded server, a single shadow process
can manage multiple user processes, with the help of ihe dispatcher
processes. For more information on the multithreaded server and how to
configure it, see Oracle Server Concepts.
Memory
The memory used by the instance is partitioned into different areas, which
are used by different processes. There are four different kinds of memory:
the shared pool, DB block cache, redo log buffer, and the process global
area (PCA). All but the PCA are allocated as part of the SCA and are thtrs
available to all processes. The SCA is completely allocated when the
instance starts up. lts size is determined by various INIT.ORA parameters,
i ncl ud i ng SHARE D_POOL_S lZE, LOC_B U FFER, and DB_B LOCK_B U FFERS.
For more information on these and other INIT.ORA parameters, see the
Orac I e Se rver Refe re nce.
SHARED POOL The shared pool is the memory structure that most
affects the performance of PL/SQL. The shared pool contains the text of
SQL statements and PL/SQL blocks sent to the database, along with the
parsed representation of them. ltems in the shared pool do not necessarily
remain there forever; they are aged out of the pool when they are no longer
necessary. We will see how this works and examine the shared pool in
detail shortly.
REDO LOG BUFFER The redo log buffer behaves the same as the DB
block cache except that it contains redo blocks rather than data blocks.
Redo information is generated by SQL statements and PL/SQL blocks as
they are processed. This redo information is used in case of instance failure
860 OracleS PUSQL Programming
and for read-consistency. LCWR is responsible for writing the blocks irr the
redo log buffer to the online redo logs.
PGA Each shadow process allocates memory for its own use. This
memory is known as the process globalarea (pcA). lnformation in the pcA
is kept in the scA. This is necessary because a session can migrate between
shadow processes with MTS.
Files
The database uses three different kinds of operating systern files, each of
which stores different kinds of information. Different processes are in
charge of maintaining different files. The three kinds of files are database
files, redo log files, and control files. These files are different from external
files used b;rthe urL_FILE package (see Chapter 1B) and external files used
to store BFILEs (see Chapter 21) in Or-acleB.
DATABASE FILES These files srore the actual data found in the
database. This includes table and index data, code for stored subprograms,
view definitions, and sequence information, along with the data dictionary
itself. DBWR is responsible for writing to database files, and the shadow
processes can read from them.
REDO LOG FILES The redo log records all of the changes made to
database objects. This information is used to generate a read-consistent
information has been written to each. LCWR also modifies the control files,
and ARCH is responsible for recording these changes in the otTline storage.
this can result in shared pool fragmentation-the space for a new object
may be available, but it is not contiguous. When there is not enough
memory in the shared pool for a new object, the following Oracle error is
returned:
This can happen either because the shared pool is not big enough, or the
space in it has become fragmented.
You can issue this command from any account with the ALTER SYSTEM
system privilege. The shared pool can be flushed while the database is still
running without affecting current applications. This ALTER SYSTEM
command is not usually issued from an application; rather, it is issued from
a DBA session when necessary.
The shared pool is also flushed when the instance is brought down.
When an instance is brought up, the shared pool is empty because no SeL
has been executed yet.
package from the trigger. The trigger thus consists only of the call to the
package, which is comparatively short.
Packaging your triggers is not necessary in OracleZ Release 2.3
because triggers are stored in compiled form with this release of
PLlsQL and the database. Calling packaged procedures from a trigger is
still a good idea, however. This way the code can be called from oiher
places as well.
NAME
TYPE CODE_SIZE
DBMS_OUTPUT
PACKAGE 388
DBMS-OUTPUT
PACKAGE BODY 62I7
DBMS-OUTPUT
SYNONYM 0
DBMS-PfPE
PACICAGE 699
DBMS-PTPE
PACKAGE BODY 6427
DBMS-PfPE
SYNON\'}4 0
STANDARD
PACKAGE I0494
STANDARD
PACKAGE BODY 22400
The code-size corumn in this view wiil
contain the size of the object.
You can query dba-object_size for ail
of the onj".,, y-o, commonry access.
Session Memory
The session memory usage for a particurar
database session can be
determined from the v$slsstat and vgstatnu."
you first need to identify a database
ui"*r. in ord",. to do this,
session identifier with a query such
as
SeL> SELECT sid
2 FROM v$process p, v$session s
3 WHERE p.addr = s.paddr
4 am s.username = ,SySTEM,;
SID
we know the identifier, we can determine the session memory for this
session with
VALUE
941 04
Thus the memory usage for this session so far is 94,7O4 bytes. This
query should be run for a session after it has been running for some time,
since it returns the maximum amount of memory used by a session so far,
not the maximum amount it will use. Multiply this by the number of
sessions to determine the necessary shared pool size.
Pinning Objects
KEEP
The DBMS-SHARED-POOL.KEEP procedure is used to pin objecrs in the
pool. Packages and sQL statements can be pinned. ln oracle8, sequences
and triggers can also be pinned. KEEP is defined with
The parameters are described in the following table. once an object has
been kept, it will not be removed until the database is shut down or the
DBMS_SHARED_POOL. U N KEEP procedure is used.
UNKEEP
UNKEEP'is the only way to remove a kept object from the shared poor.
Kept objects are never aged out automatically. UNKEEp is defined with
The arguments are the same as for KEEP. lf the specified object does not
already exist in the shared pool, an error is raised.
stzEs
SIZES will echo the contents of the shared pool to the screen. lt is
defined with
objects with a size greater than minsize will be returned. sIZES uses
DBMS-OUrPUT to return the data, so be sure to use ,'set serveroutput on,l
in sQL*Plus or server Manager before calling the procedure. For more
informajion on DBMS_OUTPUT, see Chapter 13.
EXPLAIN PLAN
The EXPLAIN PLAN sQL statement will determine an execution plan for a
given statement and inseft it into another database table. The format for
EXPLAIN PLAN is
where sql_statement is the statement you want to explain. The plan will be
inserted into plan_table.lf plan_table isn't specified, then it defaults to
PLAN_TABLE. This table can be created with:
EXPLAIN PLAN
SET STATEMENT-ID = /QueTy 1, FoR
SELECT rs.course, rs.department, students.ID
FROM registered_students rs, students
WHERE rs.student_id = students.id
AND students.last_name =, Razmataz,
;
We will discuss how to interpret the execution plan later in this chapter,
in the section "Using the Plan."
TKPROF Utility
The EXPLAIN PLAN statement is useful for determining the execution
plan, as we saw in the previous section. The TKPROF utility, however,
can give us the execution plan as well as statistics about how well the
SQL statement actually performed. ln order to use TKPROF, first you need
to get a SQL trace file for your session. TKPROF is then used to format the
trace file and make it readable. ln order to generate a trace file, issue the
SQL command
before any SQL statements you want to examine. This will start a trace file,
which will contain information about any subsequent SQL statements or
PL/SQL blocks submitted to the database. lnformation will be dumped to
the trace file until the session ends or tracing is turned off with
CAUTION
ALTER SESS/ON is not allowed in a PUSQL
block, since it is not a DML statement. You
can issue the ALTER SESS/ON before issuing
the block, however. Alternatively, you can
trace SQL statements outside of a block.
COURSE DEP ID
not specified, the SQL statements will appear in the order they were
submitted. Otherwise, you can sort based on one or more of the options
listed in Table 22-2. To specify more than one sort option, use the syntax
To include an execution plan in the trace file, specify a user name and
password in the EXPLAIN option. TKPROF will create a plan table, run
EXPLAIN PLAN into this table, select the output into the file, and drop the
table. lf specified, only num_printstatements will be included in the file,
after sorting.
We can format our trace file with
*+*************************************************************
872 OracleS PUSeL programming
The statement itself, statistics about the execution of the statement, and
the execution plan are all included in the output. ln this case, no CpU
time
was necessary for the pa.rse, since this statement had been executed already
and thus was already in the shared pool. (The vgsql and vgsqlarea data
Chapter 22: Performance and Tuning 873
dictionary views can be used to see which statements are currently in the
shared pool.) Note, however, that the parse count is still .1, because a parse
call was issued to the database.
NOTE
The trace file vyill also show the recursive
SQL -sfaferrrents generated automatically by
your SQL. For any given statement, Oracle
can is-sue Ltp to six recursive statements,
which do such things as check fhe NIS
-setting;-sand veriiy object privileges. Because
the trace file shows all of the SeL
-srale/lte/l[-s, recursive and otherwise, it can
be a useftrl debugging technique.
TIP
When )/ou enter f/re -stafenrent, do not enter
the trailing senticolon. li it is there, it *i!l be
-sent fo t/re d.rt.lb.r.se.?-s part oi the -st.tlente/lt.
Ihe dat.lb.r-se. rr i// then retLtrn "ORA-\)l l:
i nv,t I i d ch.?r.t(-le./. "
ln order to r.'ier..'a pl.rrr, sinrpl,v click on the toolb.rr button ior the
desired platl, tlt.select frotrt the Pl.tn nrenu. Yorr c.lr.r choose lr rrrtr tlrree
defaLrlt optinrizer nrodes or sLrpplr,\,our.o\\,rr with optinrizer hints. The
def.rult pl.rns inclLrde the Rule-based optinrizer.rnd the First Rol,r,and All
R.orvs cost-based optinrizer r.r.rodes. FigLrre )2-3 sholvs the Rule-based
optinrizet' pl.rn for the SQL st.ttentent.
ltr.
#
1F
#+
H
:k
Fi:
6.i
ti!::
tu
i:*
I;'
,l.l
j.
:1
ln order to look at the execution statistics for the statement, select the
statistics option from the Performance menu. This allows you to view the
statistics for different optimizer modes and compare the results in either a
graphical or textual format. Figure 22-4 shows the statistics window with
results from the Rule-based optimizer. Results from the other optimizer
modes can be viewed by clicking on the appropriate tabs in the window,
and the compare button will allow you to view side-by-side comparisons
for the different modes.
The Plan Analyzer has many more features than those shown here.
other features include the ability to analyze database objects used in a
given statement and step through each step of a given plan, with an
explanation for each one. For more information about plan Analyzer and its
features, see the online SQl-Station documentatron.
ih Ai l lalue
Iirne 5;c :lepsed Ll Ll5 UOF
otil L.FL I L-ro tl Llo
rlus Fleed LI rl
lrQ hend {4
LrgU e Ll Ll
ll0Dh srreIbyles]
I'les-rrqirg lsltsbBse LBlls -l
,lLr Lrt sttstenrents
0 Ll
rEtlE\;l rLrils L]
lshed HLrNs Ll
lompu,u I
L]
Help I chse I
NESTED LOOP
A NESTED LOOP operatiort combines the result sets from two other
operations a and b. Rows in a and b are compared according to a
condition, and those that match are kept. ln this case, the condition is
tlre loin condition "rs.student-id = students.id" given in the statement.
Whenever a join is used, a NESTED LOOP operation is required
for execution.
TABLE ACCESS(FULL)
A fLrll table scan simply retrieves all rows from a table. ln this case, a full
table scan is necessary for registered-students since there are no indexes
created on this table.
Network lssues
Once the SQL statement has made it to the clatabase, the structure of the
statement determines the execution plan and the resultant performance.
However, the SQL st:ltemcni has to lle sent to the rlatabase first, from the
Llser process to the shadow process. Even if tlre user and shaclow processes
Chapter 22: Performance and Tuning 877
are running on the sarne machine, the SQL staternent or PL/SQL block still
needs to be passed between them. ln most applications, the majority of the
processing time is spent in network transmission. Thus, reducing network
traffic is a prime component for application tuning. There are three
techniques available for reducing network traffic: using client-side PLlSeL,
avoiding unnecessary reparsing, and using the Oracle array interface.
Although the latter two methods are primarily applicable when using OCI
or the Oracle precompilers, they are still relevant to PL/SQL.
Array Processing
The precompilers and oCl can send and retrieve data using host arrays.
This technique is known as the oracle array interface. Thiiis a very useful
method, since it allows large amounts of data to be sent over the network
as one unit, rather than in several trips. For example, if you are retrieving
.100
rows, you can do it in one fetch, which brings back all 100 rows,
ratherthan in lo0fetches, each of which returns one row. This approach is
used in SQL*PIus.
PL/SQL does not directly use the oracle array interface, since it does
not store arrays the same way as a host array. pL/SeL tables are
implemented differently, as discussed in Chapter 3. However, the array
interface should be used whenever possible. lf you are issuing pl/sel
commands from oCl or the precompilers, use the array interfice for the
other sQL statements in your application. For more information on how to
use host arrays, consult the precompiler and/or OCI documentation.
Summarrf