25 June 2007

Where Is Default Values Of Procedure Arguments?

Oracle has powerful utilities to extract metadata of database objects. [dba|all|user]_* views and some dbms_* packages gives related information. These features are very useful developers who writes code generation utilities like me. I always playing with these packages and views to generate automized PL/SQL codes. I will share my utilities as soon as possible with this blog.
Let's come the subject that i mentioned in the subject. "Where Is Default Values Of Procedure Arguments?" Has anyone knows where they are, please contact me :). I want to share my experiences about this job:

Suppose procedure below
SQL> CREATE OR REPLACE PROCEDURE temp_prc
2 (
3 pin_Argument1 IN NUMBER DEFAULT 123456,
4 pis_Argument2 IN VARCHAR2
5 ) IS
6 BEGIN
7 NULL;
8 END temp_prc;
9 /

Procedure created
SQL>
If you query [dba|all|user]_arguments view you can not see default values.
SQL> SELECT a.argument_name, a.data_type, a.default_value, a.in_out
2 FROM user_arguments a
3 WHERE a.object_name = 'TEMP_PRC';< /FONT >

ARGUMENT_NAME DATA_TYPE DEFAULT_VALUE IN_OUT
------------------ ------------ ------------------ ---------
PIS_ARGUMENT2 VARCHAR2 IN
PIN_ARGUMENT1 NUMBER IN

SQL>

In the documentation of 9i:
DEFAULT_VALUE( LONG )       : Default value for the argument
DEFAULT_LENGTH( NUMBER ) : Length of the default value for the argument
This information is wrong. ( Oracle Bug 24176 )

But in documentation 10g, it was corrected.
DEFAULT_VALUE( LONG )      : Reserved for future use
DEFAULT_LENGTH( NUMBER ) : Reserved for future use

Is there any way to find out deafult values? Why oracle hides this information? I have not answered the questions now. Maybe a bit later, they can be solved. I found some sys views that shows if an argument has a default value or not. But still no information about default values!

SQL> SELECT o.NAME, a.argument, a.default#, a.default$
2 FROM sys.obj$ o, sys.argument$ a
3 WHERE o.obj# = a.obj#
4 AND o.NAME = 'TEMP_PRC';

NAME ARGUMENT DEFAULT# DEFAULT$
------------------------------ ------------------------------ ---------- --------
TEMP_PRC PIN_ARGUMENT1 1
TEMP_PRC PIS_ARGUMENT2

SQL>
Another simple replacement for query above can be describe comamnd of SQL*Plus
SQL> describe TEMP_PRC;
Parameter Type Mode Default?
------------- -------- ---- --------
PIN_ARGUMENT1 NUMBER IN Y
PIS_ARGUMENT2 VARCHAR2 IN

SQL>

For programmatic interface, there is a supplied package, dbms_describe, that describes how program units has interfaces. Again there is no way to find out default values...
SQL> DECLARE
2 overload sys.dbms_describe.number_table;
3 position sys.dbms_describe.number_table;
4 LEVEL sys.dbms_describe.number_table;
5 argument_name sys.dbms_describe.varchar2_table;
6 datatype sys.dbms_describe.number_table;
7 default_value sys.dbms_describe.number_table;/*default_value 1 if the argument being described has a default value; otherwise, the value is 0. */
8 in_out sys.dbms_describe.number_table;
9 length sys.dbms_describe.number_table;
10 PRECISION sys.dbms_describe.number_table;
11 scale sys.dbms_describe.number_table;
12 radix sys.dbms_describe.number_table;
13 spare sys.dbms_describe.number_table;
14 BEGIN
15 sys.dbms_describe.describe_procedure(object_name => 'HR.TEMP_PRC',
16 reserved1 => NULL,
17 reserved2 => NULL,
18 overload => overload,
19 position => position,
20 LEVEL => LEVEL,
21 argument_name => argument_name,
22 datatype => datatype,
23 default_value => default_value,
24 in_out => in_out,
25 length => length,
26 PRECISION => PRECISION,
27 scale => scale,
28 radix => radix,
29 spare => spare,
30 include_string_constraints => TRUE);
31
32
33 FOR i IN 1 .. overload.LAST LOOP
34 dbms_output.put_line('default value for argument ' || argument_name(i) ||
35 ' is ' || default_value(i));
36 END LOOP;
37 END;
38 /

default value for argument PIN_ARGUMENT1 is 1
default value for argument PIS_ARGUMENT2 is 0

PL/SQL procedure successfully completed
SQL>

There are some other ways to get procedure codes programatically. One of them is metadata API:
SQL> SELECT dbms_metadata.get_ddl('PROCEDURE','TEMP_PRC', 'HR') prc_ddl FROM dual;
CREATE OR REPLACE PROCEDURE "HR"."TEMP_PRC"
(
pin_Argument1 IN NUMBER DEFAULT 123456,
pis_Argument2 IN VARCHAR2
) IS
BEGIN
NULL;
END temp_prc;

PL/SQL procedure successfully completed
--
The other way is dbms_preprocessor package:
SQL> exec dbms_preprocessor.print_post_processed_source('PROCEDURE', 'HR', 'TEMP_PRC' );
PROCEDURE temp_prc
(
pin_Argument1 IN NUMBER DEFAULT 123456,
pis_Argument2 IN VARCHAR2
) IS
BEGIN
NULL;
END temp_prc;


Finally I could not find out where they are....

No comments: