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

Oracle Built−in Packages- P99 doc

5 218 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 78,85 KB

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

Nội dung

BEGIN IF v IS NULL THEN DBMS_UTILITY.DB_VERSION v, c; END IF; END; FUNCTION version RETURN VARCHAR2 IS BEGIN init_info; RETURN v; END; FUNCTION compatibility RETURN VARCHAR2

Trang 1

BEGIN

IF v IS NULL

THEN

DBMS_UTILITY.DB_VERSION (v, c);

END IF;

END;

FUNCTION version RETURN VARCHAR2

IS

BEGIN

init_info;

RETURN v;

END;

FUNCTION compatibility RETURN VARCHAR2

IS

BEGIN

init_info;

RETURN c;

END;

END;

/

Notice that this very simple package also optimizes lookups against the DBMS_UTILITY package The first time you call either the DB.VERSION or the DB.COMPATILITY functions, the private init_info procedure will detect that the v variable is NULL, and so it will call the built−in procedure From that point on, however, whenever you call either of the DB functions, they will simply return the current value After all, the version

of the database is not going to change during your connection to that database.

Here is the output I received from db.version on Oracle8:

SQL> exec DBMS_UTILITY.PUT_LINE (db.version)

8.0.3.0.0

10.1.2.9 The DBMS_UTILITY.EXEC_DDL_STATEMENT procedure

Oracle has added a procedure to the DBMS_UTILITY package that allows you to execute a DDL statement easily The header for this procedure follows:

PROCEDURE DBMS_UTILITY.EXEC_DDL_STATEMENT

(parse_string IN VARCHAR2);

Here, for example, is all the code I need to write to create an index from within PL/SQL:

BEGIN

DBMS_UTILITY.EXEC_DDL_STATEMENT

('create index so_easy on emp (hiredate, mgr, sal)');

END;

/

You can also use the DBMS_SQL package to perform the same functionality.

10.1.2.10 The DBMS_UTILITY.FORMAT_CALL_STACK function

This function formats and returns the current call stack You can use this function to access the call stack in your program The header for the function follows:

FUNCTION DBMS_UTILITY.FORMAT_CALL_STACK RETURN VARCHAR2;

Trang 2

10.1.2.10.1 Example

I generated the information in this next example with the following statement:

DBMS_OUTPUT.PUT_LINE (DBMS_UTILITY.FORMAT_CALL_STACK);

The code shows sample output from a call to FORMAT_CALL_STACK.

−−−−− PL/SQL Call Stack −−−−−

object line object

handle number name

817efc90 3 procedure BOOK.CALC_TOTALS

817d99ec 3 function BOOK.NET_PROFIT

817d101c 4 anonymous block

The output from this function can be up to 2000 bytes in length.

10.1.2.11 The DBMS_UTILITY.FORMAT_ERROR_STACK function

The FORMAT_ERROR_STACK function formats and returns the current error stack You might use this function in an exception handler to examine the sequence of errors raised The header for the function follows:

FUNCTION DBMS_UTILITY.FORMAT_ERROR_STACK RETURN VARCHAR2;

The output from this function can be up to 2000 bytes in length.

10.1.2.11.1 Example

The script file errstk.sql creates three procedures, each of which raises a different exception, and then kicks

off the nested execution of those programs.

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

CREATE OR REPLACE PROCEDURE proc1

IS

BEGIN

RAISE NO_DATA_FOUND;

END;

/

CREATE OR REPLACE PROCEDURE proc2 S

BEGIN

proc1;

EXCEPTION

WHEN OTHERS THEN RAISE VALUE_ERROR;

END;

/

CREATE OR REPLACE PROCEDURE proc2 IS

BEGIN

proc1;

EXCEPTION

WHEN OTHERS THEN RAISE VALUE_ERROR;

END;

/

CREATE OR REPLACE PROCEDURE proc3 IS

BEGIN

proc2;

EXCEPTION

WHEN OTHERS THEN RAISE DUP_VAL_ON_INDEX;

END;

/

BEGIN /* Now execute the top−level procedure */

proc3;

EXCEPTION

Trang 3

WHEN OTHERS

THEN

DBMS_OUTPUT.PUT_LINE (DBMS_UTILITY.FORMAT_ERROR_STACK);

END;

/

Here is the output from this script:

ORA−00001: unique constraint (.) violated

ORA−06502: PL/SQL: numeric or value error

ORA−01403: no data found

Here is my conclusion from this test: the DBMS_UTILITY.FORMAT_ERROR_STACK is of limited use in PL/SQL programs You don't see the name of the program in which the error was raised, and you don't see the line number on which the error occurred.

10.1.2.12 The DBMS_UTILITY.GET_HASH_VALUE function

This function gives PL/SQL developers access to a hashing algorithm You will generally use hashing to generate a unique (or at least likely to be unique) integer value for a string Here's the header for this function:

FUNCTION DBMS_UTILITY.GET_HASH_VALUE

