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

Oracle Built−in Packages- P17 docx

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 (78.88 KB, 5 trang )

datatype:
PROCEDURE DBMS_SQL.COLUMN_VALUE_CHAR
(c IN INTEGER,
position IN INTEGER,
value OUT CHAR,
[, column_error OUT NUMBER]
[, actual_length OUT INTEGER ]);
PROCEDURE DBMS_SQL.COLUMN_VALUE_RAW
(c IN INTEGER,
position IN INTEGER,
value OUT RAW,
[, column_error OUT NUMBER]
[, actual_length OUT INTEGER ]);
PROCEDURE DBMS_SQL.COLUMN_VALUE_ROWID
(c IN INTEGER,
position IN INTEGER,
value OUT ROWID,
[, column_error OUT NUMBER]
[, actual_length OUT INTEGER ]);
You call COLUMN_VALUE after a row has been fetched to transfer the value from the SELECT list of the
cursor into a local variable. For each call to the single−row COLUMN_VALUE, you should have made a call
to DEFINE_COLUMN in order to define that column in the cursor. If you want to use the multiple−row
version of COLUMN_VALUE, use the DEFINE_ARRAY procedure to define that column as capable of
holding an array of values.
The following procedure displays employees by defining a cursor with two columns and, after fetching a row,
calls COLUMN_VALUE to retrieve both column values:
/* Filename on companion disk: showemps.sp */
CREATE OR REPLACE PROCEDURE showemps (where_in IN VARCHAR2 := NULL)
IS
cur INTEGER := DBMS_SQL.OPEN_CURSOR;
rec emp%ROWTYPE;


fdbk INTEGER;
BEGIN
DBMS_SQL.PARSE
(cur, 'SELECT empno, ename FROM emp ' ||
' WHERE ' || NVL (where_in, '1=1'),
DBMS_SQL.NATIVE);
DBMS_SQL.DEFINE_COLUMN (cur, 1, rec.empno);
DBMS_SQL.DEFINE_COLUMN (cur, 2, rec.ename, 30);
fdbk := DBMS_SQL.EXECUTE (cur);
LOOP
/* Fetch next row. Exit when done. */
EXIT WHEN DBMS_SQL.FETCH_ROWS (cur) = 0;
DBMS_SQL.COLUMN_VALUE (cur, 1, rec.empno);
DBMS_SQL.COLUMN_VALUE (cur, 2, rec.ename);
DBMS_OUTPUT.PUT_LINE (TO_CHAR (rec.empno) || '=' || rec.ename);
END LOOP;
DBMS_SQL.CLOSE_CURSOR (cur);
END;
/
This next PL/SQL8 block fetches the hiredate and employee ID for all rows in the emp table and deposits
values into two separate PL/SQL tables. Notice that since I know there are just 14 rows in the emp table, I
need only one call to the EXECUTE_AND_FETCH function to fetch all rows.
[Appendix A] What's on the Companion Disk?
2.3.8 Retrieving Values 71
/* Filename on companion disk: arrayemp.sp */
CREATE OR REPLACE PROCEDURE showall
IS
cur INTEGER := DBMS_SQL.OPEN_CURSOR;
fdbk INTEGER;
empno_tab DBMS_SQL.NUMBER_TABLE;

