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

Oracle Built−in Packages- P14 docx

5 261 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,15 KB

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

Nội dung

NOTE: The common understanding among long−time Oracle programmers is that when you parse DDL, it always executes, so a call to the EXECUTE procedure is not necessary when calling DBMS_SQ

Trang 1

instructed by your DBA.

Note that you cannot defer the parsing of this statement, as is possible with OCI Statements in DBMS_SQL are parsed immediately Oracle documentation does mention that this "may change in future versions; you should not rely on this behavior." This means that at some point in the future, Oracle Corporation may allow parsing to be deferred to the execute phase, thereby reducing network traffic If this change occurs, let's hope that a flag is offered to preserve earlier functionality

NOTE: The common understanding among long−time Oracle programmers is that when you

parse DDL, it always executes, so a call to the EXECUTE procedure is not necessary when

calling DBMS_SQL.PARSE for a DDL statement You should not take this shortcut! Oracle

will not guarantee that this behavior will continue in future releases If you want to make sure

that your DDL has executed, call the DBMS_SQL.EXECUTE procedure

2.3.3.2 Parsing very long SQL statements

PL/SQL8 offers a second, overloaded version of PARSE, which comes in handy when you have very large SQL statements If your SQL statement exceeds the largest possible contiguous allocation on your system (and it is machine−dependent) or 32Kbytes (the maximum size for VARCHAR2), then use this version of the PARSE procedure:

PROCEDURE DBMS_SQL.PARSE

(c IN INTEGER,

statement IN DBMS_SQL.VARCHAR2S,

lb IN INTEGER,

ub IN INTEGER,

lfflg IN BOOLEAN,

language_flag IN INTEGER);

The parameters for this procedure are summarized in the following table

Parameter Description

c The pointer to the cursor or memory area for this SQL statement

statement The SQL statement to be parsed and associated with the cursor In this case, you will be

passing a PL/SQL table of the DBMS_SQL.VARCHAR2S type

lb The lower bound or first row in the statement table to be parsed

ub The upper bound or last row in the statement table to be parsed

lfflg If TRUE, then a line−feed should be concatenated after each row in the table

language_flag A flag determining how Oracle will handle the statement Valid options are DBMS_SQL.V6,

DBMS_SQL.V7, and DBMS_SQL.NATIVE Use DBMS_SQL.NATIVE unless otherwise instructed by your DBA

My own parse_long_one procedure offers an example of using the array−based version of the PARSE

procedure:

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

CREATE OR REPLACE PROCEDURE parse_long_one

(select_list IN VARCHAR2,

from_list IN VARCHAR2,

where_clause IN VARCHAR2,

maxlen IN BINARY_INTEGER := 256, /* Can change the max */

dbg IN BOOLEAN := FALSE /* Built−in debugging toggle */

)

IS

/* Open the cursor as I declare the variable */

cur BINARY_INTEGER := DBMS_SQL.OPEN_CURSOR;

Trang 2

/* Declare the index−by table based on the DBMS_SQL TYPE */

sql_table DBMS_SQL.VARCHAR2S;

/* Local module to extract up to the next maxlen chars */

FUNCTION next_row

(string_in IN VARCHAR2,

start_inout IN OUT BINARY_INTEGER,

len_in IN BINARY_INTEGER)

RETURN VARCHAR2

IS

v_start BINARY_INTEGER := start_inout;

BEGIN

start_inout := LEAST (len_in + 1, start_inout + maxlen);

RETURN SUBSTR (string_in, v_start, maxlen);

END;

/* Local module to transfer string to index−by table */

PROCEDURE fill_sql_table (string_in IN VARCHAR2)

IS

v_length BINARY_INTEGER;

v_start BINARY_INTEGER := 1;

BEGIN

IF string_in IS NOT NULL

THEN

v_length := LENGTH (string_in);

LOOP

sql_table (NVL (sql_table.LAST, 0)+1) :=

next_row (string_in, v_start, v_length);

