Oracle8
Enterprise Edition Getting Started
Release 8.0.5 for Windows NT A64416-01 |
|
This chapter describes Windows NT-specific issues for application
developers.
Specific topics discussed are:
This section describes how to create and use external procedures
on Windows NT.
External procedures are functions written in a third-generation
language (3GL), such as C, and callable from within PL/SQL or SQL as if
they were a PL/SQL procedure or function. External procedures enable you
to take advantage of the strengths and capabilities of a 3GL programming
language in a PL/SQL environment.
The main advantages of external procedures are:
You can use external procedures to perform specific processes, such as:
Follow these instructions to create and use an external procedure:
This section describes:
Follow the procedures in Oracle8 Enterprise Edition Installation for Windows NT to install these products on your Windows NT server:
Contains PL/SQL, from which external procedures are called, and the PL/SQL external procedure program (EXTPROC), which executes external procedures
Note: You must also have a C compiler and linker installed on your system to build DLLs. |
If you install Net8 Server from your Oracle8 Enterprise Edition
CD-ROM, your server network files are automatically configured to use external
procedures.
When PL/SQL calls an external procedure, the Net8 listener launches a session-specific process called EXTPROC. Through Net8, PL/SQL passes the following information to EXTPROC:
EXTPROC then loads the DLL and invokes the external procedure.
If you copy your Oracle7 server network files into your Oracle8 network files directory, the following files must be manually configured for the external procedure behavior described above to occur:
See "Configuring External Procedure Calls" in Chapter 8 of
Net8 Getting Started for Windows NT and Windows 95/98.
.
Using a 3GL programming language, such as C, you can write
functions to be built into DLLs and invoked by EXTPROC. The following is
a simple Microsoft Visual C++ example of an external procedure:
Note: Since external procedures are built into DLLs, they must be explicitly exported. In this example, the dllexport storage class modifier exports the function find_max from a dynamic link library. |
#include <windows.h> #define NullValue -1 /* This function simply returns the larger of x and y. */ long __declspec(dllexport) find_max(long x, short x_indicator, long y, short y_indicator, short *ret_indicator) { /* It can be tricky to debug DLL's that are being called by a process that is spawned only when needed, as in this case. Therefore try using the DebugBreak(); command. This will start your debugger. Uncomment the following line and you can step right into your code. */ /* DebugBreak(); */ /* first check to see if you have any nulls */ /* Just return a null if either x or y is null */ if ( x_indicator==NullValue || y_indicator==NullValue) { *ret_indicator = NullValue; return(0); } else { *ret_indicator = 0; /* Signify that return value is not null */ if (x >= y) return x; else return y; } }
After you have written your external procedure(s) in a 3GL
programming language, use the appropriate compiler and linker to build
a DLL, making sure to export the external procedures, as noted above. See
your compiler and linker documentation for instructions on building a DLL
and exporting its functions.
After building the DLL, you can move it to any directory
on your system. For the example above, you can build the external procedure
find_max into a DLL called EXTERN.DLL. To build the above example, go to
ORACLE_HOME\ RDBMS80\EXTPROC and type MAKE.
Once you have built a DLL containing your external procedure(s), you must register your external procedure(s) with the Oracle8 database. This involves two distinct steps:
C:\> SVRMGR30
SVRMGR> CREATE LIBRARY externProcedures AS 'C:\ORANT\RDBMS80\ EXTPROC\EXTERN.DLL';
Note: The DBA must grant EXECUTE privileges on the PL/SQL library to users that want to call the library's external procedures from PL/SQL or SQL. |
Do this by writing a PL/SQL subprogram that uses the EXTERNAL clause instead of declarations and a BEGIN...END block. The EXTERNAL clause is the interface between PL/SQL and the external procedure. The EXTERNAL clause identifies the following information about the external procedure:
To execute an external procedure, you must call the PL/SQL program unit (that is, the alias for the external function) that registered the external procedure. These calls can appear in:
In "Step 4: Registering an External Procedure", the PL/SQL function PLS_MAX registered the external procedure find_max. Follow the procedures below to execute find_max:
CREATE OR REPLACE PROCEDURE UseIt AS a integer; b integer; c integer; BEGIN a := 1; b := 2; c := PLS_MAX(a,b); dbms_output.put_line('The maximum of '||a||' and '||b||' is '||c); END;
SVRMGR> EXECUTE UseIt;
You can increase the speed of external procedure invocations
when making calls to external programs from PL/SQL stored procedures or
PL/SQL methods of object types in the database by taking advantage of multiple,
light-weight threads instead of a single dedicated process per user session.
To enable multi-threaded callouts:
The Services window appears.
See Appendix C, "Configuration
Parameters and the Registry" for instructions on accessing and modifying
the registry.
This enables you to use multiple, light-weight threads when making calls to EXTPROC from PL/SQL programs.
See the following documents for additional information on external procedures:
The XA Application Program Interface (API) is typically used to enable an Oracle8 database to interact with a transaction processing (TP) monitor, such as:
The Oracle XA Library is automatically installed as part
of Oracle8 Enterprise Edition. The following components are created in
your Oracle home directory:
Component | Location |
---|---|
XA80.DLL |
ORACLE_HOME\BIN |
XA80.LIB |
ORACLE_HOME\RDBMS80\XA |
XA.H |
ORACLE_HOME\RDBMS80\XA |
You can also use TP monitor statements in your client programs.
The use of the XA API is also supported from both Pro*C/C++ and Oracle
Call Interface (OCI). In either case, the XA80.DLL must be contained in
the execution path of the calling program.
To compile and link a Pro*C /C++ program:
Library | Located in... |
---|---|
XA80.LIB |
ORACLE_HOME\RDBMS80\XA |
OCI.LIB |
ORACLE_HOME\OCI80\LIB\MSVC |
|
or |
|
ORACLE_HOME\OCI80\LIB\BORLAND |
SQLLIB80.LIB |
ORACLE_HOME\PRO80\LIB\MSVC |
|
or |
|
ORACLE_HOME\PRO80\LIB\BORLAND |
To compile and link an OCI program:
Library | Located in... |
---|---|
XA80.LIB |
ORACLE_HOME\RDBMS80\XA |
OCI.LIB |
ORACLE_HOME\OCI80\LIB\MSVC |
|
or |
|
ORACLE_HOME\OCI80\LIB\BORLAND |
The Oracle8 database supports the use of XA dynamic registration. XA dynamic registration improves the performance of applications interfacing with XA-compliant TP monitors. For TP Monitors to use XA dynamic registration with an Oracle8 database on Windows NT, you must add either an environmental variable or a registry variable to the Windows NT computer on which your TP monitor is running. See either of the following sections for instructions:
After adding this variable, see the Oracle8 Application Developer's
Guide for information on using XA dynamic registration.
Adding an environmental variable at the command prompt affects
only the current MS-DOS session.
To add an environmental variable:
C:\> SET ORA_XA_REG_DLL = VENDOR.DLL
where VENDOR.DLL is the TP monitor DLL provided by your vendor.
Adding a registry variable affects all sessions on your Windows
NT computer. This is useful for computers where only one TP monitor is
running.
To add a registry variable:
C:\> REGEDT32
The Registry Editor window appears.
The Add Value dialog box appears:
The String Editor dialog box appears:
where VENDOR.DLL is the TP monitor DLL provided by your vendor.
The Registry Editor adds the parameter.
The registry exits.
See the following general information about XA and TP monitors:
For more information about the Oracle XA Library, see the chapter "Oracle XA" of the Oracle8 Application Developer's Guide.
This section discusses the following topics:
You must add a parameter to the registry before using ICX.
To configure ICX:
C:\> REGEDT32
The Registry Editor window appears.
ICX enables you to use a stored package called UTL_HTTP to make hypertext transfer protocol (HTTP) calls from PL/SQL, SQL, and Server Manager statements. UTL_HTTP can:
UTL_HTTP contains two similar entry points, known as packaged functions, that make HTTP callouts from PL/SQL and SQL statements:
Both packaged functions:
The declarations to use with both packaged functions are
described in the following sections.
UTL_HTTP.REQUEST takes a URL as its argument and returns
up to the first 2000 bytes of data retrieved from the given URL.
UTL_HTTP.REQUEST is specified as:
FUNCTION REQUEST (URL IN VARCHAR2) RETURN VARCHAR2;
To use UTL_HTTP.REQUEST from Server Manager, enter:
SVRMGR> SELECT UTL_HTTP.REQUEST('HTTP://WWW.ORACLE.COM/') FROM DUAL;
which outputs:
UTL_HTTP.REQUEST('HTTP://WWW.ORACLE.COM/')------------------------------------------------------
<html> <head><title>Oracle Corporation Home Page</title> <!--changed Jan. 16, 19 1 row selected.
UTL_HTTP.REQUEST_PIECES takes a URL as its argument and returns
a PL/SQL table of 2000 bytes of data retrieved from the given URL. The
final element may be shorter than 2000 characters. The UTL_HTTP.REQUEST_PIECES
return type is a PL/SQL table of type UTL_HTTP.HTML_PIECES.
UTL_HTTP.REQUEST_PIECES, which uses type UTL_HTTP.HTML_PIECES, is specified as:
type html_pieces is table of varchar2(2000) index by binary_integer; function request_pieces (url in varchar2, max_pieces natural default 32767) return html_pieces;
A call to REQUEST_PIECES can look like the example below. Note the use of the PL/SQL table method COUNT to discover the number of pieces returned, which may be zero or more:
declare pieces utl_http.html_pieces; begin pieces := utl_http.request_pieces('http://www.oracle.com/'); for i in 1 .. pieces.count loop .... -- process each piece end loop; end;
The second argument to UTL_HTTP.REQUEST_PIECES, (MAX_PIECES)
is optional. MAX_PIECES is the maximum number of pieces (each 2000 characters
in length, except for the last, which may be shorter) that UTL_HTTP.REQUEST_PIECES
returns. If provided, that argument is likely a positive integer.
For example, the following block retrieves up to 100 pieces of data (each 2000 bytes, except perhaps the last) from the URL. The block prints the number of pieces retrieved and the total length, in bytes, of the data retrieved.
set serveroutput on / declare x utl_http.html_pieces; begin x := utl_http.request_pieces('http://www.oracle.com/', 100); dbms_output.put_line(x.count || ' pieces were retrieved.'); dbms_output.put_line('with total length '); if x.count < 1 then dbms_output.put_line('0'); else dbms_output.put_line ((2000 * (x.count - 1)) + length(x(x.count))); end if; end; /
which outputs:
Statement processed. 4 pieces were retrieved. with total length 7687
The elements of the PL/SQL table returned by UTL_HTTP.REQUEST_PIECES
are successive pieces of data obtained from the HTTP request to that URL.
This section describes the exceptions that can be raised
by packaged functions UTL_HTTP.REQUEST and UTL_HTTP.REQUEST_PIECES.
The PRAGMA RESTRICT_REFERENCES enables exceptions (errors) to be displayed:
create or replace package utl_http is function request (url in varchar2) return varchar2; pragma restrict_references (request, wnds, rnds, wnps, rnps);
The PRAGMA RESTRICT_REFERENCES enables exceptions (errors) to be displayed:
create or replace package utl_http is type html_pieces is table of varchar2(2000) index by binary_integer; function request_pieces (url in varchar2, max_pieces natural default 32767) return html_pieces; pragma restrict_references (request_pieces, wnds, rnds, wnps, rnps);
This table describes possible error messages that can display:
Do not expect UTL_HTTP.REQUEST or UTL_HTTP.REQUEST_PIECES
to succeed in contacting a URL unless you can contact that URL by using
a browser on the same computer (and with the same privileges, environment
variables, etc.). If UTL_HTTP.REQUEST or UTL_HTTP.REQUEST_PIECES fails
(that is, if it raises an exception or returns an HTML-formatted error
message, yet you believe that the URL argument is correct), try contacting
that same URL with a browser to verify network availability from your computer.