hiredate_tab DBMS_SQL.DATE_TABLE;
BEGIN
DBMS_SQL.PARSE
(cur, 'SELECT empno, hiredate FROM emp', DBMS_SQL.NATIVE);
/* Allow fetching of up to 100 rows. */
DBMS_SQL.DEFINE_ARRAY (cur, 1, empno_tab, 100, 1);
DBMS_SQL.DEFINE_ARRAY (cur, 2, hiredate_tab, 100, 1);
fdbk := DBMS_SQL.EXECUTE_AND_FETCH (cur);
/* This will show total numbers of rows fetched. */
DBMS_OUTPUT.PUT_LINE (fdbk);
/* Get values for all rows in one call. */
DBMS_SQL.COLUMN_VALUE (cur, 1, empno_tab);
DBMS_SQL.COLUMN_VALUE (cur, 2, hiredate_tab);
FOR rowind IN empno_tab.FIRST empno_tab.LAST
LOOP
DBMS_OUTPUT.PUT_LINE (empno_tab(rowind));
DBMS_OUTPUT.PUT_LINE (hiredate_tab(rowind));
END LOOP;
DBMS_SQL.CLOSE_CURSOR (cur);
END;
/
The Section 2.5, "DBMS_SQL Examples"" section provides other examples of array processing in
DBMS_SQL.
2.3.8.2 The DBMS_SQL.COLUMN_VALUE_LONG procedure
DBMS_SQL provides a separate procedure, COLUMN_VALUE_LONG, to allow you to retrieve LONG
values from a dynamic query. The header for this program is as follows:
PROCEDURE DBMS_SQL.COLUMN_VALUE_LONG
(c IN INTEGER
,position IN INTEGER
,length IN INTEGER

,offset IN INTEGER
,value OUT VARCHAR2
,value_length OUT INTEGER);
The COLUMN_VALUE_LONG parameters are summarized in the following table.
Parameter Description
c Pointer to the cursor.
position Relative position of the column in the select list.
length The length in bytes of the portion of the LONG value to be retrieved.
offset The byte position in the LONG column at which the retrieval is to start.
value The variable that will receive part or all of the LONG column value.
[Appendix A] What's on the Companion Disk?
2.3.8 Retrieving Values 72
value_length The actual length of the retrieved value.
The COLUMN_VALUE_LONG procedure offers just about the only way to obtain a LONG value from the
database and move it into PL/SQL data structures in your program. You cannot rely on a static SELECT to do
this. Instead, use DBMS_SQL and both the DEFINE_COLUMN_LONG and COLUMN_VALUE_LONG
procedures.
The following example demonstrates the technique, and, in the process, offers a generic procedure called
dump_long that you can use to dump the contents of a long column in your table into a local PL/SQL table.
The dump_long procedure accepts a table name, column name, and optional WHERE clause. It returns a
PL/SQL table with the LONG value broken up into 256−byte chunks.
/* Filename on companion disk: dumplong.sp */
CREATE OR REPLACE PROCEDURE dump_long (
tab IN VARCHAR2,
col IN VARCHAR2,
whr IN VARCHAR2 := NULL,
pieces IN OUT DBMS_SQL.VARCHAR2S)
/* Requires Oracle 7.3 or above */
IS
cur PLS_INTEGER := DBMS_SQL.OPEN_CURSOR;

fdbk PLS_INTEGER;
TYPE long_rectype IS RECORD (
piece_len PLS_INTEGER,
pos_in_long PLS_INTEGER,
one_piece VARCHAR2(256),
one_piece_len PLS_INTEGER
);
rec long_rectype;
BEGIN
if whr is NULL */
DBMS_SQL.PARSE (
cur,
'SELECT ' || col ||
' FROM ' || tab ||
' WHERE ' || NVL (whr, '1 = 1'),
DBMS_SQL.NATIVE);
/* Define the long column and then execute and fetch */
DBMS_SQL.DEFINE_COLUMN_LONG (cur, 1);
fdbk := DBMS_SQL.EXECUTE (cur);
fdbk := DBMS_SQL.FETCH_ROWS (cur);
/* If a row was fetched, loop through the long value until
|| all pieces are retrieved.
*/
IF fdbk > 0
THEN
rec.piece_len := 256;
rec.pos_in_long := 0;
LOOP
DBMS_SQL.COLUMN_VALUE_LONG (
cur,

1,
rec.piece_len,
rec.pos_in_long,
rec.one_piece,
rec.one_piece_len);
EXIT WHEN rec.one_piece_len = 0;
/* Always put the new piece in the next available row */
pieces (NVL (pieces.LAST, 0) + 1) := rec.one_piece;
rec.pos_in_long := rec.pos_in_long + rec.one_piece_len;
[Appendix A] What's on the Companion Disk?
2.3.8 Retrieving Values 73
END LOOP;
END IF;
DBMS_SQL.CLOSE_CURSOR (cur);
END;
/
To test this procedure, I created a table with a LONG column as follows (the table creation, INSERT, and test
script may all be found in dumplong.tst):
DROP TABLE nextbook;
CREATE TABLE nextbook
(title VARCHAR2(100), text LONG);
INSERT INTO nextbook VALUES
('Oracle PL/SQL Quick Reference',
RPAD ('INSTR ', 256, 'blah1 ') ||
RPAD ('SUBSTR ', 256, 'blah2 ') ||
RPAD ('TO_DATE ', 256, 'blah3 ') ||
RPAD ('TO_CHAR ', 256, 'blah4 ') ||
RPAD ('LOOP ', 256, 'blah5 ') ||
RPAD ('IF ', 256, 'blah6 ') ||
RPAD ('CURSOR ', 256, 'blah7 ')

);
I then put together this short test script. It extracts the single value from the table. (I pass a NULL WHERE
clause, so it simply returns the first −− and only −− row fetched.) It then uses a numeric FOR loop to scan
through the returned table to display the results.
DECLARE
mytab DBMS_SQL.VARCHAR2S;
BEGIN
dump_long ('nextbook', 'text', NULL, mytab);
FOR longind IN 1 mytab.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE (SUBSTR (mytab(longind), 1, 60));
END LOOP;
END;
/
Here is the output displayed in my SQL*Plus window:
INSTR blah1 blah1 blah1 blah1 blah1 blah1 blah1 blah1 blah1
SUBSTR blah2 blah2 blah2 blah2 blah2 blah2 blah2 blah2 blah2
TO_DATE blah3 blah3 blah3 blah3 blah3 blah3 blah3 blah3 blah
TO_CHAR blah4 blah4 blah4 blah4 blah4 blah4 blah4 blah4 blah
LOOP blah5 blah5 blah5 blah5 blah5 blah5 blah5 blah5 blah5 b
IF blah6 blah6 blah6 blah6 blah6 blah6 blah6 blah6 blah6 bla
CURSOR blah7 blah7 blah7 blah7 blah7 blah7 blah7 blah7 blah7
2.3.8.3 The DBMS_SQL.VARIABLE_VALUE procedure
The VARIABLE_VALUE procedure retrieves the value of a named variable from the specified PL/SQL
block. You can retrieve the value for a single variable, or, with PL/SQL8, you can retrieve the values for an
array or PL/SQL table of values. This is the header for the single−row version of the procedure:
PROCEDURE DBMS_SQL.VARIABLE_VALUE
(c IN INTEGER
,name IN VARCHAR2
,value OUT <datatype>);

