/* Filename on companion disk: delret.sp */* CREATE OR REPLACE PROCEDURE delret tab_in IN VARCHAR2, pkey_in IN VARCHAR2, where_in IN VARCHAR2, pkeys_out OUT DBMS_SQL.NUMBER_TABLE I
Trang 1/
Here is the result:
SQL> @insret.sp
New primary key = 41
Note insert failure:
ORA−00001: unique constraint (SCOTT.NOTE_TEXT_IND) violated
The same technique and steps can be used for using the RETURNING clause in UPDATEs and DELETEs when affecting single rows Let's now take a look at the slightly more complex scenario: changing multiple rows of data and returning values from those rows
2.5.7.2 RETURNING from a multiple−row delete
I want to use dynamic SQL to provide a generic delete mechanism for tables with single integer primary keys You provide the name of the table, the name of the primary key, and the WHERE clause I do the delete But such a general utility will never be used unless it can be trusted, unless its actions can be confirmed That is where the RETURNING clause comes into play
/* Filename on companion disk: delret.sp */*
CREATE OR REPLACE PROCEDURE delret
(tab_in IN VARCHAR2,
pkey_in IN VARCHAR2,
where_in IN VARCHAR2,
pkeys_out OUT DBMS_SQL.NUMBER_TABLE)
IS
cur INTEGER := DBMS_SQL.OPEN_CURSOR;
delstr VARCHAR2(2000) :=
'DELETE FROM ' || tab_in || ' WHERE ' || where_in ||
' RETURNING ' || pkey_in || ' INTO :idarray';
fdbk INTEGER;
v_pkeys DBMS_SQL.NUMBER_TABLE;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Dynamic Delete Processing: ');
DBMS_OUTPUT.PUT_LINE (delstr);
DBMS_SQL.PARSE (cur, delstr, DBMS_SQL.NATIVE);
DBMS_SQL.BIND_ARRAY (cur, 'idarray', v_pkeys);
fdbk := DBMS_SQL.EXECUTE (cur);
DBMS_SQL.VARIABLE_VALUE (cur, 'idarray', v_pkeys);
pkeys_out := v_pkeys;
DBMS_SQL.CLOSE_CURSOR (cur);
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE ('Dynamic Delete Failure:');
DBMS_OUTPUT.PUT_LINE (SQLERRM);
END;
/
In this program, I construct the DELETE statement and save it to a local variable I do this so that I can display the string for confirmation purposes and then parse it without duplicating the code I will go to great lengths (and do so on a regular basis) to avoid even the slightest repetition of code
When I bind, I call DBMS_SQL.BIND_ARRAY instead of DBMS_SQL.BIND_VARIABLE so that I can retrieve an entire list of values My call to DBMS_SQL.VARIABLE_VARIABLE performs the retrieval, and
I close the cursor The following anonymous block exercises my generic "delete and return" procedure Notice
[Appendix A] What's on the Companion Disk?
Trang 2that since I am returning an index table, I must always declare such a table to hold the values.
/* Filename on companion disk: delret.sp */*
DECLARE
v_pkeys DBMS_SQL.NUMBER_TABLE;
BEGIN
delret ('emp', 'empno', 'deptno = 10', v_pkeys);
IF v_pkeys.COUNT > 0
THEN
FOR ind IN v_pkeys.FIRST v_pkeys.LAST
LOOP
DBMS_OUTPUT.PUT_LINE ('Deleted ' || v_pkeys(ind));
END LOOP;
END IF;
ROLLBACK;
END;
/
Here are the results from execution of the previous script:
Dynamic Delete Processing:
DELETE FROM emp WHERE deptno = 10 RETURNING empno INTO :idarray
Deleted 7782
Deleted 7839
Deleted 7934
2.4 Tips on Using Dynamic
SQL
3 Intersession Communication
Copyright (c) 2000 O'Reilly & Associates All rights reserved.
[Appendix A] What's on the Companion Disk?
Trang 3Chapter 3
138
Trang 43 Intersession Communication
Contents:
DBMS_PIPE: Communicating Between Sessions
DBMS_ALERT: Broadcasting Alerts to Users
It seems that everything these days has something to do with communication Messaging technologies are consequently receiving lots of attention, but they are nothing new for Oracle Through the packages described
in this chapter, Oracle has already provided mechanisms for communication between database sessions:
DBMS_PIPE
Using database pipes with DBMS_PIPE, an application can communicate with a service routine external to the database Or, debuggers that capture PL/SQL errors can utilize the fact that
DBMS_PIPE is asynchronous with database transactions, getting the errors logged whether the transaction issued a COMMIT or a ROLLBACK
DBMS_ALERT
This package is a little different, in that it allows synchronous notification to multiple users that specific database events have occurred
3.1 DBMS_PIPE: Communicating Between Sessions
The DBMS_PIPE package provides services that allow Oracle sessions connected to the same instance to communicate messages with each other without the need for a COMMIT Sessions use DBMS_PIPE
programs to pack data into a message buffer and then send the message to a memory area in the Oracle shared
pool (the pipe), where another session can receive it and unpack the message data into local variables The database pipes implemented by DBMS_PIPE are roughly modeled after UNIX pipes Pipes may be private to the user or public, and can be written to, or read from, independent of database transactions.
The basic functionality that DBMS_PIPE introduces is the ability for Oracle sessions to communicate with each other Before the existence of database pipes, users connected to an Oracle database could communicate
or interact with each other only through the database If users needed to somehow exchange information with each other, this had to be done by reading, writing, and committing data to tables (i.e., the database was itself the communications medium) This communications model suffers from the following problems:
•
It is transactional; it relies on COMMIT for users to see messages
•
Communications are slow; they involve physical writing to disk
•
There is limited capacity due to locking issues in message tables
•
There are space management issues
The database pipes introduced through the DBMS_PIPE package establish a fast, lightweight, memory−based, nontransactional mechanism of intersession communications
The DBMS_PIPE package is most often used to provide an interface between sessions connected to an Oracle instance and service routines external to Oracle in the host operating environment In this kind of application, the service routine connects to Oracle and listens for service requests on a specific database pipe Sessions in
Trang 5the database request services by placing messages on the request pipe, and they receive data from the service routine on session−specific response pipes
Other applications you might consider developing with DBMS_PIPE include:
•
Debuggers that place error messages into pipes
•
Auditing of security violations independent of transaction success
•
Transaction concentrators to multiplex many user transactions through a single session
•
Complex calculation servers to offload long or memory−intensive computations
•
Alerters that notify sessions of important events
An example of the last application has actually been built by Oracle as the DBMS_ALERT package
(described later in this chapter), which makes extensive use of DBMS_PIPE programs to implement database alerts
3.1.1 Getting Started with DBMS_PIPE
The DBMS_PIPE package is created when the Oracle database is installed The dbmspipe.sql script (found in
the built−in packages source code directory, as described in Chapter 1, Introduction) contain the source code
for this package's specification This script is called by catproc.sql, which is normally run immediately after
database creation The script creates the public synonym DBMS_PIPE for the package Under Oracle7, no privileges are automatically granted on DBMS_PIPE Under Oracle8, the EXECUTE_CATALOG_ROLE role is granted EXECUTE privilege on DBMS_PIPE Thus, the DBMS_PIPE programs are not generally available to users
3.1.1.1 DBMS_PIPE programs
Table 3.1 lists the programs included in the DBMS_PIPE package
Table 3.1: DBMS_PIPE Programs
CREATE_PIPE Creates a public or private pipe Yes
NEXT_ITEM_TYPE Returns datatype of next item in message buffer Yes
PACK_MESSAGE_RAW Packs RAW item into message buffer No
PACK_MESSAGE_ROWID Packs ROWID item into message buffer No
RECEIVE_MESSAGE Receives message from pipe into local buffer Yes
[Appendix A] What's on the Companion Disk?