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

Oracle Built−in Packages- P16 pdf

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

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 80,37 KB

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

Nội dung

2.3.6.1 The DBMS_SQL.EXECUTE function The EXECUTE function executes the SQL statement associated with the specified cursor, FUNCTION DBMS_SQL.EXECUTE c IN INTEGER RETURN INTEGER; where c

Trang 1

2.3.6 Executing the Cursor

So you've opened and parsed the cursor You've bound your variables and defined your columns Now it's

time to get some work done.

2.3.6.1 The DBMS_SQL.EXECUTE function

The EXECUTE function executes the SQL statement associated with the specified cursor,

FUNCTION DBMS_SQL.EXECUTE (c IN INTEGER) RETURN INTEGER;

where c is the pointer to the cursor This function returns the number of rows processed by the SQL statement

if that statement is an UPDATE, INSERT, or DELETE For all other SQL (queries and DDL) and PL/SQL statements, the value returned by EXECUTE is undefined and should be ignored

If the SQL statement is a query, you can now call the FETCH_ROWS function to fetch rows that are retrieved

by that query If you are executing a query, you can also use EXECUTE_AND_FETCH to execute the cursor and fetch one or more rows with a single program call

2.3.7 Fetching Rows

You can fetch one or more rows of data from a dynamically constructed query with either the FETCH_ROWS

or EXECUTE_AND_FETCH functions

NOTE: Prior to PL/SQL8, both of these functions would return either 0 (no rows fetched) or

1 (one row fetched) With PL/SQL8 and array processing, these functions will return 0 (no

rows fetched) or the actual number of rows fetched

2.3.7.1 The DBMS_SQL.FETCH_ROWS function

The FETCH_ROWS function corresponds to the FETCH statement for regular PL/SQL cursors It fetches the next N rows from the cursor (a maximum of one if not using array processing in PL/SQL8) Here's the

specification for the function,

FUNCTION DBMS_SQL.FETCH_ROWS

(c IN INTEGER) RETURN INTEGER;

where c is the pointer to the cursor The function returns 0 when there are no more rows to fetch You can therefore use FETCH_ROWS much as you would FETCH and the %FOUND (or %NOTFOUND) attributes The following two sets of statements are equivalent:

Use a normal, static cursor:

FETCH emp_cur INTO emp_rec;

IF emp_cur%FOUND THEN

process data

END IF;

Use DBMS_SQL to fetch rows:

IF DBMS_SQL.FETCH_ROWS (c) > 0 THEN

process data

END IF;

Trang 2

So that happens when you fetch past the end of the cursor's result set? With static cursors, you can fetch all you want and never raise an error In the following block, for example, I fetch 1000 times from a table with 14 rows (C'mon, you knew that, right? The emp table has 14 rows.)

DECLARE

CURSOR empcur IS SELECT * FROM emp;

emprec empcur%ROWTYPE;

BEGIN

OPEN empcur;

FOR rowind IN 1 1000

LOOP

FETCH empcur INTO emprec;

END LOOP;

END;

/