The VARIABLE_VALUE parameters are summarized in the following table.
Parameter Description
[Appendix A] What's on the Companion Disk?
2.3.8 Retrieving Values 74
c The handle or pointer to the cursor originally returned by a call to OPEN_CURSOR.
name The name of the host variable included in the PL/SQL statement passed to PARSE.
value The PL/SQL data structure (either a scalar variable, <datatype>, or a PL/SQL table,
<table_type>) that receives the value from the cursor.
<datatype> can be one of the following:
NUMBER
DATE
MLSLABEL
VARCHAR2 CHARACTER SET ANY_CS
BLOB
CLOB CHARACTER SET ANY_CS
BFILE
The header for the multiple−row version of VARIABLE_VALUE is the following:
PROCEDURE DBMS_SQL.VARIABLE_VALUE
(c IN INTEGER
,name IN VARCHAR2
,value IN <table_type>);
<table_type> can be one of the following:
DBMS_SQL.NUMBER_TABLE
DBMS_SQL.VARCHAR2_TABLE
DBMS_SQL.DATE_TABLE
DBMS_SQL.BLOB_TABLE
DBMS_SQL.CLOB_TABLE
DBMS_SQL.BFILE_TABLE
The DBMS_SQL package also offers more specific variants of VARIABLE_VALUE for less common
datatypes:

PROCEDURE DBMS_SQL.VARIABLE_VALUE_CHAR
(c IN INTEGER
,name IN VARCHAR2
,value OUT CHAR CHARACTER SET ANY_CS);
PROCEDURE DBMS_SQL.VARIABLE_VALUE_RAW
(c IN INTEGER
,name IN VARCHAR2
,value OUT RAW);
PROCEDURE DBMS_SQL.VARIABLE_VALUE_ROWID
(c IN INTEGER
,name IN VARCHAR2
,value OUT ROWID);
If you use the multiple−row version of VARIABLE_VALUE, you must have used the BIND_ARRAY
procedure to define the bind variable in the PL/SQL block as an array of values.
The following program allows you to provide the name of a stored procedure, a list of IN parameters, and a
single OUT variable. It then uses dynamic PL/SQL to construct and execute that stored procedure, and finally
retrieves the OUT value and returns it to the calling block.
/* Filename on companion disk: runprog.sp */
CREATE OR REPLACE PROCEDURE runproc
(proc IN VARCHAR2, arglist IN VARCHAR2, outval OUT NUMBER)
IS
cur INTEGER := DBMS_SQL.OPEN_CURSOR;
[Appendix A] What's on the Companion Disk?
2.3.8 Retrieving Values 75

×