1. Trang chủ
  2. » Công Nghệ Thông Tin

Oracle PLSQL Language- P23

50 292 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề External Procedures
Trường học O'Reilly & Associates
Chuyên ngành Oracle PL/SQL Programming
Thể loại essay
Năm xuất bản 2000
Thành phố Sebastopol
Định dạng
Số trang 50
Dung lượng 195,21 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

External Procedures Contents: Introduction to External Procedures Steps in Creating an External Procedure Syntax for External Procedures Mapping Parameters OCI Service Routines External

Trang 1

FOR EACH ROW

DECLARE

l_file_name images.file_name%TYPE;

l_directory VARCHAR2(30);

BEGIN

/* Determine the directory name */

DBMS_LOB.FILEGETNAME (file_loc => :NEW.image_file,

INSERT INTO images

VALUES (:NEW.image_id, l_file_name, :NEW.file_type,

INSERT INTO keywords

VALUES (:NEW.image_id, keywords_holder

And finally, we can demonstrate how an insert would be made using the object view:

INSERT INTO images_v VALUES

(Image_t (1002, BFILENAME('WEBPIX','abc.gif'), 'GIF',

1024,

Keyword_tab_t('ALPHABET', 'LETTERS')));

Appendix C, Built-In Packages, contains information about these built-in packages

Trang 2

Previous: 20.7 Object

Views Housekeeping

Oracle PL/SQL Programming, 2nd Edition

Next: 21 External Procedures

20.7 Object Views

Housekeeping

Book Index 21 External Procedures

The Oracle Library

Navigation

Copyright (c) 2000 O'Reilly & Associates All rights reserved

Trang 3

Previous: 20.8 Postscript:

Using the BFILE Datatype

Creating an External Procedure

21 External Procedures

Contents:

Introduction to External Procedures

Steps in Creating an External Procedure

Syntax for External Procedures

Mapping Parameters

OCI Service Routines

External Procedure Housekeeping

an alternative to an even more primitive approach: using a temporary table as a sort of "bulletin board" for interprocess communication.[2]

[1] See Dan Bikle, "Inter-Application Communication Using Oracle7 Database Pipes,"

Select Vol 1, No 2, Winter 93/94, p 34

[2] The original paper did not present a true UNIX daemon (which has a specific

definition to UNIX and C programmers), but rather discussed the generic idea of a

continuously running process

Temporary tables have serious limitations for this use, and even database pipe-based daemons have their shortcomings Packing and unpacking the contents of the pipe is a challenge; the daemon

typically execute in a separate Oracle session (and thus can't participate in a transaction), and the solution is inherently single-threaded Moreover, with the pipe solution, it's difficult to get return values back from the daemon to the caller What we need from Oracle is a fast, reliable way of

calling out to operating system commands or functions from within PL/SQL Better yet, Oracle

Trang 4

should allow external routines to serve as user-defined functions so that you can use them in SQL statements

Enter external procedures This long-awaited Oracle feature allows you to call anything that you can

compile into the native "shared library" format of the operating system Yes, the external procedures features is reliable; yes, it's multi-threaded; yes, communication is bidirectional; and yes, you can use external procedures as user-defined functions in SQL

Under UNIX, a shared library is a shared object or so file; under Windows NT, it's a DLL

(dynamically linked library) You can write the external routine in any language you wish, as long as your compiler and linker will generate the appropriate shared library format that is callable from C In Oracle 8.0, however, C will be the most common language for external procedures, since all of

Oracle's support libraries are written in C Curiously, Oracle has named this feature external

"procedures," although the external routines you invoke are, technically speaking, C functions (There

is no such thing as a procedure in C.) If the C function returns a value, you map it to a PL/SQL

function; if it returns no value, you map it to a PL/SQL procedure

This chapter presents a few examples of external procedures (and functions) In addition, we review the preconditions you must establish before they will work, and present the syntax for creating and

using this new feature So, the next time you hear the question about calling whatever, you can

answer, "You bet! in Oracle8."

This chapter does not discuss "distributed external procedures," which are a way of accessing

non-Oracle data sources from an non-Oracle server Despite the name, these procedures are not closely related

to external procedures Neither do we discuss at length the programming techniques that allow your 3GL code to call back to Oracle (we'll leave that to the books on programming C language access to Oracle) But we do include some samples that you can use right away

21.1 Introduction to External Procedures

How do external procedures work? How can I build my own? What are their advantages and

disadvantages? Before answering in detail, let's take a look at a quick example

21.1.1 Example: Determining Free Disk Space on Windows NT

Here is an external procedure that will discover the amount of free space on a given disk drive This example is just to get you going We won't try to explain all the details at this point This example was designed for Windows NT 4.0, but the idea can be applied to any operating system that meets the requirements for external procedures In this case, we simply make a call to the appropriate function

in the Windows kernel, rather than writing our own DLL

Windows NT's kernel, kernel32.dll, contains a routine called GetDiskFreeSpaceA, which accepts a

drive letter as an input parameter and returns four statistics about the drive When we register the routine with PL/SQL, we will provide mappings for each of these parameters to a PL/SQL parameter

Trang 5

Then, when we invoke the external procedure from a PL/SQL program, we'll use these statistics to compute the free disk space

First, we need to define a "library" to tell Oracle where the DLL lives:

/* Filename on companion disk: nt_space.sql */

CREATE OR REPLACE LIBRARY nt_kernel

AS

'c:\winnt\system32\kernel32.dll';

We'll create a package called disk_util that will contain our function, which we will call

get_disk_free_space as shown here:

CREATE OR REPLACE PACKAGE disk_util

AS

FUNCTION get_disk_free_space

(root_path IN VARCHAR2,

sectors_per_cluster OUT PLS_INTEGER,

bytes_per_sector OUT PLS_INTEGER,

number_of_free_clusters OUT PLS_INTEGER,

total_number_of_clusters OUT PLS_INTEGER)

sectors_per_cluster OUT PLS_INTEGER,

bytes_per_sector OUT PLS_INTEGER,

number_of_free_clusters OUT pls_integer,

total_number_of_clusters OUT PLS_INTEGER)

Trang 6

CALLING STANDARD PASCAL uses Pascal parameter

sectors_per_cluster BY REFERENCE LONG,

bytes_per_sector BY REFERENCE LONG,

number_of_free_clusters BY REFERENCE LONG,

total_number_of_clusters BY REFERENCE LONG,

RETURN LONG); "return code" indicating

success or failure

END disk_util;

Assuming that the DBA has set up the environment to support external procedures (see Section 21.2.1, "Step 1: Set Up the Listener" later in this chapter), we can make an easy call to compute free disk space on the C: drive:

SET SERVEROUTPUT ON SIZE 100000

Trang 7

DBMS_OUTPUT.PUT_LINE('free disk space, megabytes = '

|| free_meg);

END;

On my machine, this fragment produces the following output:

free disk space, megabytes = 214.53515625

Of course, you could put this computation in a named function or procedure, and even make it part of the disk_util package

Figure 21.1: Invoking an external procedure

21.1.2 Architecture

Let's take a look at what happens when you invoke an external procedure As shown in Figure 21.1, the process flow starts with a PL/SQL application that calls a special PL/SQL "module body." In our example above, this body defines the get_disk_free_space function PL/SQL then looks for a special Net8 listener[3] process, which should already be running in the background At this point, the

listener will spawn an executable program called extproc This process loads the dynamic library and then invokes the desired routine in the shared library, whereupon it returns its results back to PL/SQL

[3] Net8 is the name for what was formerly the Oracle SQL*Net product A Net8

Trang 8

listener is a background process, typically configured by the DBA, which enables other

processes to connect to a given service such as the Oracle server

To limit overhead, only one extproc process needs to run for a given Oracle session; this process starts with the first external procedure call and terminates when the session exits For each distinct external procedure you call, this extproc process loads the associated shared library, but only if it hasn't already been loaded

In case you are unfamiliar with dynamic linking, we've provided a few words of explanation Calling

a dynamically linked routine simply maps the shared code pages into the address space of the "user" process Then, when that process touches one of the pages of the shared library, it will be paged into physical memory, if it isn't already there The resident pages of the mapped shared library file will be shared automatically between users of that library.[4] In practical terms, this means that heavy

concurrent use of your external procedure often requires a lot less computer processing power and

memory than, say, the primitive approach you might take with database pipes

[4] This description applies to Sun's Solaris operating system as well as to Windows

NT For a more detailed discussion from a UNIX perspective, see Adrian Cockroft's

performance column, "Which is Better Static or Dynamic Linking?" in SunWorld

Online, February 1996, at

● Oracle external procedures run in a separate memory space from the main kernel processes This is a good thing; it makes it easy to prevent your custom code from stepping on the

memory used by the database server While it is technically possible to write an external procedure that would crash the Oracle server, you have to set out to do so If the external procedure crashes, the companion process, extproc, returns an error to the PL/SQL engine, which in turn reports it to the application

● External procedures provide full transaction support; that is, they can participate fully in the current transaction By accepting "context" information from PL/SQL, the procedure can call back to the database to fetch data, make SQL or PL/SQL calls, and raise exceptions In the current release, utilizing these features requires some low-level Oracle Call Interface (OCI)

Trang 9

programming but at least it's possible!

● Oracle enforces the execution of external procedures with database-level security At the first level of security, only the DBA can execute or grant privileges on the required CREATE LIBRARY statement that tells Oracle where the operating system file exists At the next level

of security, users may only invoke the external procedure if they are granted EXECUTE

privilege on it

21.1.4 Limitations

External procedures are not perfect, although their benefits far outweigh their shortcomings I have

no doubt that external procedures will find uses in many applications Here are some of the current limitations of these procedures:

● Despite the wonders of shared libraries, Oracle's architecture requires an unavoidable amount

of interprocess communication Moreover, in Oracle 8.0, extproc is single-threaded; while there is only one external procedure process per session, each session does require its own process (A future version may be multi-threaded, allowing sessions to share a smaller number

of extproc processes.)

● External procedures (at least, as they are implemented in their first release) cannot pass

parameters of any user-defined type Arguments must be conventional scalars If you wish to exchange objects or collections, a possible workaround is to write a PL/SQL module that would split them up into scalars before calling the external procedure, and reassemble them upon return

● With Oracle's current implementation, extproc closes the shared library after it's called,

meaning that libraries are not cached Although this approach could save memory, it could also mean more of a CPU hit for subsequent calls In addition, the overhead for the first

external procedure call from a given session may result in a noticeable delay in response time; however, subsequent calls are much faster

Previous: 20.8 Postscript:

Using the BFILE Datatype

Oracle PL/SQL Programming, 2nd Edition

Next: 21.2 Steps in Creating an External Procedure

20.8 Postscript: Using the

Trang 10

Previous: 21.1 Introduction

to External Procedures

Chapter 21External Procedures

Next: 21.3 Syntax for External Procedures

21.2 Steps in Creating an External Procedure

Before you try external procedures, be sure that the machine where you're running the Oracle server supports shared or dynamically linked libraries Virtually all UNIX machines qualify, as do Windows

NT machines If your own machine doesn't qualify, you can stop here, or you can investigate the use

of distributed external procedures

These are your next tasks:

1 Ensure that your DBA has enabled a listener for external procedures in your Net8

environment (This involves changes to tnsnames.ora and listener.ora.) This is a one-time job

for a given server

2 Identify or create the so or DLL file which contains the shared library

3 In Oracle, issue the SQL statement CREATE LIBRARY , which defines an alias in the data dictionary for the external shared library file This registers the program with the database engine so that it knows where to find it when it is called

4 Create the PL/SQL function or procedure body, typically within a package, that will register with PL/SQL the desired routine from the external library The body of the procedure or

function will use the EXTERNAL clause in place of a BEGIN END block

And that's it! Let's look at each step in more detail, focusing on the implementation of a random number generator for PL/SQL

21.2.1 Step 1: Set Up the Listener

What actually happens when your code needs to use the external procedure? First, your code calls a predefined PL/SQL body When the PL/SQL runtime engine notices such a call, it looks for the

special Net8 listener named EXTERNAL_PROCEDURE_LISTENER, which in turn spawns a

session-specific process called extproc It is extproc that invokes your routine in the shared library

You need to create a new listener with a specific name, EXTERNAL_PROCEDURE _LISTENER This listener process will execute alongside other listener(s) that you already have running

NOTE: You cannot change the names EXTERNAL_PROCEDURE_LISTENER or

Trang 11

extproc In the listener.ora fragment given, everything that's not in lowercase italics

must match the listing

In your listener.ora file, you will need the following entries:

/* filename on companion disk: lsnrfrag.ora /*

A short identifier that is used by Net8 to locate the listener Its actual name is rather arbitrary,

since your programs will never see it epsid has to be the same identifier in the address list and

in the SID list

full_directory_path

The full pathname to your ORACLE_HOME directory, such as /u01/app/oracle/product/8.0.3

on UNIX or C:\ORANT on Windows NT Notice that there are no quotes around the directory

this:

Trang 12

app/

oracle/admin/SID/logbookTRACE_LEVEL_EXTERNAL_PROCEDURE_LISTENER=user

The tnsnames.ora file on the machine where the server is running will need an entry like the

Again, epsid must match the key used in the listener.ora file

TIP: If you intend to use external procedures on your server, remember to modify your

database startup and shutdown procedures to incorporate the listener start and stop

commands On UNIX, this typically means editing a startup shell script

On Windows NT, a Net8 listener is automatically installed as a system service the first

time you start it from the command line However, the listener will not launch

automatically on boot unless you configure it to do so You can use the control panel to

designate which listeners launch on system startup

To remove the external procedure service on NT, delete the entries from listener.ora

and tnsnames.ora, and use the NT command instsrv <service name>

remove as follows:

instsrv OracleTNSListener80external_procedure_listener remove

(The instsrv utility is available in the NT 4.0 Server Resource Kit Without it, you'll

probably have to edit the registry.)

After making these configuration file changes, you'll need to start the new listener process In UNIX, this is typically performed from the command line:

lsnrctl start external_procedure_listener

Trang 13

If your database server is running on Windows NT, the first time you start the listener, you'll use the LSNRCTL80 command From the command prompt, for example, the command would be:

LSNRCTL80 start external_procedure_listener

Thereafter (on NT) you can start and stop specific listeners from the Services component of the

Control Panel

21.2.2 Step 2: Identify or Create the Shared Library

Step 1 is completely independent of any external procedure that you may create on your system The remaining steps, while specific to our random number procedure, include discussion that applies to almost any external procedure

Although later examples will show how to create your own shared libraries, let's start with an

example that requires no C language programming: calling a standard C library function, rand, which generates a 16-bit random number On many platforms, rand already exists in a shared object library;

on UNIX, it's often in /lib/libc.so, and on NT, in c:\winnt\system32\CRTDLL.DLL.[5]

[5] Documentation on available library functions is commonly available in UNIX man

pages or in SDK documentation on other platforms

A bit of background is in order for folks who haven't played with random number generators

Random number algorithms have certain quirks you need to realize First, such generators can be deterministic; that is, the algorithm may return the same sequence of "random numbers" every time unless first "seeded" with a quasi-random number Often, the previous random number is stored and used as a seed But for the very first call, your program provides the seed, perhaps using some

function of the current system time If you call rand later with an identical seed value, you will get an identical pseudo-random sequence

rand has a companion "seeding" function, srand, that allows you to supply your own seed value Calling srand before calling rand stores the seed value as a global in memory, for use by the next call

to rand Subsequent calls from the same session need not call srand, since rand will re-seed itself

21.2.3 Step 3: Issue CREATE LIBRARY Statement

Now that we have identified /lib/libc.so as the file containing our needed functions, the next thing we

have to do is create a library in the Oracle database This is the easy part!

Creating a library is a way of telling Oracle that we want to refer to a specific shared object file by a

programmer-defined name For many UNIX systems, /lib/libc.so will contain the needed function as

shown here:

Trang 14

CREATE OR REPLACE LIBRARY libc_l

AS

'/lib/libc.so';

Executing this command requires the CREATE LIBRARY privilege (see Section 21.3, "Syntax for External Procedures" for more details)

Note that we have to use a fully qualified pathname; attempting to use an environment variable such

as $ORACLE_BASE in the filename will not work

If your database server runs on Windows NT, your library would likely be created as follows:

CREATE OR REPLACE LIBRARY libc_l

21.2.4 Step 4: Create the PL/SQL Body

The final step is to create a function or procedure definition which registers the desired routine from the shared library This feature lets you write the body of a PL/SQL procedure or function in C instead of PL/SQL To the caller it looks like any other PL/SQL subprogram

Assuming that your C language skills are ready for any custom programming needed in Step 3, Step

4 is potentially the most complex one Because of the differences between PL/SQL arguments and C language arguments (in datatype, character set, whether they can be null, etc.), Oracle provides a lot

of "instrumentation" to allow you to properly map PL/SQL arguments to C language arguments The details of this instrumentation are described in Section 21.4, "Mapping Parameters" later in this chapter

TIP: All of the samples in this chapter put the needed modules in a PL/SQL package

One of many benefits of packages is that they enable us to use the

RESTRICT_REFERENCES pragma with our module(s) This pragma allows us to tell

Oracle that the user-defined function is "safe" and can therefore be used in SQL

statements (See Chapter 17, Calling PL/SQL Functions in SQL, for a full discussion of

this pragma.)

Returning once again to our random number example, the specification for an appropriate PL/SQL package might look like this:

Trang 15

/* Filename on companion disk: rand_utl.sql */

CREATE OR REPLACE PACKAGE random_utl

AS

FUNCTION rand RETURN PLS_INTEGER;

PRAGMA RESTRICT_REFERENCES (rand, WNDS, RNDS, WNPS,

RNPS);

PROCEDURE srand (seed IN PLS_INTEGER);

PRAGMA RESTRICT_REFERENCES (srand, WNDS, RNDS, WNPS,

RNPS);

END random_utl;

Notice that the package specification is completely devoid of clues that we intend to implement the two subprograms as external procedures We can't yet tell that rand and srand are any different from conventional PL/SQL modules And that is exactly the point! From a usage perspective, external procedures are interchangeable with conventional procedures

Our package body is blissfully short By the way, assuming that your library is defined correctly, this package will work as-is on either UNIX or Windows NT (Even in cases where you can't use the same external code on different operating systems, it may be possible to make the PL/SQL

specification the same You could then make the external code the only thing that differs which would be very desirable if you have to support multiple platforms.)

CREATE OR REPLACE PACKAGE BODY random_utl

AS

/* Tested with: (1) Solaris 2.5.1 and Oracle 8.0.3

|| (2) Windows NT 4.0 and Oracle 8.0.3

*/

FUNCTION rand RETURN PLS_INTEGER

/* Return a random number between 1 and (2**16 - 1),

NAME "rand" function's real name is lowercase

LANGUAGE C; we are calling a function written

in C

PROCEDURE srand (seed IN PLS_INTEGER)

/* Store a seed value used by external rand() function

Trang 16

different so that you can talk about (or document) the parameters independently

Notice the PARAMETERS clause in the body of srand Each of the formal parameters to the PL/SQL module must have at least one corresponding entry in a PARAMETERS clause Although there is an extensive set of defaults which can eliminate the need for this clause, this explicit PARAMETERS clause makes it perfectly clear how the parameters will be mapped between PL/SQL and C

21.2.5 Using the rand External Procedure

Now that we've "registered" the external procedure with a PL/SQL package, we can test it:

SET SERVEROUTPUT ON SIZE 100000

SELECT TO_CHAR(SYSDATE, 'SSSSS') INTO seed FROM DUAL;

/* Call the srand external procedure to store our seed

Trang 17

This brief test routine simply seeds the library routine with a quasi-random number derived from the current system time, then calls the random number generator ten times in a row

One of our trial runs produced the following results:

rand() call #1 returns 27610

rand() call #2 returns 27964

rand() call #3 returns 27908

rand() call #4 returns 21610

rand() call #5 returns 14085

rand() call #6 returns 14281

rand() call #7 returns 9569

rand() call #8 returns 9397

rand() call #9 returns 24266

rand() call #10 returns 142

Limitations of rand

It doesn't take a rocket scientist to see that the numbers from our trial run are not totally random This

isn't Oracle's fault! The problem lies with the algorithm used in rand Moreover, rand returns

numbers only in the range 1 through 65535 Many C libraries include the XPG4 standard function rand48, which overcomes these limitations at the expense of mildly increased complexity See the

companion diskette for the source code of an external procedure that uses rand48 (the rand48ut.c and rand48ut.sql files)

Previous: 21.1 Introduction

to External Procedures

Oracle PL/SQL Programming, 2nd Edition

Next: 21.3 Syntax for External Procedures

Trang 18

Previous: 21.2 Steps in

Creating an External

Procedure

Chapter 21External Procedures

Next: 21.4 Mapping Parameters

21.3 Syntax for External Procedures

Now that we've gone through the basic steps and seen examples of the kind of code you must write in order to take advantage of external procedures, let's explore each syntactic element in more detail

21.3.1 CREATE LIBRARY: Creating the External Procedure Library

Step 3 in the random number generator example we presented in the previous section uses the SQL statement CREATE LIBRARY The general syntax for this command is:

CREATE [ OR REPLACE ] LIBRARY <library name>

AS

'<path to file>';

Where:

library name

A legal PL/SQL identifier This name will be used in subsequent bodies of external

procedures that need to call the shared object (or DLL) file

path to file

The fully qualified pathname to the shared object (or DLL) file As shown above, it must be enclosed in single quotes

Here are some things to keep in mind when issuing a CREATE LIBRARY statement:

● The statement must be executed by the DBA or by a user who has been granted CREATE LIBRARY or CREATE ANY LIBRARY privileges

● As with most other database objects, libraries are owned by a specific Oracle user (schema)

Other users can refer to the library using owner.library syntax, or they can create synonyms

for the library (or use a synonym) if desired

Trang 19

● Oracle doesn't check whether the named shared library file exists when you execute the

CREATE LIBRARY statement Nor will it check when you later create an external procedure declaration for a function in that library (see Step 4) If you have a syntax error in the path, you won't know it until the first time you try to execute the function

● Setting up a listener is typically a DBA task performed (in UNIX, anyway) when the DBA is logged on as the "oracle user." However, for security reasons, Oracle recommends setting up a different OS-level user with a limited profile to run the listener for external procedures

21.3.2 EXTERNAL: Creating the PL/SQL Body

In lieu of a BEGIN END block, the body of your PL/SQL function or procedure must contain an EXTERNAL clause This section describes the content of this clause Syntactically, it looks like this:

EXTERNAL LIBRARY <library name>

[ NAME <external routine name> ]

[ LANGUAGE <language name> ]

[ CALLING STANDARD C | PASCAL ]

[ PARAMETERS (<external parameter list>) ]

[ WITH CONTEXT ];

Where:

library name

Name defined previously in the CREATE LIBRARY statement

external routine name

Name of the function as defined in the C language library If the name is lowercase, you must put double quotes around it You can omit this parameter; if you do, the name of the external routine must match your PL/SQL module's name (defaults to uppercase)

Trang 20

External parameters appear in a comma-delimited list Each item in the list is one of three things:

❍ The keyword CONTEXT, which is a placeholder for the context pointer

❍ Information about a formal parameter's mapping between PL/SQL and C

❍ The keyword RETURN and information about its mapping

The syntax and rules are discussed in "Mapping Parameters" below

WITH CONTEXT

The presence of this clause indicates that you want PL/SQL to pass a "context pointer" to the called program The called program must be expecting the pointer as a formal parameter of

type OCIExtProcContext * (defined in the C header file ociextp.h)

This "context" that we are passing via a pointer is a data structure that contains a variety of Oracle-specific information The called procedure doesn't actually refer directly to the data structure's content; instead, the structure simply facilitates other Oracle Call Interface (OCI) calls which perform various Oracle-specific tasks These tasks include raising predefined or user-defined exceptions, allocating session-only memory (which gets released as soon as

control returns to PL/SQL), and obtaining information about the Oracle user's environment

21.3.3 DROP: Dropping Libraries

The syntax for dropping a library is simply:

DROP LIBRARY <library name>;

The Oracle user who executes this command must have the DROP LIBRARY or DROP ANY

LIBRARY privilege

Oracle does not check dependency information before dropping the library This is useful if you need

to change the name or location of the shared object file to which the library points You can just drop

it and rebuild it, and any dependent routines will continue to function (More useful, perhaps, would

be a requirement that you use a DROP LIBRARY FORCE command, but such an option does not exist)

Before you drop the library permanently, you'll probably want to look in the DBA_DEPENDENCIES view to see if any PL/SQL module relies on the library

Previous: 21.2 Steps in

Creating an External

Procedure

Oracle PL/SQL Programming, 2nd Edition

Next: 21.4 Mapping Parameters

Trang 21

21.2 Steps in Creating an

External Procedure

Book Index 21.4 Mapping Parameters

The Oracle Library

Navigation

Copyright (c) 2000 O'Reilly & Associates All rights reserved

Trang 22

Previous: 21.3 Syntax for

External Procedures

Chapter 21External Procedures

Next: 21.5 OCI Service Routines

21.4 Mapping Parameters

Consider for a moment the problems of exchanging data between PL/SQL and C PL/SQL has its own set of datatypes that are only somewhat similar to those you find in 3GLs PL/SQL variables can

be NULL and subject to three-valued truth table logic; C variables have no equivalent concept Your

C library might not know which national language character set you're using to express alphanumeric values And should your C functions expect a given argument by value, or by reference (pointer)?

Given these hurdles, it would be easy to conclude that the job is impossible or, at best, difficult The good news, though, is that Oracle has thought of all these issues already, and has built a lot of options into the PARAMETERS clause to cover the possibilities So the programmer's key task is to figure out how to apply the options to a given situation

21.4.1 Datatype Conversion

Let's look first at the issue of datatype conversions Oracle has kindly provided a useful set of default type conversions Each PL/SQL datatype maps to an "external datatype," which in turn maps to an allowed set of C types as illustrated below:

PL/SQL types External types C types

The external datatypes, which are included in the PARAMETERS clause, are case-insensitive In some cases, the external datatypes have the same name as the C type, but in some others, they do not For example, the STRING external datatype maps to a char * in C

As another example, if you pass a PL/SQL variable of type PLS_INTEGER, the corresponding

default external type is INT, which maps to an int datatype in C Or if you prefer, you can override this conversion with an explicit mapping to other external types such as SHORT (maps to short in C)

or UNSIGNED INT (maps to unsigned int in C)

Table 21.1 lists all the default datatype conversions, as well as alternative conversions, allowed by Oracle's PL/SQL to C interface.For brevity, in the cases where the external datatype and the C

datatype are the same except for case sensitivity, we have listed the type name only once, in

Trang 23

lowercase Note that the allowable conversions depend on both the datatype and the mode of the PL/SQL formal parameter

Table 21.1: Legal Mappings of PL/SQL and C Datatypes

C Datatype if PL/SQL Formal Parameters are

PL/SQL Datatype IN or RETURN

IN BY REFERENCE or RETURN BY REFERENCE

Same list of types as

at left, but use a pointer (for example, the default is int * rather than int)

Same list of types as

at far left, but use a pointer (for example, the default is int * rather than int)

"Short" integer family:

Same as above, except default is unsigned int *

Same as above, except default is unsigned int *

Trang 24

BFILE, BLOB, CLOB OCILOBLOCATOR

Disallowed in this Oracle release

Disallowed in this Oracle release

[6] In the PARAMETERS clause, use the external datatype STRING, but in the C

specification, use char *

[7] In the PARAMETERS clause, use the external datatype RAW, but in the C

specification, use unsigned char *

[8] In the PARAMETERS clause, use the external datatype OCILOBLOCATOR; in

the C specification, use OciLobLocator * for parameters of mode IN, RETURN, IN BY

REFERENCE, or RETURN BY REFERENCE; use OciLobLocator ** for IN OUT or

For example, if you had a generic procedure which accepted an operating system command and

returned output from that command, your procedure body might look like this (notice the

Trang 25

INDICATOR and MAXLEN are two of five properties with which we can pass supplemental

information for any given PL/SQL parameter We pass the "indicator" in addition to the variable if it's important to detect whether the value is null Once we specify that the indicator should be

included, Oracle sets and interprets this value properly on the PL/SQL side Our C application,

though, will need to get and set this value programmatically MAXLEN, on the other hand, is a only property that gets set automatically by the PL/SQL environment; MAXLEN communicates to the C program the maximum storage that can be used for an IN OUT, OUT, or RETURN parameter

read-Each piece of supplemental information we want to exchange will be passed as a parameter, and will appear both in the PARAMETERS clause and in the C language function specification

21.4.2 More Syntax: The PARAMETERS Clause

Three types of entries may appear in the PARAMETERS clause:

● Formal parameters of the PL/SQL module

● The function return value

● A placeholder for the context area

The syntax you use to map a PL/SQL formal parameter to a C parameter is:

<parameter name> [<property>] [BY REFERENCE] [<external

datatype>]

For function return values, you use the keyword RETURN in lieu of a parameter name RETURN must appear in the last position in the PARAMETERS clause:

RETURN <property> [BY REFERENCE] [<external datatype>]

Use the third variation of the external PARAMETER clause when you have specified WITH

CONTEXT In this case, the parameter is simply

Ngày đăng: 17/10/2013, 19:15

TỪ KHÓA LIÊN QUAN