(name IN VARCHAR2

,base IN NUMBER

,hash_size IN NUMBER)

RETURN NUMBER;

Parameters are summarized in the following table.

Parameter Description

name The string to be converted or hashed into an integer

base The base or starting value of integer values for the hashing algorithm

hash_size The size of the "hash table," meaning the total number of values that are available to the hashing

algorithm as conversions from the string inputs

The values of base and hash_size determine the range of integers that can be used as converted values.

Clearly, the larger the hash size, the more likely it is that you will be able to obtain a unique integer for every string you pass to the program.

Here are some points to keep in mind when working with the GET_HASH_VALUE function:

Use a small prime number for the base parameter This establishes the low point of the range of values for the hash table.

Use a very large number, and, at Oracle's suggestion, a power of 2, for the hash size to obtain best results I usually employ a number like 230.

You can never be sure that the function will actually return an integer value that is unique across the different strings you are converting or have already converted You must always check to ensure that the value is unique.

If you hit a conflict, you must rebuild your entire hash table (the list of integer values you have

generated so far).

Trang 4

Since you want to make sure that your base and hash_size values are applied consistently to all hashings for a particular application, you should never call the GET_HASH_VALUE function

directly Instead, you should build a "wrapper" around it that presets all of the arguments except the

string that you are hashing This technique is shown in the following example.

10.1.2.12.1 Example

The following example demonstrates how to use the hash function It also shows how to use the function to build an alternative index on a PL/SQL table Finally, it compares the performance of hash−based lookups versus a "full table scan" of a PL/SQL table Comments in the program should make it easy to follow the algorithm.

NOTE: The demohash procedure makes use of the p.l procedure, the PL/Vision replacement

for the much more awkward and limited DBMS_OUTPUT.PUT_LINE, as well as the

PLVtmr package.[1]

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

CREATE OR REPLACE PROCEDURE demohash (counter IN INTEGER)

IS

v_row PLS_INTEGER;

v_name VARCHAR2(30);

hashing_failure EXCEPTION;

/* Define the PL/SQL table */

TYPE string_tabtype IS TABLE OF VARCHAR2(60)

INDEX BY BINARY_INTEGER;

names string_tabtype;

/* A function which returns the hashed value */

FUNCTION hashval (value IN VARCHAR2) RETURN NUMBER

IS

BEGIN

RETURN DBMS_UTILITY.GET_HASH_VALUE

(value, 37, 1073741824); /* POWER (2, 30) */

END hashval;

/* Add a name to the table, using the hash function to

determine the row in which the value is placed Ah,

the beauty of sparse PL/SQL tables! */

PROCEDURE addname (nm IN VARCHAR2) IS

BEGIN

v_row := hashval (nm);

names (v_row) := nm;

END;

/* Obtain the row for a name by scanning the table */

FUNCTION rowbyscan (nm IN VARCHAR2) RETURN PLS_INTEGER

IS

v_row PLS_INTEGER := names.FIRST;

retval PLS_INTEGER;

BEGIN

LOOP

EXIT WHEN v_row IS NULL;

IF names(v_row) = nm

THEN

retval := v_row;

EXIT;

ELSE

v_row := names.NEXT (v_row);

END IF;

END LOOP;

RETURN retval;

Trang 5

END;

/* Obtain the row for a name by hashing the string */

FUNCTION rowbyhash (nm IN VARCHAR2) RETURN PLS_INTEGER

IS

BEGIN

RETURN hashval (nm);

END;

BEGIN

/* Load up the table with a set of strings based on the number

of iterations requested This allows us to easily test the

scalability of the two algorithms */

FOR i IN 1 counter

LOOP

addname ('Steven' || i);

addname ('Veva' || i);

addname ('Eli' || i);

addname ('Chris' || i);

END LOOP;

/* Verify that there were no hashing conflicts (the COUNT should

be 4 x counter */

p.l ('Count in names', names.COUNT);

IF names.COUNT != 4 * counter

THEN

p.l ('Hashing conflict! Test suspended ');

RAISE hashing_failure;

END IF;

/* Verify that the two scans return matching values */

v_name := 'Eli' || TRUNC (counter/2);

p.l ('scan',rowbyscan (v_name));

p.l ('hash',rowbyhash (v_name));

IF rowbyscan (v_name) != rowbyhash (v_name)

THEN

p.l ('Scanned row differs from hashed row Test suspended ');

RAISE hashing_failure;

END IF;

/* Time performance of retrieval via scan */

plvtmr.capture;

FOR i IN 1 counter

LOOP

v_row := rowbyscan (v_name);

END LOOP;

plvtmr.show_elapsed ('scan');

/* Time performance of retrieval via hashed value */

plvtmr.capture;

FOR i IN 1 counter

LOOP

v_row := rowbyhash (v_name);

END LOOP;

plvtmr.show_elapsed ('hash');

EXCEPTION

WHEN hashing_failure

THEN

NULL;

END;

/

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

TỪ KHÓA LIÊN QUAN