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

Oracle Built−in Packages- P15 ppsx

5 289 0

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

THÔNG TIN TÀI LIỆU

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 [Appendix A] What's on the Companion Disk? 2.3.4 Binding Values into Dynamic SQL 61 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. • [Appendix A] What's on the Companion Disk? 2.3.4 Binding Values into Dynamic SQL 62 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. [Appendix A] What's on the Companion Disk? 2.3.5 Defining Cursor Columns 63 <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); [Appendix A] What's on the Companion Disk? 2.3.5 Defining Cursor Columns 64 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 c Pointer to cursor. 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). [Appendix A] What's on the Companion Disk? 2.3.5 Defining Cursor Columns 65

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

Xem thêm: Oracle Built−in Packages- P15 ppsx

Mục lục

    A. What's on the Companion Disk?

    1.1 The Power of Built-in Packages

    1.1.1 A Kinder , More Sharing Oracle

    1.2 Built-in Packages Covered in This Book

    1.3.1 What Is a Package?

    1.3.2 Controlling Access with Packages

    1.3.3 Referencing Built-in Package Elements

    1.3.4 Exception Handling and Built-in Packages

    1.3.5 Encapsulating Access to the Built-in Packages

    1.3.6 Calling Built-in Packaged Code from Oracle Developer/2000 Release 1

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN