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

Oracle Built−in Packages- P15 ppsx

5 290 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 79,89 KB

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

Nội dung

Call this procedure after PARSE, but before calls to EXECUTE and EXECUTE_AND_FETCH: PROCEDURE DBMS_SQL.BIND_ARRAY c IN INTEGER, name IN VARCHAR2, IN , [,index1 IN INTEGER, ,index2

Trang 1

Kind of ugly, isn't it? All of those single quotes glommed together (three consecutive single quotes at the end

of a string result in one single quote around the literal values stuffed into the SQL statement), the

concatenation, datatype conversions, etc This is the tradeoff for not using the programmatic interface

provided by DBMS_SQL

You will also call BIND_VARIABLE for every placeholder in a dynamic PL/SQL block, even if the

placeholder is an OUT argument or is otherwise simply receiving a value Consider the following PL/SQL procedure, which performs an assignment dynamically when it could simply do it explicitly:

CREATE OR REPLACE PROCEDURE assign_value (newval_in IN NUMBER)

IS

cur PLS_INTEGER := DBMS_SQL.OPEN_CURSOR;

fdbk PLS_INTEGER;

local_var NUMBER; /* Receives the new value */

BEGIN

DBMS_SQL.PARSE

(cur, 'BEGIN :container := :newval; END;', DBMS_SQL.NATIVE);

DBMS_SQL.BIND_VARIABLE (cur, 'newval', newval_in);

DBMS_SQL.BIND_VARIABLE (cur, 'container', 1);

fdbk := DBMS_SQL.EXECUTE (cur);

DBMS_SQL.VARIABLE_VALUE (cur, 'container', local_var);

END;

/

Notice that even though the container placeholder's value before execution is irrelevant, I still needed to bind

that placeholder to a value for the PL/SQL block to execute successfully

2.3.4.1.2 The DBMS_SQL.BIND_ARRAY procedure

With PL/SQL8, you can use the new BIND_ARRAY procedure to perform bulk selects, inserts, updates, and deletes to improve the performance of your application This same procedure will allow you to use and manipulate index−by tables (previously known as PL/SQL tables) within dynamically constructed PL/SQL blocks of code To perform bulk or array processing, you will associate one or more index−by tables with columns or placeholders in your cursor

The BIND_ARRAY procedure establishes this association for you Call this procedure after PARSE, but before calls to EXECUTE and EXECUTE_AND_FETCH:

PROCEDURE DBMS_SQL.BIND_ARRAY

(c IN INTEGER,

name IN VARCHAR2,

<table_variable> IN <datatype>,

[,index1 IN INTEGER,

,index2 IN INTEGER)]);

The parameters for this procedure are summarized in the following table

Parameter Description

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 SQL statement passed to PARSE

index1 The lower bound or row in the index−by table <table_variable> for the first table element

variable See the following description

index2 The upper bound or row in the index−by table <table_variable> for the last table element

The <table_variable> IN <datatype> clause may be any of the following:

n_tab IN DBMS_SQL.NUMBER_TABLE

Trang 2

c_tab IN DBMS_SQL.VARCHAR2_TABLE

d_tab IN DBMS_SQL.DATE_TABLE

bl_tab IN DBMS_SQL.BLOB_TABLE

cl_tab IN DBMS_SQL.CLOB_TABLE

bl_tab IN DBMS_SQL.BFILE_TABLE

The following example shows how I can use BIND_ARRAY to update multiple numeric rows of any table that has a numeric primary key:

/* Filename on companion disk: updarray.sp */

CREATE OR REPLACE PROCEDURE updarray

(tab IN VARCHAR2,

keycol IN VARCHAR2,

valcol IN VARCHAR2,

keylist IN DBMS_SQL.NUMBER_TABLE,

vallist IN DBMS_SQL.NUMBER_TABLE)

IS

cur INTEGER := DBMS_SQL.OPEN_CURSOR;

fdbk INTEGER;

mytab DBMS_SQL.NUMBER_TABLE;

BEGIN