EXIT WHEN v_start > v_length;

END LOOP;

END IF;

END;

BEGIN

/* Move each portion of the SELECT string to the table */

fill_sql_table (select_list);

fill_sql_table (from_list);

fill_sql_table (where_clause);

/* Parse everything from first to last row of table */

DBMS_SQL.PARSE (cur,

sql_table, sql_table.FIRST, sql_table.LAST,

FALSE, DBMS_SQL.NATIVE);

/* Execute and fetch rows if doing something for real */

/* If debugging, then display contents of the table */

IF dbg

THEN

DBMS_OUTPUT.PUT_LINE

('Parsed into lines of length ' || TO_CHAR (maxlen));

FOR rowind IN sql_table.FIRST sql_table.LAST

LOOP

DBMS_OUTPUT.PUT_LINE (sql_table(rowind));

END LOOP;

END IF;

/* Close the cursor when done */

DBMS_SQL.CLOSE_CURSOR (cur);

END;

/

Here is a little test script (and the results of execution) for this procedure:

SQL> BEGIN

parse_long_one ('select empno, ename, sal, hiredate, mgr, comm ',

'from emp ', 'where empno = empno and sal = sal', 10, TRUE);

Trang 3

/

Parsed into lines of length 10

select emp

no, ename,

sal, hire

date, mgr,

comm

from emp

where empn

o = empno

and sal =

sal

/

Notice that the SELECT statement is broken without any concern for keeping identifiers intact The lfflg value passed in to the PARSE procedure is set to FALSE so linefeeds are not concatenated As a result, the broken identifiers are concatenated back together and the SQL statement parses without any difficulty

2.3.4 Binding Values into Dynamic SQL

The SQL (or PL/SQL) statement you execute is constructed as a string at runtime In most scenarios, you are using dynamic SQL because all the information about the SQL statement is not known at compile time You

therefore have values that you want to pass into the SQL statement at runtime You have two ways of doing

this: concatenation and binding With concatenation, you convert all elements of the SQL statement into

strings and concatenate them together With binding, you insert placeholders in your string (identifiers

prefaced with a colon) and then explicitly bind or associate a value with that placeholder before executing the SQL statement

If you concatenate the value into the string, then you are not really binding values and you do not have to make calls to the BIND_VARIABLE or BIND_ARRAY procedures Here is an example of the parsing of a dynamically constructed string relying on concatenation:

DBMS_SQL.PARSE

(cur, 'SELECT * FROM emp WHERE ename LIKE ' || v_ename);

At runtime the string is cobbled together and passed to the SQL engine for parsing With binding, you would write code like this:

DBMS_SQL.PARSE

(cur, 'SELECT * FROM emp WHERE ename LIKE :varname');

DBMS_SQL.BIND_VARIABLE (cur, 'varname', var_name_in);

Binding involves writing more code, but offers much more flexibility and power The following comparison between concatenation and binding techniques will help you decide which to use:

When you concatenate, you convert to a string format This can become awkward and error−prone With binding, you do not perform any conversions Instead, the native datatypes are employed

When you execute DDL statements dynamically, you cannot use bind variables Your only choice is

to concatenate together the strings and then pass that to the engine This makes sense, since, at least in the current version of DBMS_SQL, there is no such thing as deferred parsing When you parse, you also execute DDL

Trang 4

You can execute the same dynamic cursor more than once, and each time you bind in different values

to the SQL statement This is not possible if you concatenate the values into the string at the time of parsing

With bind variables, you can take advantage of the new array−processing features of PL/SQL8's DBMS_SQL package You can bind an entire array of scalar values into the SQL string and then apply each of those values in a single SQL execution

So if you decide that you really do want to bind variables into your dynamic SQL, use one of the programs described in the following sections

2.3.4.1 The DBMS_SQL.BIND_VARIABLE procedure

The BIND_VARIABLE procedure binds a scalar value to a placeholder in your SQL statement A placeholder

