Tải bản đầy đủ (.pdf) (5 trang)

Oracle Built−in Packages- P8 pps

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (80.47 KB, 5 trang )

common errors.
DBMS_APPLICATION_
INFO
register_app register.sql Allows developers to easily register applications
and track resource usage statistics.
DBMS_APPLICATION_
INFO.SET_SESSION_
LONGOPS
longops longops.sql Simplifies use of this difficult procedure.
DBMS_UTILITY.
GET_PARAMETER_
VALUE
dbparm dbparm.spp Makes it easier to obtain specific initialization
values from the database instance.
DBMS_UTILITY.
DB_VERSION
db dbver.spp Converts through encapsulation the
DB_VERSION procedure into two separate
functions, so you can ask for the version or the
compatibility value, as desired.
DBMS_SQL.
DESCRIBE_
COLUMNS
desccols desccols.spp Provides a general, flexible interface to
DBMS_SQL.DESCRIBE_COLUMNS so you
don't need to declare PL /SQL tables and call
that wordy built−in procedure to obtain the
column information.
DBMS_SQL.PARSE dynconst dynconst.spp Hides the need to provide a DBMS_SQL
database mode when you parse a SQL statement.
This technique is especially useful when you are


writing code in Oracle Developer/2000 Release
1. (See the next section for details.)
DBMS_DESCRIBE psdesc psdesc.spp Hides the need to declare a dozen different PL
/SQL tables just so you can use
DBMS_DESCRIBE.
DESCRIBE_PROCEDURE.
DBMS_IJOB.REMOVE remove_all_jobs
(procedure)
job3.sql Allows the DBA to remove all jobs regardless of
owner.
DBMS_LOCK dblock dblock.sql Simplifies the use of user−named locks, as well
as maximizing their efficiency.
DBMS_IJOB.BROKEN break_all_jobs
(procedure)
job3.sql Allows the DBA to set the broken flag in all jobs
regardless of owner.
DBMS_PIPE dbpipe dbpipe.sql Provides some useful and interesting pipe
utilities, including generic message pack/unpack
and message forwarding.
DBMS_SESSION my_session mysess.sql Simplifies use of some of the programs and adds
some additional conveniences.
DBMS_SHARED_POOL. object_keeper keeper.sql Allows configurable auto−keeping of packages
in database startup scripts.
[Appendix A] What's on the Companion Disk?
1.3.5 Encapsulating Access to the Built−in Packages 26
KEEP (procedure)
DBMS_SPACE segspace segspace.sql Transforms the unwieldy procedure calls into
simple, SQL−callable functions.
DBMS_SYSTEM.
SET_SQL_TRACE_

IN_SESSION
trace trace.sql Allows the DBA to set SQL tracing on or off in
other sessions by username or session id.
1.3.6 Calling Built−in Packaged Code from Oracle Developer/2000
Release 1
If you use Oracle Developer/2000 Release 1 to build your client−side application, you can use the built−in
packages, but you should be aware of the following restrictions:[3]
[3] These restrictions are not likely to affect you when you work with Oracle Developer/2000
Release 2 or above.

You can reference only packaged procedures and functions. You cannot, for example, make reference
in your client−side code to DBMS_SQL.NATIVE (a constant) or
UTL_FILE.INVALID_OPERATION (an exception).

You must supply a value for each argument in a packaged procedure or function. You cannot rely on
default values in the headers of those programs. This is true even if those default values do not
reference elements in the built−in packages (in other words, are literal values).

You must be connected to the Oracle database before you can compile program units that reference
built−in packages. While it is possible to work on your client−side module without connecting to
Oracle, the PL /SQL compiler cannot resolve references to server−side objects like built−in packages
unless you are connected.
The following sections explore these restrictions in more detail and suggest work−arounds for making full use
of the built−in packages from within products like Oracle Forms and Oracle Reports.
1.3.6.1 Referencing packaged constants and variables
Consider the DBMS_SQL.PARSE procedure. Here is the header for this program:
PROCEDURE DBMS_SQL.PARSE
(c IN INTEGER,
statement IN VARCHAR2,
language_flag IN INTEGER);

The third argument, language_flag, can be any of the following values, as defined by constants in the
DBMS_SQL specification:
DBMS_SQL.V6
DBMS_SQL.V7
DBMS_SQL.NATIVE
Now, if you try to execute this program in an Oracle Forms program unit, as in the following,
[Appendix A] What's on the Companion Disk?
1.3.6 Calling Built−in Packaged Code from Oracle Developer/2000 Release 1 27
BEGIN
DBMS_SQL.PARSE (cur, 'SELECT ', DBMS_SQL.NATIVE);

you will receive this error:
Error 302: component NATIVE must be declared
Oracle Forms simply does not know how to interpret anything but procedures and functions in stored
packages. So what's a developer to do? You have several options:

Find out the literal value behind the named constant and use that, or

Create a stored function that encapsulates the constant and call that, or

Create a stored procedure that calls DBMS_SQL.PARSE and hides the use of the constant.
The first option would result in code like this:
BEGIN
DBMS_SQL.PARSE (cur, 'SELECT ', 1);

I suggest that you do not take this approach. You are always better off not proliferating the use of literals like
this one in your code. They are hard to understand and leave you vulnerable to errors caused by changes in the
way that DBMS_SQL behaves.
The second option (encapsulating the constant inside a function) is better. I could, for example, create a tiny
package as follows:

