Oracle Built−in Packages- P99 doc

5 218 0
Oracle Built−in Packages- P99 doc

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

Thông tin tài liệu

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; [Appendix A] What's on the Companion Disk? 10.1.2 The DBMS_UTILITY Interface 481 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 [Appendix A] What's on the Companion Disk? 10.1.2 The DBMS_UTILITY Interface 482 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 2 30 . • 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). • [Appendix A] What's on the Companion Disk? 10.1.2 The DBMS_UTILITY Interface 483 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; [Appendix A] What's on the Companion Disk? 10.1.2 The DBMS_UTILITY Interface 484 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; / [Appendix A] What's on the Companion Disk? 10.1.2 The DBMS_UTILITY Interface 485 . 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. 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. establishes the low point of the range of values for the hash table. • Use a very large number, and, at Oracle& apos;s suggestion, a power of 2, for the hash size to obtain best results. I usually employ

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

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

Tài liệu liên quan