DBMS_SQL.PARSE

(cur,

'UPDATE ' || tab ||

' SET ' || valcol || ' = :vals ' ||

' WHERE ' || keycol || ' = :keys',

DBMS_SQL.NATIVE);

DBMS_SQL.BIND_ARRAY (cur, 'keys', keylist);

DBMS_SQL.BIND_ARRAY (cur, 'vals', vallist);

fdbk := DBMS_SQL.EXECUTE (cur);

DBMS_SQL.CLOSE_CURSOR (cur);

END;

/

Now I can execute this "update by array" procedure for the sal column of the emp table

DECLARE

emps DBMS_SQL.NUMBER_TABLE;

sals DBMS_SQL.NUMBER_TABLE;

BEGIN

emps (1) := 7499;

sals (1) := 2000;

emps (2) := 7521;

sals (2) := 3000;

updarray ('emp', 'empno', 'sal', emps, sals);

END;

/

The section on the DEFINE_ARRAY procedure and the section called "Array Processing with DBMS_SQL" provide additional examples of using BIND_ARRAY

2.3.4.1.3 Rules for array binding

There are a number of factors to keep in mind when you are binding with index−by tables

At the time of binding, the contents of the nested table are copied from your private global area to the DBMS_SQL buffers Consequently, if you make changes to the nested table after your call to

DBMS_SQL.BIND_ARRAY, those changes will not affect the cursor when executed

Trang 3

If you specify values for index1 and/or index2, then those rows must be defined in the nested table The value of index1 must be less than or equal to index2 All elements between and included in those rows will be used in the bind, but the table does not have to be densely filled

If you do not specify values for index1 and index2, the first and last rows defined in the nested table will be used to set the boundaries for the bind

Suppose that you have more than one bind array in your statement and the bind ranges (or the defined rows, if you did not specify) for the arrays are different DBMS_SQL will then use the smallest common range −− that is, the greatest of the lower bounds and the least of the upper bounds

You can mix array and scalar binds in your dynamic SQL execution If you have a scalar bind, the same value will be used for each element of the arrays

When fetching data using dynamic SQL, you cannot use arrays in both the bind and define phases You may not, in other words, specify multiple bind values and at the same time fetch multiple rows into an array

2.3.5 Defining Cursor Columns

The OPEN_CURSOR procedure allocates memory for a cursor and its result set and returns a pointer to that area in memory It does not, however, give any structure to that cursor And even after you parse a SQL statement for that pointer, the cursor itself still does not have any internal structure If you are going to

execute a SELECT statement dynamically and extract values of columns in retrieved rows, you will need to take the additional step of defining the datatype of the individual columns in the cursor

Each cursor column is, essentially, a container which will hold fetched data You can use the

DEFINE_COLUMN procedure to define a "scalar" column −− one that will hold a single value You can also (with PL/SQL8) call DEFINE_ARRAY to create a column that will hold multiple values, allowing you to fetch rows in bulk from the database

2.3.5.1 The DBMS_SQL.DEFINE_COLUMN procedure

When you call the PARSE procedure to process a SELECT statement, you need to pass values from the database into local variables To do this, you must tell DBMS_SQL the datatypes of the different columns or expressions in the SELECT list by making a call to the DEFINE_COLUMN procedure:

PROCEDURE DBMS_SQL.DEFINE_COLUMN

(c IN INTEGER,

position IN INTEGER,

column IN <datatype>);

The parameters for this procedure are summarized in the following table

Parameter Description

c Pointer to the cursor

position The relative position of the column in the SELECT list

column A PL/SQL variable or expression whose datatype determines the datatype of the column being

defined The particular value being passed in is irrelevant

Trang 4

<datatype> may be one of the following data types: NUMBER, DATE, MLSLABEL, BLOB, CLOB

CHARACTER SET ANY_CS, BFILE

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

datatypes

PROCEDURE DBMS_SQL.DEFINE_COLUMN

