在Oracle中,有没有办法区分'参数没有默认值'和'paratemer的默认值为null'

时间:2016-09-02 09:37:44

标签: oracle

我正在尝试创建一个调试工具:一些提供包名称并为其生成调试包装的东西(具有类似过程的包;这些过程将记录调用,参数值,执行原始过程并记录调用结果)。

通常我做了,但我发现了一个不好的情况:在查看USER_PROCEDURES和USER_ARGUMENTS时,没有默认值的参数和具有null默认值的参数之间没有任何差异。有没有办法区分它?

现在我只是将'default null'放到任何包装器的'in'参数中,但没有一个,但这对我来说并不好。我找到的第二种方法是解析USER_SOURCE,但我猜这通常很讨厌。

===编辑:感谢@phonetic_man,对于Oracle 11,有USER_ARGUMENTS.DEFAULTED列。是否有Oracle 10的决定? ===

1 个答案:

答案 0 :(得分:0)

正如@phonetic_man在评论中所述,在11g中,user_arguments视图有一个defaulted列。这在早期版本中不存在。在10g中有一个sqljutl包,as part of the database's Java installation。你可以使用has_default函数:

desc sys.sqljutl

...
FUNCTION HAS_DEFAULT RETURNS NUMBER
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OID                            NUMBER                  IN
 PROC                           CHAR                    IN
 SEQ                            NUMBER                  IN
 OVR                            NUMBER                  IN
...

您可以将user_arguments中的列值传递到该函数中:

select object_name, package_name, argument_name, data_type, defaulted,
  sys.sqljutl.has_default(object_id,
    case when package_name is null then null else object_name end,
    sequence,
    nvl(overload, 0)) as defaulted
from user_arguments
where package_name = '<YOUR_PACKAGE>'
and object_name = '<YOUR PROCEDURE>';

case表达式是因为函数执行略有不同的查询,具体取决于传递的对象名是否为null;它只需要为包过程设置,而不是为独立过程设置。 (你可以在$ORACLE_HOME/rdbms/admin/initsqlj.sql中看到它实际上在做什么。)

create package pack42 as
  procedure proc42 (p1 number, p2 varchar2 default null);
end pack42;
/

create package body pack42 as
  procedure proc42 (p1 number, p2 varchar2 default null) is
  begin
    null;
  end proc42;
end pack42;
/

select object_name, package_name, argument_name, data_type, -- defaulted,
  sys.sqljutl.has_default(object_id,
    case when package_name is null then null else object_name end,
    sequence,
    nvl(overload, 0)) as defaulted
from user_arguments
where package_name = 'PACK42'
and object_name = 'PROC42';

OBJECT_NAME PACKAGE_NAME ARGUMENT_NAME DATA_TYPE  DEFAULTED
----------- ------------ ------------- --------- ----------
PROC42      PACK42       P2            VARCHAR2           1
PROC42      PACK42       P1            NUMBER             0

和一个独立的程序:

create procedure proc42 (p1 number, p2 varchar2 default null) as
begin
  null;
end;
/

select object_name, package_name, argument_name, data_type, -- defaulted,
  sys.sqljutl.has_default(object_id,
    case when package_name is null then null else object_name end,
    sequence,
    nvl(overload, 0)) as defaulted
from user_arguments
where package_name is null
and object_name = 'PROC42';

OBJECT_NAME PACKAGE_NAME ARGUMENT_NAME DATA_TYPE  DEFAULTED
----------- ------------ ------------- --------- ----------
PROC42                   P2            VARCHAR2           1
PROC42                   P1            NUMBER             0

如果有默认值,则返回1,如果没有则返回0。

这也适用于11g,而user_arguments.defaulted列正在查看相同的基础数据字典信息(argument$.default#);虽然它被转换为Y / N,你当然可以自己做。

使用11g中的相同包构建,您可以看到两个标志:

select object_name, package_name, argument_name, data_type, defaulted,
  sys.sqljutl.has_default(object_id,
    case when package_name is null then null else object_name end,
    sequence,
    nvl(overload, 0)) as defaulted
from user_arguments
where package_name = 'PACK42'
and object_name = 'PROC42';

OBJECT_NAME PACKAGE_NAME ARGUMENT_NAME DATA_TYPE D  DEFAULTED
----------- ------------ ------------- --------- - ----------
PROC42      PACK42       P1            NUMBER    N          0
PROC42      PACK42       P2            VARCHAR2  Y          1