在Oracle 11g中测试异常处理

时间:2011-02-03 00:02:22

标签: oracle exception-handling

我有这个oracle代码

 FUNCTION get_enc_val(p_in                          IN VARCHAR2,
                        p_key                         IN VARCHAR2
                       )
   RETURN raw
   IS
      p_title_procedure_name        VARCHAR2(100) := 'get_enc_val';
      l_enc_val                     RAW(2000);
      l_mod                         PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
      v_key                         VARCHAR2(16);

      encryption_ex Exception;
   BEGIN



      v_key                 := RPAD(SUBSTR(TRIM(p_key), 1, 16), 16, '0');
      l_enc_val             := DBMS_CRYPTO.encrypt(UTL_RAW.cast_to_raw(p_in), l_mod, UTL_RAW.cast_to_raw(v_key));


      RAISE encryption_ex;

      RETURN l_enc_val;

   EXCEPTION
      WHEN OTHERS THEN
         service_func.log_error(p_title_package_name || '.' || p_title_procedure_name, 'Proc', NULL, SYSDATE, SQLERRM, p_in || '~' || p_key);
         RETURN 'Encryption_ERROR';
   END;

当我运行这个时,我得到ORA-06510未处理的用户定义异常,而它应该真正返回字符串'Encryption_ERROR'。这给了什么?它转到Exception块,因为我看到了log_error函数的结果。问题是,是不是异常块应该处理任何异常?

我有点困惑。

2 个答案:

答案 0 :(得分:4)

问题是你的第二个RETURN语句在声明函数返回RAW时返回VARCHAR2。您可以通过调用UTL_RAW.CAST_TO_RAW来解决这个问题,即

   EXCEPTION
      WHEN OTHERS THEN
         service_func.log_error(p_title_package_name || '.' || 
                                   p_title_procedure_name, 
                                'Proc', 
                                NULL, 
                                SYSDATE, 
                                SQLERRM, 
                                p_in || '~' || p_key);
         RETURN utl_raw.cast_to_raw( 'Encryption_ERROR' );
   END;

如果我声明两个函数,一个返回硬编码字符串,另一个返回RAW,你会看到差异(我正在删除DBMS_CRYPTO调用和LOG_ERROR调用)。如果我声明一个返回RAW的函数,你会得到一个结果(尽管人类必须将原始数据转换为字符串才能理解结果)

SQL> ed
Wrote file afiedt.buf

  1  create or replace function throw_exception
  2    return raw
  3  is
  4    my_exception exception;
  5  begin
  6    raise my_exception;
  7  exception
  8    when others then
  9      return utl_raw.cast_to_raw( 'Foo' );
 10* end;
SQL> /

Function created.

SQL> select throw_exception
  2    from dual;

THROW_EXCEPTION
-----------------------------------------------------------------------------

466F6F

如果我只是返回一个字符串,我会得到你得到的同样的异常

SQL> ed
Wrote file afiedt.buf

  1  create or replace function throw_exception2
  2    return raw
  3  is
  4    my_exception exception;
  5  begin
  6    raise my_exception;
  7  exception
  8    when others then
  9      return 'Foo';
 10* end;
SQL> /

Function created.

SQL> select throw_exception2
  2    from dual;
select throw_exception2
       *
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: hex to raw conversion error
ORA-06512: at "SCOTT.THROW_EXCEPTION2", line 9
ORA-06510: PL/SQL: unhandled user-defined exception

当然,另一种选择是声明函数返回VARCHAR2。但我宁愿在RAW中使用哈希值和加密数据而不是VARCHAR2,这样你就不必担心字符集转换问题会破坏数据。

答案 1 :(得分:-1)

由于您确定service_func.log_error(...);没有引发错误,因此调用过程/函数必须抛出该错误。

这是引起同样错误的事情。

create or replace function abc return raw is
begin
    return 'Encryption_ERROR';
end;
/

declare
     r raw(50);
begin
     r := abc;
end;
/