(c IN INTEGER

,position IN INTEGER

,column IN VARCHAR2 CHARACTER SET ANY_CS

,column_size IN INTEGER);

PROCEDURE DBMS_SQL.DEFINE_COLUMN_CHAR

(c IN INTEGER

,position IN INTEGER

,column IN CHAR CHARACTER SET ANY_CS

,column_size IN INTEGER);

PROCEDURE DBMS_SQL.DEFINE_COLUMN_RAW

(c IN INTEGER

,position IN INTEGER

,column IN RAW

,column_size IN INTEGER);

PROCEDURE DBMS_SQL.DEFINE_COLUMN_ROWID

(c IN INTEGER

,position IN INTEGER

,column IN ROWID);

PROCEDURE DBMS_SQL.DEFINE_COLUMN_LONG

(c IN INTEGER

,position IN INTEGER);

You call DEFINE_COLUMN after the call to the PARSE procedure, but before the call to EXECUTE or EXECUTE_AND_FETCH Once you have executed the SELECT statement, you will then use the

COLUMN_VALUE procedure to grab a column value from the select list and pass it into the appropriate local variable

The following code shows the different steps required to set up a SELECT statement for execution with DBMS_SQL:

DECLARE

/* Declare cursor handle and assign it a pointer */

c INTEGER := DBMS_SQL.OPEN_CURSOR;

/* Use a record to declare local structures */

rec employee%ROWTYPE;

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

execute_feedback INTEGER;

BEGIN

/* Parse the query with two columns in SELECT list */

DBMS_SQL.PARSE

(c,

'SELECT employee_id, last_name FROM employee',

DBMS_SQL.V7);

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

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

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

/* Now I can execute the query */

execute_feedback := DBMS_SQL.EXECUTE (c);

Trang 5

DBMS_SQL.CLOSE_CURSOR (c)

END;

Notice that with the DEFINE_COLUMN procedure, you define columns (their datatypes) using a sequential position With BIND_VARIABLE, on the other hand, you associate values to placeholders by name

2.3.5.2 The DBMS_SQL.DEFINE_ARRAY procedure

If you are working with PL/SQL8, you have the option of defining a column in the cursor which is capable of holding the values of multiple fetched rows You accomplish this with a call to the DEFINE_ARRAY

procedure:

PROCEDURE DBMS_SQL.DEFINE_ARRAY

(c IN INTEGER

,position IN INTEGER

,<table_parameter> IN <table_type>

,cnt IN INTEGER

,lower_bound IN INTEGER);

The DEFINE_ARRAY parameters are summarized in the following table

Parameter Description

position The relative position of the column in the select list

<table_parameter> The nested table which is used to tell DBMS_SQL the datatype of the column

cnt The maximum number of rows to be fetched in the call to the FETCH_ROWS or

EXECUTE_AND_FETCH functions

lower_bound The starting row (lower bound) in which column values will be placed in the nested

table you provide in the corresponding call to the COLUMN_VALUE or VARIABLE_VALUE procedures

<table_parameter> IN <table_type> is one of the following:

n_tab IN DBMS_SQL.NUMBER_TABLE

c_tab IN DBMS_SQL.VARCHAR2_TABLE

d_tab IN DBMS_SQL.DATE_TABLE

bl_tab IN DBMS_SQL.BLOB_TABLE

cl_tab IN DBMS_SQL._TABLE

bf_tab IN DBMS_SQL.BFILE_TABLE

When you call the COLUMN_VALUE or VARIABLE_VALUE procedures against an array−defined

column, the Nth fetched column value will be placed in the lower_bound+N−1th row in the nested table In other words, if you have fetched three rows and your call to DEFINE_ARRAY looked like this:

DECLARE

datetab DBMS_SQL.DATE_TABLE;

BEGIN

DBMS_SQL.DEFINE_ARRAY (cur, 2, datetab, 10, 15);

execute and fetch rows

DBMS_SQL.COLUMN_VALUE (cur, 2, datetab);

END;

then the data will be placed in datetab(15), datetab(16), and datetab(17)

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