/* Filename on companion disk: dynconst.spp */*
CREATE OR REPLACE PACKAGE dynsql_value
IS
FUNCTION v6 RETURN INTEGER;
FUNCTION v7 RETURN INTEGER;
FUNCTION native RETURN INTEGER;
END;
/
CREATE OR REPLACE PACKAGE BODY dynsql_value
IS
FUNCTION v6 RETURN INTEGER
IS BEGIN RETURN DBMS_SQL.V6; END;
FUNCTION v7 RETURN INTEGER
IS BEGIN RETURN DBMS_SQL.V7; END;
FUNCTION native RETURN INTEGER
IS BEGIN RETURN DBMS_SQL.NATIVE; END;
END;
/
With this code in place on the server, I can then call DBMS_SQL.PARSE as follows:
BEGIN
DBMS_SQL.PARSE (cur, 'SELECT ', dynsql_value.native);

[Appendix A] What's on the Companion Disk?
1.3.6 Calling Built−in Packaged Code from Oracle Developer/2000 Release 1 28
This code is almost identical to my first example, but I am calling a function rather than referencing a literal,
and that makes all the difference.
The third option, encapsulating the call to DBMS_SQL.PARSE, is perhaps the optimal solution. Why should
you even have to bother passing the database mode? You might as well just always make it "native." Here is
some code that hides this argument entirely:
*Filename on companion disk: dynconst.spp */

CREATE OR REPLACE PACKAGE dynsql_value
IS
PROCEDURE parse (cur IN INTEGER, sql_str IN VARCHAR2);
END;
/
CREATE OR REPLACE PACKAGE BODY dynsql_value
IS
PROCEDURE parse (cur IN INTEGER, sql_str IN VARCHAR2)
IS
BEGIN
DBMS_SQL.PARSE (cur, sql_str, DBMS_SQL.NATIVE)
END;
END;
/
Now I can parse a SQL statement from within Oracle Forms as follows:
BEGIN
dynsql_value.parse (cur, 'SELECT ');

I recommend this last technique, because you will inevitably find other workaround needs having to do with
DBMS_SQL or another built−in package. Why not collect them all together in a single encapsulator package?
This point is driven home in the next section.
1.3.6.2 Handling exceptions in Oracle Developer/2000 Release 1
An earlier section in this chapter ("Exception Handling and Built−in Packages") explored the different types
of exceptions that can be raised from within built−in packages. One type in particular, the package−specific
exception, presents a challenge to Oracle Developer/2000 programmers.
Consider once again the UTL_FILE package. It declares a number of exceptions and, as noted previously, the
only way to handle those exceptions (and know which exception was raised) is to create an explicit exception
handler, as in:
EXCEPTION
WHEN UTL_FILE.INVALID_MODE

THEN

END;
Unfortunately, you cannot write this kind of code from Oracle Forms. It cannot resolve the reference to
UTL_FILE.INVALID_MODE. What can you do? If you are going to make extensive use of UTL_FILE from
Oracle Forms (or Oracle Reports), and you want to build in some robust error handling, you should probably
consider building a wrapper package around UTL_FILE.
Instead of calling UTL_FILE.FOPEN directly, for example, and risk raising an exception you cannot interpret
accurately, you might want to consider something like this:
/* Filename on companion disk: myfile.spp */
CREATE OR REPLACE PACKAGE myfile
IS
[Appendix A] What's on the Companion Disk?
1.3.6 Calling Built−in Packaged Code from Oracle Developer/2000Release 1 29
/* Document in the package specification that:
− INVALID_MODE is returned as −20100.
− INVALID_PATH is returned as −20101.
− INVALID_OPERATION is returned as −20102.
*/
PROCEDURE fopen
(loc IN VARCHAR2, file IN VARCHAR2, fmode IN VARCHAR2);
END;
/
CREATE OR REPLACE PACKAGE BODY myfile
IS
g_file UTL_FILE.FILE_TYPE;
PROCEDURE fopen
(loc IN VARCHAR2, file IN VARCHAR2, fmode IN VARCHAR2)
IS
BEGIN

g_file := UTL_FILE.FOPEN (loc, file, fmode);
EXCEPTION
WHEN UTL_FILE.INVALID_MODE
THEN
RAISE_APPLICATION_ERROR (−20100, 'Invalid mode ' || fmode);
WHEN UTL_FILE.INVALID_PATH
THEN
RAISE_APPLICATION_ERROR (−20101, 'Invalid path ' || loc);
WHEN UTL_FILE.INVALID_MODE
THEN
RAISE_APPLICATION_ERROR (−20102, 'Invalid operation);
END;
END;
/
I accomplish two things with this prototype package:
1.
I translate the package−specific exceptions to −20NNN exceptions. Therefore, my UTL_FILE
exception now has a number. I can check for that number within my client−side application and take
appropriate action.
2.
I hide the UTL_FILE.FILE_TYPE record. From Oracle Forms, I cannot even declare a record of this
type (it is not a program, so UTL_FILE.FILE_TYPE cannot be referenced from within Oracle
Developer/2000 Release 1).
With this wrapper approach, you can build a package that allows you to read and write a particular
server−side file from Oracle Forms. You would still need to build read, write, and close procedures, but the
technique should be clear.
1.3.7 Accessing Built−in Packaged Technology from Within SQL
Throughout this book, you will find documentation indicating whether a particular packaged function can be
called from within an SQL statement, or whether a packaged procedure can be called by a function that, in
turn, is called from within SQL. This section explains the significance of that capability.

If you are running a version of Oracle Server 7.1 and beyond, you can call PL /SQL functions from within
SQL statements. (If you are not running at least Oracle Server 7.1, you can skip this section −− but you
should also certainly upgrade your database software as soon as possible!) Let's take a look at an example to
give you a feel for this capability.
[Appendix A] What's on the Companion Disk?
1.3.7 Accessing Built−in Packaged Technology from Within SQL 30

×