Chapter 1: OraclePL/SQL Overview 15
can also call the FORMAT_CALL_STACK or FORMAT_ERROR_STACK from the same package
to work with thrown exceptions.
The following is a simple example:
DECLARE
local_exception EXCEPTION;
FUNCTION nested_local_function
RETURN BOOLEAN IS
retval BOOLEAN := FALSE;
BEGIN
RAISE local_exception;
RETURN retval;
END;
BEGIN
IF nested_local_function THEN
dbms_output.put_line('No raised exception');
END IF;
EXCEPTION
WHEN others THEN
dbms_output.put_line('DBMS_UTILITY.FORMAT_CALL_STACK');
dbms_output.put_line(' ');
dbms_output.put_line(dbms_utility.format_call_stack);
dbms_output.put_line('DBMS_UTILITY.FORMAT_ERROR_BACKTRACE');
dbms_output.put_line(' ');
dbms_output.put_line(dbms_utility.format_error_backtrace);
dbms_output.put_line('DBMS_UTILITY.FORMAT_ERROR_STACK');
dbms_output.put_line(' ');
dbms_output.put_line(dbms_utility.format_error_stack);
END;
/
This script produces the following output:
DBMS_UTILITY.FORMAT_CALL_STACK
PL/SQL Call Stack
object line object
handle number
name
20909240 18 anonymous block
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
ORA-06512: at line 7
ORA-06512: at line 11
DBMS_UTILITY.FORMAT_ERROR_STACK
ORA-06510: PL/SQL: unhandled user-defined exception
You will likely find the FORMAT_ERROR_BACKTRACE the most helpful. It captures the line
where the first error occurs at the top, and then moves backward through calls until it arrives at
16 OracleDatabase11gPL/SQL Programming
the initial call. Line numbers and program names are displayed together when named blocks are
involved in an event stack. Chapter 5 contains more on error management.
Wrapping PL/SQL Stored Programs
Beginning with Oracle 10g Release 2, the database now supports the ability to wrap, or obfuscate,
your PL/SQL stored programs. This is done by using the DBMS_DDL package CREATE_WRAPPED
procedure. You use it as follows:
BEGIN
dbms_ddl.create_wrapped(
'CREATE OR REPLACE FUNCTION hello_world RETURN STRING AS '
||'BEGIN '
||' RETURN ''Hello World!''; '
||'END;');
END;
/
After creating the function, you can query it by using the following SQL*Plus column
formatting and query:
SQL> COLUMN message FORMAT A20 HEADING "Message"
SQL> SELECT hello_world AS message FROM dual;
Message
Hello World!
You can describe the function to inspect its signature and return type:
SQL> DESCRIBE hello_world
FUNCTION hello_world RETURNS VARCHAR2
Any attempt to inspect its detailed operations will yield an obfuscated result. You can test this
by querying stored function implementation in the TEXT column of the USER_SOURCE table, like
the following:
SQL> COLUMN text FORMAT A80 HEADING "Source Text"
SQL> SET PAGESIZE 49999
SQL> SELECT text FROM user_source WHERE name = 'HELLO_WORLD';
The following output is returned:
FUNCTION hello_world wrapped
a000000
369
abcd
. . . et cetera . . .
This is a very useful utility to hide the implementation details from prying eyes. We will revisit
this in Appendix F.
Chapter 1: OraclePL/SQL Overview 17
Oracle 11g New Features
New PL/SQL features introduced in Oracle11g include
Automatic subprogram inlining
A continue statement
A cross-session PL/SQL function result cache
Dynamic SQL enhancements
Mixed, named, and positional notation SQL calls
A multiprocess connection pool
A PL/SQL Hierarchical Profiler
That the PL/SQL Native Compiler now generates native code
PL/Scope
Regular expression enhancements
A SIMPLE_INTEGER datatype
Direct sequence calls in SQL statements
These enhancements are briefly reviewed in the following subsections. Chapter 3 covers the
SIMPLE_INTEGER datatype. Chapter 4 covers the continue statement. Chapter 6 demonstrates
the cross-session PL/SQL function result cache, and both mixed, named, and positional notation
calls. Automatic subprogram inlining and the PL/SQL Native Compiler are covered in Chapter 9.
Chapter 16 covers web application development and the multiprocess connection pool. You will
also find more information about the Regular Expression, PL/SQL Hierarchical Profiler, and PL/Scope
in Appendixes E, G, and H, respectively.
Automatic Subprogram Inlining
Inlining a subprogram replaces the call to the external subprogram with a copy of the subprogram.
This almost always improves program performance. You could instruct the compiler to inline
subprograms by using the PRAGMA INLINE compiler directive in PL/SQL starting with the
Oracle 11g Database. You must set the PRAGMA when you have the PLSQL_OPTIMIZE_LEVEL
parameter set to 2.
Let’s say you have an ADD_NUMBERS stored function in a schema; you can then instruct a
PL/SQL program unit to inline the call to the ADD_NUMBERS function. This would be very useful
when you call the ADD_NUMBERS function in a loop, as in this example:
CREATE OR REPLACE PROCEDURE inline_demo
( a NUMBER
, b NUMBER ) IS
PRAGMA INLINE(add_numbers,'YES');
BEGIN
FOR i IN 1 10000 LOOP
■
■
■
■
■
■
■
■
■
■
■
■
18 OracleDatabase11gPL/SQL Programming
dbms_output.put_line(add_function(8,3));
END LOOP;
END;
/
The database automates inlining choices when you set the PLSQL_OPTIMIZE_LEVEL
parameter to 3. This generally frees you from identifying when it is appropriate to inline function
calls. However, these are only recommendations to the compiler. It is recommended that you let
the engine optimize your code during compilation.
Continue Statement
The CONTINUE statement has finally been added to the PL/SQL language. Some may have mixed
emotions. There are opinions that the continue statement leads to less-than-optimal programming,
but generally it simplifies loop structures.
The CONTINUE statement signals an immediate end to a loop iteration and returns to the first
statement in the loop. The following anonymous block illustrates using a continue statement when
the loop index is an even number:
BEGIN
FOR i IN 1 5 LOOP
dbms_output.put_line('First statement, index is ['||i||'].');
IF MOD(i,2) = 0 THEN
CONTINUE;
END IF;
dbms_output.put_line('Second statement, index is ['||i||'].');
END LOOP;
END;
/
The MOD function returns a zero when dividing any even number, so the second line is never
printed, because the CONTINUE statement aborts the rest of the loop. More on using this command
is in Chapter 4. Appendix J covers the MOD function.
Cross-Session PL/SQL Function Result Cache
The cross-session PL/SQL function result cache is a mechanism to share frequently accessed
functions in the SGA between sessions. Prior to the Oracle11g Database, each call to a function
with the same actual parameters, or run-time values, was cached once per session. The only
work-around to that functionality required you to code the access methods.
You designate either of the following to cache results:
RESULT_CACHE clause
or
RESULT_CACHE RELIES_ON(table_name)
The RELIES_ON clause places a limitation on the cached result. Any change to the referenced
table invalidates the function, as well as any functions, procedures, or views that depend on the
function.
The overhead when calling the function for the first time is no different than that from calling
a non-cached result. Likewise, the cache will age out of the SGA when it is no longer actively
called by sessions.
Chapter 1: OraclePL/SQL Overview 19
Dynamic SQL Enhancements
Dynamic SQL still has two varieties in the Oracle11g Database. You have Native Dynamic SQL,
also known as NDS, and the DBMS_SQL built-in package. Both have been improved in this release.
Native Dynamic SQL
In Oracle 11g, native dynamic SQL now supports dynamic statements larger than 32KB by
accepting CLOB. You access it them in lieu of a SQL statement by using the following syntax:
OPEN cursor_name FOR dynamic_string;
The dynamic string can be a CHAR, VARCHAR2, or CLOB. It cannot be a Unicode NCHAR or
NVARCHAR2. This removes the prior restriction that limited the size of dynamically built strings.
The DBMS_SQL Built-in Package
Several changes have improved the utility of the DBMS_SQL package. Starting with Oracle 11g,
you can now use all NDS-supported datatypes. Also, you can now use the PARSE procedure to
work with statements larger than 32KB. This is done by using a CLOB datatype. The CLOB replaces
the prior work-around that used a table of VARCHAR2 datatypes (typically VARCHAR2A or
VARCHAR2S). Fortunately, the DBMS_SQL package continues to support the work-around, but
you should consider moving forward to the better solution.
DBMS_SQL has added two new functions: the TO_REFCURSOR and TO_CURSOR_NUMBER
functions. They let you transfer reference cursors to cursors and vice versa. There naturally are
some words of wisdom on using these. You must open either the cursor or system reference cursor
before using them, and after running them you cannot access their old structures. Basically, the
code reassigns the interactive reference from the cursor to system reference cursor or from the
system reference cursor to the cursor.
Last but certainly not least, you can now perform bulk binding operations against user-defined
collection types. Collection types can be scalar arrays. You were previously restricted to the types
defined by the DBMS_SQL package specification.
Mixed Name and Position Notation Calls
The Oracle11gDatabase brings changes in how name and positional notation work in both SQL
and PL/SQL. They actually now work the same way in both SQL and PL/SQL. This fixes a long-
standing quirk in the Oracle database.
PL/SQL Calls
Previously, you had two choices. You could list all the parameters in their positional order or
address some to all parameters by named reference. You can now use positional reference,
named reference, or a mix of both.
The following function will let you experiment with the different approaches. The function
accepts three optional parameters and returns the sum of three numbers.
CREATE OR REPLACE FUNCTION add_three_numbers
( a NUMBER := 0, b NUMBER := 0, c NUMBER := 0 ) RETURN NUMBER IS
BEGIN
RETURN a + b + c;
END;
/
20 OracleDatabase11gPL/SQL Programming
The first three subsections show how you call using positional, named, and mixed notation.
In these you provide actual parameters for each of the formal parameters defined by the function
signature.
You can also exclude one or more values because all formal parameters are defined as
optional, which means they have default values. This is done in the subsection “Exclusionary
Notation.”
Positional Notation
You call the function using positional notation by
BEGIN
dbms_output.put_line(add_three_numbers(3,4,5));
END;
/
Named Notation
You call the function using named notation by
BEGIN
dbms_output.put_line(add_three_numbers(c => 4,b => 5,c => 3));
END;
/
Mixed Notation
You call the function using a mix of both positional and named notation by
BEGIN
dbms_output.put_line(add_three_numbers(3,c => 4,b => 5));
END;
/
There is a restriction on mixed notation. All positional notation actual parameters must occur
first and in the same order as they are defined by the function signature. You cannot provide a
position value after a named value.
Exclusionary Notation
As mentioned, you can also exclude one or more of the actual parameters when the formal
parameters are defined as optional. All parameters in the ADD_THREE_NUMBERS function are
optional. The following example passes a value to the first parameter by positional reference,
and the third parameter by named reference:
BEGIN
dbms_output.put_line(add_three_numbers(3,c => 4));
END;
/
When you opt to not provide an actual parameter, it acts as if you’re passing a null value. This
is known as exclusionary notation. This has been the recommendation for years to list the optional
variables last in function and procedure signatures. Now, you can exclude one or a couple but
not all optional parameters. This is a great improvement, but be careful how you exploit it.
Chapter 1: OraclePL/SQL Overview 21
SQL Call Notation
Previously, you had only one choice. You had to list all the parameters in their positional order
because you couldn’t use named reference in SQL. This is fixed in Oracle 11g; now you can call
them just as you do from a PL/SQL block. The following demonstrates mixed notation in a SQL call:
SELECT add_three_numbers(3,c => 4,b => 5) FROM dual;
As in earlier releases you can only call functions that have IN mode–only variables from SQL
statements. You cannot call a function from SQL when any of its formal parameters are defined as
IN OUT or OUT mode–only variables. This is because you must pass a variable reference when a
parameter has an OUT mode. Functions return a reference to OUT mode variables passed as actual
parameters.
Multiprocess Connection Pool
Enterprise JavaBeans (EJBs) just got better with the release of multiprocess connection pooling
in the Oracle11g Database. It is officially Database Resident Connection Pooling (DRCP). This
feature lets you manage a more scalable server-side connection pool. Prior to this release you
would leverage shared server processes or a multithreaded Java Servlet.
The multiprocess connection pool significantly reduces the memory footprint on the database
tier, and it boosts the scalability of both the middle and database tiers. A standard database
connection requires 4.4MB of real memory; 4MB is allotted for the physical connection and
400KB for the user session. Therefore, 500 dedicated concurrent connections would require
approximately 2.2GB of real memory. A shared-server model is more scalable and requires only
600MB of real memory for the same number of concurrent users. Eighty percent of that memory
would be managed in Oracle’s Shared Global Area (SGA). Database Resident Connection Pooling
scales better and would require only 400MB of real memory. Clearly for web-based applications
DRCP is the preferred solution, especially when using OCI8 persistent connections.
The behaviors of these models dictate their respective scalability. Figure 1-2 graphically
depicts memory use for the three models from 500 to 2,000 concurrent users.
FIGURE 1-2 Connection scalability
22 OracleDatabase11gPL/SQL Programming
The new feature is delivered by the new DBMS_CONNECTION_POOL built-in package. This
package lets you start, stop, and configure connection pooling parameters such as size and time
limit. You start the connection pool as the SYS user by using the following command:
SQL> EXECUTE DBMS_CONNECTION_POOL.START_POOL();
You must enable your tnsnames.ora file to support the connection to the shared pool. The
following enables a shared pool connect descriptor, provided you substitute a correct hostname,
domain, and Oracle listener port number:
ORCLCP =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)
(HOST = hostname.domain)
(PORT = port_number)
)
(CONNECT_DATA = (SERVER = POOLED)
(SERVICE_NAME = orcl)
)
)
The SERVER key in the connect descriptor directs connections to the connection pooling
service. You can only use the connection pool when you have a supported Oracle11gDatabase
or Oracle11g Client, though this feature could be subsequently backported. The following error
is raised when attempting to connect with an older release client or server library:
ERROR:
ORA-56606: DRCP: Client version does not support the feature
The message is signaled from the server when it fails to create an appropriate socket; it indicates
that it is dropping the remote connection pool request.
Table 1-2 lists the data dictionary views for auditing connection pools. You can use these to
monitor connections or performance characteristics.
You stop the connection pool as the SYS user by using the following command:
SQL> EXECUTE DBMS_CONNECTION_POOL.STOP_POOL();
View Description
DBA_CPOOL_INFO
The status, maximum and minimum connections, and idle
timeouts are available in this view for each connection pool.
V$CPOOL_STAT
The number of session requests, the number of times a session that
matches a request is found in the pool, and the total wait time per
session request are available in this view.
V$CPOOL_CC_STATS
The connection class level statistics for each instance of the
connection pool.
TABLE 1-2 Connection Pooling Data Dictionary Views
Chapter 1: OraclePL/SQL Overview 23
It appears that the initial release will only support a single connection pool. The connection
pool name is SYS_DEFAULT_CONNECTION_POOL. You also have three other procedures in the
DBMS_CONNECTION_POOL package to manage the connection pool: the ALTER_PARAM(),
CONFIGURE_POOL(), and RESTORE_DEFAULTS() procedures. You change a single connection
pool parameter with the ALTER_PARAM() procedure. When you want to change more than one
to all parameters, you use the CONFIGURE_POOL() procedure. The RESTORE_DEFAULTS()
procedure resets all connection pool parameters to their defaults.
This new Oracle11gDatabase feature certainly improves the scalability of web applications.
It is a critical feature that empowers the persistent connection feature introduced in the OCI8
libraries in the Oracle 10g Release 2 database.
PL/SQL Hierarchical Profiler
The hierarchical profiler delivered in the Oracle11gDatabase lets you see how all components in
an application perform. This differs from a non-hierarchical (flat) profiler that simply records the
time spent in each module. Hierarchical profilers follow the execution cycle from the containing
program down to the lowest subprogram.
The PL/SQL Hierarchical Profiler does the following:
It reports the dynamic execution profile of your PL/SQL program, which is organized by
subprogram calls.
It divides SQL and PL/SQL execution times and reports them separately.
It requires no special source or compile-time preparation, like the PRAGMA required for
recommending inlining.
It stores results in a set of database tables, which you can use to develop reporting tools
or alternatively use the plshprof command-line tool to generate simple HTML reports.
The subprogram-level summary includes information about the number of subprogram calls,
time spent in subprograms or their subtrees, and detailed information between modules.
Appendix G covers how to read and use the PL/SQL Hierarchical Profiler.
PL/SQL Native Compiler Generates Native Code
PL/SQL Native compilation changes in the Oracle11g Database. Unlike prior versions where
the PL/SQL was translated first into C code and then compiled, you can now compile directly.
Execution speed of the final code in some cases is twice as fast or an order of magnitude greater.
Oracle recommends that you run all PL/SQL in either NATIVE or INTERPRETED mode.
INTERPRETED mode is the database default, and PL/SQL modules are stored as clear text or
wrapped text. You can view stored programs by querying the ALL_SOURCE, DBA_SOURCE, or
USER_SOURCE data dictionary tables. NATIVE-mode code is compiled into an intermediate form
before being reduced to machine-specific code. A copy of the code is also stored in the data
dictionary, while the library is positioned in an external directory. You map the physical directory
to the virtual directory defined by the PLSQL_NATIVE_LIBRARY_DIR database parameter.
Natively compiled code is advantageous when the PL/SQL code run time is slow. This can
happen with compute-intensive code, but generally performance delays are caused by SQL
statement processing. You should use the new PL/SQL Hierarchical Profiler to determine if there is
a significant advantage to support your conversion effort.
■
■
■
■
24 OracleDatabase11gPL/SQL Programming
PL/Scope
The PL/Scope is a compiler-driven tool that lets you examine identifiers and their respective
behaviors in the Oracle11g Database. It is disabled by default. You can enable it for the database
or session. You should consider enabling it for the session, not the database. You enable it by
using the following command:
ALTER SESSION SET PLSCOPE_SETTINGS = 'IDENTIFIERS:ALL';
The PL/Scope utility does not collect statistics until you enable it. The statistics let you
examine how your programs use identifiers. It should be added to your arsenal of tuning tools.
Appendix H gives you a brief introduction to this new feature.
Regular Expression Enhancement
Oracle 11g Release 1 enhances the functionality of the REGEXP_LIKE and REGEXP_INSTR
functions and introduces the REGEXP_COUNT function. Appendix E discusses, reviews, and
demonstrates regular expressions using the Oracle11gDatabase regular expression functions.
SIMPLE_INTEGER Datatype
The Oracle11gDatabase introduces the SIMPLE_INTEGER. It is a derived subtype of BINARY_
INTEGER, and it has the same range of values. Unlike BINARY_INTEGER, SIMPLE_INTEGER
excludes the null value and overflow is truncated. Also, the truncation from overflow does not
raise an error. You should use the SIMPLE_INTEGER type if you opt to natively compile your
code because it provides significant performance improvements in compiled code.
This section has reviewed the Oracle11gDatabase new features, or it has referred you to
other areas of the book for more information. Clearly, the new features make upgrading very
appealing.
Direct Sequence Calls in SQL Statements
Oracle 11g finally lets you call a sequence with the .nextval or .currval inside SQL
commands, which means you can dispense with this:
SELECT some_sequence.nextval
INTO some_local_variable
FROM dual;
This book uses the old and new style. The new style is simpler and easier to use.
Summary
This chapter has reviewed the history, utility, coding basics, and recent features added to the
PL/SQL programming language. It has also explained the importance of PL/SQL, and how it can
leverage your investment in the Oracle11g database. You should now see that a combination of
SQL and PL/SQL can simplify your external application development projects in languages like
Java and PHP.
.
this in Appendix F.
Chapter 1: Oracle PL/SQL Overview 17
Oracle 11g New Features
New PL/SQL features introduced in Oracle 11g include
Automatic subprogram. LOOP
■
■
■
■
■
■
■
■
■
■
■
■
18 Oracle Database 11g PL/SQL Programming
dbms_output.put_line(add_function(8,3));
END LOOP;
END;
/
The database automates inlining