is an identifier prefaced by a colon, as in :myval Call BIND_VARIABLE after DBMS_SQL.PARSE, but before calls to EXECUTE and EXECUTE_AND_FETCH This procedure is overloaded to allow you to bind

a number of different types of data This is the header:

PROCEDURE DBMS_SQL.BIND_VARIABLE

(c IN INTEGER,

name IN VARCHAR2,

value IN <datatype>);

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 placeholder included in the SQL statement passed to PARSE

value The value to be bound to the placeholder variable

<datatype> may be any of the following:

BFILE

BLOB

CLOB CHARACTER SET ANY_CS

DATE

MLSLABEL /*Trusted Oracle only*/

NUMBER

VARCHAR2 CHARACTER SET ANY_CS_ARRAY

Here is an example of binding the current date/time into a placeholder called "now:"

DBMS_SQL.BIND_VARIABLE (cur, 'now', SYSDATE);

Here is an example of binding the literal value "Liberation Theology" into a placeholder called "progress:"

DBMS_SQL.BIND_VARIABLE (cur, ':progress', 'Liberation Theology');

Notice that you can include or leave out the colon when you specify the placeholder name

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

datatypes,

PROCEDURE DBMS_SQL.BIND_VARIABLE

(c IN INTEGER,

name IN VARCHAR2,

Trang 5

value IN VARCHAR2 CHARACTER SET ANY_CS,

[,out_value_size IN INTEGER]);

PROCEDURE DBMS_SQL.BIND_VARIABLE_CHAR

(c IN INTEGER,

name IN VARCHAR2,

value IN CHAR CHARACTER SET ANY_CS,

[,out_value_size IN INTEGER]);

PROCEDURE DBMS_SQL.BIND_VARIABLE_RAW

(c IN INTEGER,

name IN VARCHAR2,

value IN RAW

[,out_value_size IN INTEGER]);

PROCEDURE DBMS_SQL.BIND_VARIABLE_ROWID

(c IN INTEGER,

name IN VARCHAR2,

value IN ROWID);

where out_value_size is the maximum size expected for the value that might be passed to this variable Square brackets indicate optional parameters If you do not provide a value for out_value_size, the size is the length

of the current value provided

2.3.4.1.1 Examples

For every placeholder you put in your SQL string, you must make a call to BIND_VARIABLE (or

BIND_ARRAY) For example, the SELECT statement in the call to PARSE below contains two bind

variables, :call_date and :call_type:

DBMS_SQL.PARSE

(the_cursor,

'SELECT COUNT(*) freq FROM call WHERE call_date = :call_date ' ||

'AND call_type_cd = :call_type',

DBMS_SQL.V7);

I will therefore need to issue the following two calls to BIND_VARIABLE before I can execute the query,

DBMS_SQL.BIND_VARIABLE (the_cursor, 'call_date', :call.last_date_called);

DBMS_SQL.BIND_VARIABLE (the_cursor, 'call_type', :call.call_status);

where the two bind values are items in an Oracle Forms screen Since BIND_VARIABLE is overloaded, I can call it with either a date value or a string, and PL/SQL will execute the appropriate code Notice that the name

of the bind variable does not have to match any particular column name in the SELECT statement, and it does

not have to match the name of the PL/SQL variable that may hold the value The name is really just a

placeholder into which a value is substituted

You can also include the colon in the placeholder name when you bind the value to the variable:

DBMS_SQL.BIND_VARIABLE (the_cursor, ':call_date', :call.last_date_called);

If you want to avoid having to make these separate calls to BIND_VARIABLE, you can substitute these values into the SQL statement yourself at the time the statement is parsed The code shows the same SELECT statement, but without any bind variables

DBMS_SQL.PARSE

(the_cursor,

'SELECT COUNT(*) freq FROM call WHERE call_date = ''' ||

TO_CHAR (:call.last_date_called) ||

''' AND call_type_cd = ''' || :call.call_status || '''',

DBMS_SQL.V7);

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