10. Miscellaneous Packages
Contents:
You can't find a neat category for everything, can you? This chapter brings together a variety of useful packages you are sure to dip into on a regular basis:
10.1 DBMS_UTILITY: Performing Miscellaneous OperationsThe DBMS_UTILITY package is the "miscellaneous package" for PL/SQL. It contains programs that perform a wide variety of operations (listed in Table 10.1 ).
10.1.1 Getting Started with DBMS_UTILITYThe DBMS_UTILITY package is created when the Oracle database is installed. The dbmsutil.sql script (found in the built-in packages source code directory, as described in Chapter 1, Introduction ) contains the source code for this package's specification. This script is called by catproc.sql , which is normally run immediately after database creation. The script creates the public synonym DBMS_UTILITY for the package and grants EXECUTE privilege on the package to public. All Oracle users can reference and make use of this package. Table 10.1 summarizes the programs available with DBMS_UTILITY.
10.1.1.1 DBMS_UTILITY nonprogram elementsIn addition to the functions and procedures defined in the package, DBMS_UTILITY also declares five PL/SQL tables that are used either as input into or output from the package's built-in modules. By the way, these tables are also used by other built-in packages, such as DBMS_DEFER. See Chapter 10 of Oracle PL/SQL Programming for more information about PL/SQL tables (also called index-by tables as of Oracle8).
You can declare PL/SQL tables based on these TABLE type statements as shown below: DECLARE short_name_list DBMS_UTILITY.NAME_ARRAY; long_name_list DBMS_UTILITY.INDEX_TABLE_TYPE; BEGIN ... Of course, if you do declare PL/SQL tables based on DBMS_UTILITY data structures, then those declarations will change with any changes in the package. 10.1.2 The DBMS_UTILITY InterfaceThis section describes each of the programs in the DBMS_UTILITY package; because of the miscellaneous nature of these programs, they are simply listed in alphabetical order. 10.1.2.1 The DBMS_UTILITY. ANALYZE_DATABASE procedureThis procedure analyzes all the tables, clusters, and indexes in the entire database. The header for the procedure follows: PROCEDURE DBMS_UTILITY.ANALYZE_DATABASE (method IN VARCHAR2 ,estimate_rows IN NUMBER DEFAULT NULL ,estimate_percent IN NUMBER DEFAULT NULL ,method_opt IN VARCHAR2 DEFAULT NULL); Parameters are summarized in this table.
Here are the valid entries for the method argument, and the resulting activity (when you pass one of these values, they must be enclosed in single quotes):
Here are the valid method_opt entries and the resulting impact (when you pass one of these values, they must be enclosed in single quotes):
10.1.2.1.1 ExampleHere is an example of a request to this program to analyze all columns in my database: BEGIN DBMS_UTILITY.ANALYZE_DATABASE ( 'ESTIMATE', 100, 50, 'FOR ALL COLUMNS SIZE 200'); END; 10.1.2.2 The DBMS_UTILITY. ANALYZE_SCHEMA procedureThis procedure analyzes all of the tables, clusters, and indexes in the specified schema. The header for the procedure follows: PROCEDURE DBMS_UTILITY.ANALYZE_SCHEMA (schema IN VARCHAR2 ,method IN VARCHAR2 ,estimate_rows IN NUMBER DEFAULT NULL ,estimate_percent IN NUMBER DEFAULT NULL ,method_opt IN VARCHAR2 DEFAULT NULL); Parameters are summarized in this table.
Here are the valid entries for the method argument, and the resulting activity (when you pass one of these values, they must be enclosed in single quotes):
Here are the valid method_opt entries and the resulting impact (when you pass one of these values, they must be enclosed in single quotes):
10.1.2.2.1 ExampleHere is an example of a request to this program to analyze all indexes in my current schema: BEGIN DBMS_UTILITY.ANALYZE_SCHEMA ( USER, 'ESTIMATE', 100, 50, 'FOR ALL INDEXES'); END; / 10.1.2.3 The DBMS_UTILITY. ANALYZE_PART_OBJECT procedure (Oracle8 Only)This procedure analyzes the specified, partitioned object. Here's the header for the procedure: PROCEDURE DBMS_UTILITY.ANALYZE_PART_OBJECT (schema IN VARCHAR2 DEFAULT NULL ,object_name IN VARCHAR2 DEFAULT NULL ,object_type IN CHAR DEFAULT 'T' ,command_type IN CHAR DEFAULT 'E' ,command_opt IN VARCHAR2 DEFAULT NULL ,sample_clause IN VARCHAR2 DEFAULT 'SAMPLE 5 PERCENT'); Parameters are summarized in the following table.
Running this program is equivalent to executing this SQL command, ANALYZE TABLE|INDEX [<schema>.]<object_name> PARTITION <pname> [<command_type>] [<command_opt>] [<sample_clause>] for each partition of the specified object. DBMS_UTILITY will submit a job for each partition, so that the analysis can run in parallel using job queues. It is up to the user to control the number of concurrent jobs that will be started by setting correctly the initialization parameter JOB_QUEUE_PROCESSES. Any syntax errors encountered for the object specification will be reported in SNP trace files. 10.1.2.3.1 ExampleHere is an example of a request to this program to delete the statistics associated with the columns of the emp table: BEGIN DBMS_UTILITY.ANALYZE_PART_OBJECT ( USER, 'EMP', 'T', 'DELETE STATISTICS', 'FOR ALL COLUMNS'); END; / 10.1.2.4 The DBMS_UTILITY.COMMA_TO_TABLE procedureThe COMMA_TO_TABLE procedure parses a comma-delimited list and places each name into a PL/SQL table. Here's the header for the procedure: PROCEDURE DBMS_UTILITY.COMMA_TO_TABLE (list IN VARCHAR2 ,tablen OUT BINARY_INTEGER ,tab OUT UNCL_ARRAY); Parameters are summarized in the following table.
This procedure uses the NAME_TOKENIZE procedure to determine which of the string's characters are names and which are commas. 10.1.2.4.1 ExampleCOMMA_TO_TABLE is a handy utility if you happen to have a comma-delimited string; otherwise, it does you no good. Just think: with a tiny bit more effort, Oracle could have provided us with a much more general-purpose and useful string parsing engine. In any case, here is a sample use of DBMS_UTILITY.COMMA_TO_TABLE. It takes two different lists of correlated information, parses them into rows in two different tables, and then uses that data in a series of UPDATE statements. /* Filename on companion disk: upddelist.sp */* CREATE OR REPLACE PROCEDURE upd_from_list ( empno_list IN VARCHAR2, sal_list IN VARCHAR2) IS empnos DBMS_UTILITY.UNCL_ARRAY; sals DBMS_UTILITY.UNCL_ARRAY; numemps INTEGER; BEGIN DBMS_UTILITY.COMMA_TO_TABLE (empno_list, numemps, empnos); DBMS_UTILITY.COMMA_TO_TABLE (sal_list, numemps, sals); FOR rownum IN 1 .. numemps LOOP UPDATE emp SET sal = TO_NUMBER (sals(rownum)) WHERE empno = TO_NUMBER (empnos(rownum)); END LOOP; END; /
10.1.2.5 The DBMS_UTILITY. COMPILE_SCHEMA procedureThis procedure compiles all procedures, functions, and packages in the specified schema. The header for the procedure is, PROCEDURE DBMS_UTILITY.COMPILE_SCHEMA (schema VARCHAR2); where schema is the name of the schema. I have heard reports from developers that it sometimes seems as though they run this program and it does not do anything at all. As I write this, though, I have requested that DBMS_UTILITY recompile my PL/Vision schema, and the buzzing of the hard drive light, as well as the delay in the resurfacing of my SQL*Plus prompt, attests to the fact that it is indeed recompiling the scores of packages in this schema. 10.1.2.5.1 ExampleI execute the following command in SQL*Plus to recompile all programs in my current schema. Notice that before the recompilation, I had a single invalid package. Afterwards, all objects are valid. SQL> select object_name from user_objects where status='INVALID'; OBJECT_NAME --------------------------------------------------------------- PLGTE SQL> exec DBMS_UTILITY.COMPILE_SCHEMA(user) PL/SQL procedure successfully completed. SQL> select object_name from user_objects where status='INVALID'; no rows selected 10.1.2.6 The DBMS_UTILITY. DATA_BLOCK_ADDRESS_BLOCK functionThis function extracts and returns the block number of a data block address. The header for this function is, FUNCTION DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK (dba IN NUMBER) RETURN NUMBER; where dba is the data block address. 10.1.2.7 The DBMS_UTILITY. DATA_BLOCK_ADDRESS_FILE functionThis function extracts and returns the file number of a data block address. The header for this function is, FUNCTION DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE (dba IN NUMBER) RETURN NUMBER; where dba is the data block address. 10.1.2.8 The DBMS_UTILITY. DB_VERSION procedureThis procedure (PL/SQL8 only) returns version information for the current database instance. Here's the header for this procedure: PROCEDURE DBMS_UTILITY.DB_VERSION (version OUT VARCHAR2 ,compatibility OUT VARCHAR2); Parameters are summarized in the following table.
10.1.2.8.1 ExampleBefore this function was available, you had to build a query against a V$ table in order to obtain this information. Now it is easy to obtain your database version from within PL/SQL. In fact, you can make it even easier to get this information by building a wrapper around DBMS_UTILITY.DB_VERSION, as shown here: /* Filename on companion disk: dbver.spp */* CREATE OR REPLACE PACKAGE db IS FUNCTION version RETURN VARCHAR2; FUNCTION compatibility RETURN VARCHAR2; END; / CREATE OR REPLACE PACKAGE BODY db IS v VARCHAR2(100); c VARCHAR2(100); PROCEDURE init_info IS 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 procedureOracle 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 functionThis 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; 10.1.2.10.1 ExampleI 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 functionThe 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 ExampleThe 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 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 functionThis 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.
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:
10.1.2.12.1 ExampleThe 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.
/* 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; 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; / 10.1.2.13 The DBMS_UTILITY. GET_PARAMETER_VALUE functionAvailable first in PL/SQL8, this function allows you to retrieve the value of a database initialization parameter (set in the INIT.ORA initialization file). Here's the header: FUNCTION DBMS_UTILITY.GET_PARAMETER_VALUE (parnam IN VARCHAR2 ,intval IN OUT BINARY_INTEGER ,strval IN OUT VARCHAR2) RETURN BINARY_INTEGER; The value returned by the function is either of the following:
Parameters are summarized in the following table.
Long desired by Oracle developers, the GET_PARAMETER_VALUE function now allows you to get critical information about the current database instance, including the default date format and lots of information about the way shared memory is configured. And you don't have to use UTL_FILE to read the initialization file. (Chances are your DBA would not enable the database directory holding this file for UTL_FILE access anyway!). Note that if you have more than one entry for the same parameter (certainly a possibility with a parameter such as UTL_FILE_DIR), then this built-in will retrieve only the value associated with the first occurrence of the parameter. You will probably want to build a wrapper around GET_PARAMETER_VALUE to make it easier to retrieve and interpret the results. Why? Whenever you call this built-in function, you must declare two variables to retrieve the OUT arguments. You must then interpret the results. Rather than write all this code and have to remember all these rules, you can build it into a package once and then simply call the appropriate program as needed. A prototype of such a package is shown later in this section. My package specification contains these three sections:
CREATE OR REPLACE PACKAGE dbparm IS /* Generic (by datatype) interfaces to built-in. */ FUNCTION strval (nm IN VARCHAR2) RETURN VARCHAR2; FUNCTION intval (nm IN VARCHAR2) RETURN INTEGER; FUNCTION boolval (nm IN VARCHAR2) RETURN BOOLEAN; /* Encapsulation for specific parameter retrieval */ FUNCTION nls_date_format RETURN VARCHAR2; FUNCTION utl_file_dir RETURN VARCHAR2; FUNCTION db_block_buffers RETURN INTEGER; PROCEDURE showval (nm IN VARCHAR2); END; / Rather than show the entire package body (also found in dbparm.spp ), I will show you the two levels of encapsulation around DBMS_UTILITY.GET_PARAMETER_VALUE found in the package. You can then apply that technique to other parameters of interest. Here is the dbparm.intval function. It calls the built-in procedure and then returns the integer value. You might want to enhance this procedure to check the datatype of the parameter and only return a value if it is in fact a numeric (or Boolean) type. FUNCTION intval (nm IN VARCHAR2) RETURN INTEGER IS valtype PLS_INTEGER; ival PLS_INTEGER; sval VARCHAR2(2000); BEGIN valtype := DBMS_UTILITY.GET_PARAMETER_VALUE (nm, ival, sval); RETURN ival; END; Now I build my dbparm.db_block_buffers package on top of that one as follows: FUNCTION db_block_buffers RETURN INTEGER IS BEGIN RETURN intval ('db_block_buffers'); END; 10.1.2.14 The DBMS_UTILITY. GET_TIME functionThis function returns the number of 100ths of seconds that have elapsed from an arbitrary time. The header for the function follows: FUNCTION DBMS_UTILITY.GET_TIME RETURN NUMBER; You are probably wondering what this "arbitrary time" is and why I don't tell you about what that starting point is. Two reasons: I don't know and it doesn't matter. You should not use GET_TIME to establish the current time, but only to calculate the elapsed time between two events. The following example calculates the number of 100ths of elapsed seconds since the calc_totals procedure was executed: DECLARE time_before BINARY_INTEGER; time_after BINARY_INTEGER; BEGIN time_before := DBMS_UTILITY.GET_TIME; calc_totals; time_after := DBMS_UTILITY.GET_TIME; DBMS_OUTPUT.PUT_LINE (time_after - time_before); END; Without GET_TIME, Oracle functions can only record and provide elapsed time in second intervals, which is a very coarse granularity in today's world of computing. With GET_TIME, you can get a much finer understanding of the processing times of lines in your program. Notice that in my anonymous block I had to declare two local variables, make my calls to GET_TIME, and then compute the difference. I will probably need to perform those actions over and over again in my programs. I might even want to perform timings that cross product lines (e.g., start my timing in a form and then check elapsed time from inside a report module). To make it easier to use GET_TIME in these various ways, I built a package called sptimer ("stored package timer" mechanism), which you can find in the sptimer.sps and sptimer.spb files on the companion disk.[ 2 ]
10.1.2.15 The DBMS_UTILITY. IS_PARALLEL_SERVER functionThis function helps determine whether the database is running in parallel server mode. The specification follows: FUNCTION DBMS_UTILITY.IS_PARALLEL_SERVER RETURN BOOLEAN; The function returns TRUE if the database is running in parallel server mode; otherwise, it returns FALSE. 10.1.2.16 The DBMS_UTILITY. MAKE_DATA_BLOCK_ADDRESS functionUse this function to obtain a valid data block address from a file number and block number. The header follows: FUNCTION DBMS_UTILITY.MAKE_DATA_BLOCK_ADDRESS (file IN NUMBER ,block IN NUMBER) RETURN NUMBER; 10.1.2.16.1 ExampleHere is an example of calling this function and displaying the resulting value: SQL> BEGIN 2 DBMS_OUTPUT.PUT_LINE 3 (DBMS_UTILITY.MAKE_DATA_BLOCK_ADDRESS (10000, 20000)); 4 END; 5 / 268455456 10.1.2.17 The DBMS_UTILITY. NAME_RESOLVE procedureThis procedure resolves the name of an object into its component parts, performing synonym translations as necessary. Here's the header for the procedure: PROCEDURE DBMS_UTILITY.NAME_RESOLVE (name IN VARCHAR2, context IN NUMBER, schema OUT VARCHAR2, part1 OUT VARCHAR2, part2 OUT VARCHAR2, dblink OUT VARCHAR2, part1_type OUT NUMBER, object_number OUT NUMBER); Parameters are summarized in the following table.
An object type may have one of the following values:
The NAME_RESOLVE procedure has six OUT parameters, which means that in order to use this module you will have to declare six variables -- an annoying task that creates an obstacle to casual use of the procedure. I built a procedure called show_name_components precisely to make it easier to take advantage of NAME_RESOLVE. The show_name_components accepts an object name, and then calls DBMS_OUTPUT.PUT_LINE to display the different components of the name. It shows information only if it is relevant; in other words, if there is no part2, then part2 is not displayed. The name of the database link is displayed only if there is a database link associated with that object. Here are some examples of calls to show_name_components: SQL> execute show_name_components('do.pl'); Schema: BOOK Package: DO Name: PL SQL> execute show_name_components('do'); Schema: BOOK Package: DO SQL> execute show_name_components('show_name_components'); Schema: BOOK Procedure: SHOW_NAME_COMPONENTS Here is the show_name_components procedure in its entirety: /* Filename on companion disk: showcomp.sp */* CREATE OR REPLACE PROCEDURE show_name_components (name_in IN VARCHAR2) IS /* variables to hold components of the name */ schema VARCHAR2(100); part1 VARCHAR2(100); part2 VARCHAR2(100); dblink VARCHAR2(100); part1_type NUMBER; object_number NUMBER; /*--------------------- Local Module -----------------------*/ FUNCTION object_type (type_in IN INTEGER) RETURN VARCHAR2 /* Return name for integer type */ IS synonym_type CONSTANT INTEGER := 5; procedure_type CONSTANT INTEGER := 7; function_type CONSTANT INTEGER := 8; package_type CONSTANT INTEGER := 9; BEGIN IF type_in = synonym_type THEN RETURN 'Synonym'; ELSIF type_in = procedure_type THEN RETURN 'Procedure'; ELSIF type_in = function_type THEN RETURN 'Function'; ELSIF type_in = package_type THEN RETURN 'Package'; END IF; END; BEGIN /* Break down the name into its components */ DBMS_UTILITY.NAME_RESOLVE (name_in, 1, schema, part1, part2, dblink , part1_type, object_number); /* If the object number is NULL, name resolution failed. */ IF object_number IS NULL THEN DBMS_OUTPUT.PUT_LINE ('Name "' || name_in || '" does not identify a valid object.'); ELSE /* Display the schema, which is always available. */ DBMS_OUTPUT.PUT_LINE ('Schema: ' || schema); /* If there is a first part to name, have a package module */ IF part1 IS NOT NULL THEN /* Display the first part of the name */ DBMS_OUTPUT.PUT_LINE (object_type (part1_type) || ': ' || part1); /* If there is a second part, display that. */ IF part2 IS NOT NULL THEN DBMS_OUTPUT.PUT_LINE ('Name: ' || part2); END IF; ELSE /* No first part of name. Just display second part. */ DBMS_OUTPUT.PUT_LINE (object_type (part1_type) || ': ' || part2); END IF; /* Display the database link if it is present. */ IF dblink IS NOT NULL THEN DBMS_OUTPUT.PUT_LINE ('Database Link:' || dblink); END IF; END IF; END; / 10.1.2.18 The DBMS_UTILITY.NAME_TOKENIZE procedureThis procedure calls the PL/SQL parser to parse the given name that is in the following format, a [ . b [. c]] [@dblink ] where dblink is the name of a database link. Here's the header for the procedure: PROCEDURE DBMS_UTILITY.NAME_TOKENIZE (name IN VARCHAR2, a OUT VARCHAR2, b OUT VARCHAR2, c OUT VARCHAR2, dblink OUT VARCHAR2, nextpos OUT BINARY_INTEGER); Parameters are summarized in the following table.
NAME_TOKENIZE follows these rules:
10.1.2.19 The DBMS_UTILITY.PORT_STRING functionThe PORT_STRING function returns a string that uniquely identifies the version of Oracle Server and the platform or operating system of the current database instance. The specification for this function follows: FUNCTION DBMS_UTILITY.PORT_STRING RETURN VARCHAR2; Running the PORT_STRING function in Oracle8 on Windows NT, for example, returns the following string: IBMPC/WINNT-8.0.0 The maximum length of the string returned by this function is operating system-specific. 10.1.2.20 The DBMS_UTILITY.TABLE_TO_COMMA procedureThe TABLE_TO_COMMA procedure converts a PL/SQL table into a comma-delimited list. Here's the header for this procedure: PROCEDURE DBMS_UTILITY.TABLE_TO_COMMA (tab IN UNCL_ARRAY, tablen OUT BINARY_INTEGER, list OUT VARCHAR2); Parameters are summarized in the following table.
Copyright (c) 2000 O'Reilly & Associates. All rights reserved. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|