No problem −− and no exceptions! After the fourteenth fetch, the FETCH statement simply does nothing (and the record continues to hold the fourteenth row's information)

However, the "fetch past last record" behavior with dynamic SQL is different The FETCH_ROWS function

will raise the ORA−01002 exception: fetch out of sequence, if you fetch again after a call to FETCH_ROWS

has returned 0 The following anonymous block raises the ORA−01002 error, because there are only three employees in department 10:

DECLARE

cur PLS_INTEGER := DBMS_SQL.OPEN_CURSOR;

fdbk PLS_INTEGER;

BEGIN

DBMS_SQL.PARSE

(cur, 'SELECT * FROM emp WHERE deptno = 10', DBMS_SQL.NATIVE);

fdbk := DBMS_SQL.EXECUTE_CURSOR (cur);

FOR Nfetch IN 1 5

LOOP

/* On fetch #5 this will raise ORA−01002 */

fdbk := DBMS_SQL.FETCH_ROWS (cur);

END LOOP;

DBMS_SQL.CLOSE_CURSOR (cur);

END;

/

The following procedure shows how you can employ the FETCH_ROWS logic inside of a loop to fetch each

of the rows from a cursor and place column values in an Oracle Forms block:

/* Filename on companion disk: fillblck.fp */

PROCEDURE fill_block (where_clause_in IN VARCHAR2)

/*

|| Query data from table using a dynamic where clause and then

|| pass those values to an Oracle Forms block.

*/

IS

/*

|| Declare cursor handle and parse the query, all in a single

|| statement using open_and_parse (see PARSE description).

*/

c INTEGER := DBMS_SQL.OPEN_CURSOR;

emprec employee%ROWTYPE;

/* return value from EXECUTE; ignore in case of query */

fdbk INTEGER;

BEGIN

/* Parse the query with a dynamic WHERE clause */

Trang 3

DBMS_SQL.PARSE (c,

'SELECT employee_id, last_name ' ||

' FROM employee WHERE ' || where_clause_in,

DBMS_SQL.NATIVE);

/* Define the columns in the cursor for this query */

DBMS_SQL.DEFINE_COLUMN (c, 1, emprec.empno);

DBMS_SQL.DEFINE_COLUMN (c, 2, emprec.ename, 30);

/* Now I can execute the query */

fdbk:= DBMS_SQL.EXECUTE (c);

LOOP

/* Try to fetch next row If done, then exit the loop */

EXIT WHEN DBMS_SQL.FETCH_ROWS (c) = 0;

/*

|| Retrieve data via calls to COLUMN_VALUE and place those

|| values in a new record in the block.

*/

DBMS_SQL.COLUMN_VALUE (c, 1, emprec.empno);

DBMS_SQL.COLUMN_VALUE (c, 2, emprec.ename);

CREATE_RECORD;

:employee.employee_id := emprec.empno;

:employee.employee_nm := emprec.ename;

END LOOP;

/* Clean up the cursor */

DBMS_SQL.CLOSE_CURSOR (c);

END;

In this example, you can fetch only one row at a time, because you defined each of your columns in the cursor

to hold a single value If, on the other hand, you defined a column as an array, then the fetch could receive multiple rows in a single call This approach is explored in more detail in the section Section 2.5.6, "Array Processing with DBMS_SQL"."

2.3.7.2 The DBMS_SQL.EXECUTE_AND_FETCH function

The EXECUTE_AND_FETCH function executes the SELECT statement associated with the specified cursor and immediately fetches the rows associated with the query Here's the specification for the function

FUNCTION DBMS_SQL.EXECUTE_AND_FETCH

(c IN INTEGER

,exact IN BOOLEAN DEFAULT FALSE)

RETURN INTEGER;

Parameters are summarized in the following table

Parameter Description

c The handle or pointer to the cursor originally returned by a call to OPEN_CURSOR

exact Set to TRUE if you want the function to raise an exception when it fetches more than one row Even if EXECUTE_AND_FETCH does raise an exception (TOO_MANY_ROWS), the rows will still be fetched and available The value returned by the function will, however, be NULL

This function is designed to make it easy to execute and fetch a single row from a query It is very similar to the implicit SELECT cursor in native PL/SQL, which either returns a single row, multiple rows (for PL/SQL8 array access only), or raises the TOO_MANY_ROWS exception (ORA−01422)

See the sidebar entitled the sidebar "Oracle: The Show Me Technology"," for a script you can use to examine the behavior of this built−in function

Trang 4

2.3.8 Retrieving Values

Oracle: The Show Me Technology

If there is one thing I have learned over the years, it is that if I am not absolutely sure about the way a

particular feature works, I have to try it out and see what happens I have two primary references for writing about PL/SQL technology: the Oracle documentation and the Oracle software The former is helpful for guiding my "first draft." The latter is helpful for making sure that my "final draft" is accurate and honest See, unfortunately, just because the documentation says that something works a certain way, that doesn't

necessarily mean it really does operate as advertised

I built the following script (designed for use in SQL*Plus) to make it easier for Oracle to "show me" exactly the kind of variations in behavior of DBMS_SQL.EXECUTE_AND_FETCH I might encounter You use the first argument to indicate whether or not you want rows to be found The second argument dictates the

error−handling behavior I thought I would share it with you to give you a sense of how these kinds of scripts can make it very easy to test functionality and behavior

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

DECLARE

cur INTEGER := DBMS_SQL.OPEN_CURSOR;

fdbk INTEGER;

BEGIN

DBMS_SQL.PARSE

(cur, 'SELECT empno FROM emp where 1=&1', DBMS_SQL.NATIVE);

DBMS_SQL.DEFINE_COLUMN (cur, 1, 1);

fdbk := DBMS_SQL.EXECUTE_AND_FETCH (cur, &2);

DBMS_OUTPUT.PUT_LINE (fdbk);

DBMS_SQL.CLOSE_CURSOR (cur);

EXCEPTION

WHEN OTHERS

THEN

DBMS_OUTPUT.PUT_LINE ('error code ' || SQLCODE);

DBMS_OUTPUT.PUT_LINE

('returned by e_and_f ' || NVL (TO_CHAR (fdbk), '[NULL]'));

END;

/

Here are the results of executing this script in SQL*Plus:

SQL> @execftch 1 false

1

SQL> @execftch 2 false

0

SQL> @execftch 1 true

error code −1422

returned by e_and_f [NULL]

SQL> @execftch 2 true

error code 100

returned by e_and_f [NULL]ORA−01403: no data found

If you construct a dynamic SELECT or PL/SQL block, you can retrieve values from the cursor after

execution Use the COLUMN_VALUE procedure to obtain the values of individual columns in the fetched row of a SELECT Use the COLUMN_VALUE_LONG procedure to obtain the values of a LONG column in the fetched row of a SELECT Use the VARIABLE_VALUE procedure to extract the values of variables in a dynamic PL/SQL block

Trang 5

2.3.8.1 The DBMS_SQL.COLUMN_VALUE procedure

The COLUMN_VALUE procedure retrieves a value from the cursor into a local variable Use this procedure when the SQL statement is a query and you are fetching rows with EXECUTE_AND_FETCH or

FETCH_ROWS You can retrieve the value for a single column in a single row or, with PL/SQL8, you can retrieve the values for a single column across multiple rows fetched The header for the single−row version of the procedure is as follows:

PROCEDURE DBMS_SQL.COLUMN_VALUE

(c IN INTEGER,

position IN INTEGER,

value OUT <datatype>,

[, column_error OUT NUMBER]

[, actual_length OUT INTEGER ]);

The COLUMN_VALUE parameters are summarized in the following table

Parameter Description

c Pointer to the cursor

position Relative position of the column in the select list

value The PL/SQL structure that receives the column value If the <datatype> of this argument

does not match that of the cursor's column, DBMS_SQL will raise the DBMS_SQL.INCONSISTENT_DATATYPE exception

<table_parameter> The PL/SQL table (of type <table_type>) holding one or more colum values, depending

on how many rows were previously fetched

column_error Returns an error code for the specified value (the value might be too large for the

variable, for instance)

actual_length Returns the actual length of the returned value before any truncation takes place (due to

a difference in size between the retrieved value in the cursor and the variable)

<datatype> can be one of the following types:

NUMBER

DATE

MLSLABEL

VARCHAR2 CHARACTER SET ANY_CS

BLOB

CLOB CHARACTER SET ANY_CS

BFILE

The header for the multiple−row version of COLUMN_VALUE is as follows:

PROCEDURE DBMS_SQL.COLUMN_VALUE

(c IN INTEGER,

position IN INTEGER,

<table_parameter> OUT <table_type>);

<table_parameter> OUT <table_type> can be one of the following:

n_tab OUT DBMS_SQL.NUMBER_TABLE

c_tab OUT DBMS_SQL.VARCHAR2_TABLE

d_tab OUT DBMS_SQL.DATE_TABLE

bl_tab OUT DBMS_SQL.BLOB_TABLE

cl_tab OUT DBMS_SQL.CLOB_TABLE

bf_tab OUT DBMS_SQL.BFILE_TABLE

The DBMS_SQL package also offers more specific variants of COLUMN_VALUE for less common

Ngày đăng: 07/07/2014, 00:20

TỪ KHÓA LIÊN QUAN