暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 参数为null时的歧义重载

askTom 2018-06-18
408

问题描述

我有一个包含重载函数的包,它接受一个参数 (整数/VARCHAR2)
并返回一个boobelean,指示是否存在具有对应列的寄存器
与参数相同的值。

在测试中,当输入参数为null时,它似乎无法区分EXISTE可能执行的版本。
如果我将参数转换为数字或char,它会

有人知道另一种更优雅的方法,而不是铸造?

函数查阅的表格的概要说明是:

CREATE TABLE TGEOMUNICIPIOS 
   ( 
 ID NUMBER(*,0), 
 CODINEMUNICIPIO VARCHAR2(11 BYTE)
   );



仅插入一条记录以证明问题:

 INSERT INTO TGEOMUNICIPIOS VALUES ( 6015, '06015000000' );
 COMMIT;



包装规格和主体为:

create or replace PACKAGE PAQ_TGEOMUNICIPIOS
IS
...    
    FUNCTION EXISTE 
    (
    pe_idmunicipio IN TGEOMUNICIPIOS.ID%TYPE
    )
    RETURN BOOLEAN;
    /*
    Devuelve un booleano indicando si existe un municipio con el identificador
    proporcionado. 
    */   

    FUNCTION EXISTE (
    pe_inemunicipio IN TGEOMUNICIPIOS.CODINEMUNICIPIO%TYPE
    )
    RETURN BOOLEAN;
    /*
    Devuelve un booleano indicando si existe un municipio dado su código ine. 
    */  
...
END PAQ_TGEOMUNICIPIOS;

create or replace PACKAGE BODY  PAQ_TGEOMUNICIPIOS
IS
...    
    
    FUNCTION EXISTE 
    (
    pe_idmunicipio IN TGEOMUNICIPIOS.ID%TYPE
    )
    RETURN BOOLEAN
    IS
      v_existe   INTEGER;
    BEGIN
            
      SELECT ID
        INTO v_existe
        FROM TGEOMUNICIPIOS
       WHERE ID = pe_idmunicipio;
    
      RETURN TRUE;
      
    EXCEPTION
    WHEN NO_DATA_FOUND
    THEN
       RETURN FALSE;
         
    END EXISTE;
    

    FUNCTION EXISTE (
    pe_inemunicipio IN TGEOMUNICIPIOS.CODINEMUNICIPIO%TYPE
    )
    RETURN BOOLEAN
    IS
      v_existe  INTEGER;
    BEGIN
    
      SELECT ID
        INTO v_existe
        FROM TGEOMUNICIPIOS
       WHERE CODINEMUNICIPIO LIKE pe_inemunicipio;         
    
      RETURN TRUE;
      
    EXCEPTION
    WHEN OTHERS 
    THEN
       RETURN FALSE;
                
    END EXISTE;
...
END PAQ_TGEOMUNICIPIOS;    



测试代码:
DECLARE
BEGIN
   
   --next line doesn't distinguish which version to run
   dbms_output.put_line ( paq_conversiones.f_boolean_a_cadena ( paq_tgeomunicipios.existe ( null ) ) );  
   
   --next line forces to run the first version
   dbms_output.put_line ( paq_conversiones.f_boolean_a_cadena ( paq_tgeomunicipios.existe ( TO_NUMBER( null ) ) ) );  
   
   --next line forces to run the second version
   dbms_output.put_line ( paq_conversiones.f_boolean_a_cadena ( paq_tgeomunicipios.existe ( TO_CHAR( null ) ) ) );

END;   



它返回:

ORA-06550: línea 5, columna 65:
PLS-00307: too many declarations of 'EXISTE' match this call
ORA-06550: línea 5, columna 4:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:


专家解答

这是您的示例的缩减版本

SQL> create or replace
  2  package body pkg is
  3    procedure P(x int) is begin null; end;
  4    procedure P(x varchar2) is begin null; end;
  5  end;
  6  /

Package body created.

SQL>
SQL> exec pkg.p(1);

PL/SQL procedure successfully completed.

SQL> exec pkg.p('1');

PL/SQL procedure successfully completed.

SQL> exec pkg.p(null);
BEGIN pkg.p(null); END;

      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00307: too many declarations of 'P' match this call
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored


但现实是-这很少是一个问题。因为它非常罕见,我们会把解释术语 “空” 传递给一个包。他们从别的地方收到一些东西。只要我们 * 知道 * 数据类型,它就可以正常工作。例如

SQL> declare
  2    var int;
  3  begin
  4    pkg.p(var);
  5  end;
  6  /

PL/SQL procedure successfully completed.


因此,尽管它看起来像一个问题-我认为您很少会受到它的打击。毕竟,你打算多久用一个文字而不是变量作为参数来显式调用你的包?
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论