4

我正在尝试编写一个函数来从我在这里和那里收集的位中获取 MD5 哈希。我想获得哈希的小写十六进制表示。到目前为止我有这个:

CREATE OR REPLACE FUNCTION MD5 (
    CADENA IN VARCHAR2
) RETURN DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM
AS
BEGIN
    RETURN LOWER(
        RAWTOHEX(
            UTL_RAW.CAST_TO_RAW(
                DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING => CADENA)
            )
        )
    );
END;

我不确定函数的返回类型。DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM看起来是合适的选择,据我所知,它按预期工作,但dbms_obfuscation_toolkitSQL Developer 显示的包定义显示了这一点:

SUBTYPE varchar2_checksum IS VARCHAR2(16);

输出有 32 个字符,所以我一定做错了什么。我的问题:

  • 语句的正确类型是RETURN什么?
  • 我是否在进行不必要的转换来计算哈希?
4

2 回答 2

10

干得好:

create or replace function getMD5(
  in_string in varchar2)
return varchar2
as
  cln_md5raw raw(2000);
  out_raw raw(16);
begin
  cln_md5raw := utl_raw.cast_to_raw(in_string);
  dbms_obfuscation_toolkit.md5(input=>cln_md5raw,checksum=>out_raw);
  -- return hex version (32 length)
  return rawtohex(out_raw);
end;

32 长度是因为它是 raw(16) 值的十六进制表示。或者,修改上面的内容以输出原始版本并将原始版本存储在 RAW 列中(使用的空间更少,但您将在未来进行 rawtohex 和 hextoraw 转换,相信我)。

干杯

于 2011-05-05T17:17:41.143 回答
5

不能限制存储过程参数和函数返回类型是 Oracle PL/SQL 的一个特点。也就是说,我们不能有这样一个签名的过程:

SQL> create or replace procedure my_proc (p1 in varchar2(30))
  2  is
  3  begin
  4      null;
  5  end;
  6  /

Warning: Procedure created with compilation errors.

SQL> show error
Errors for PROCEDURE MY_PROC:

LINE/COL ERROR
-------- -----------------------------------------------------------------
1/34     PLS-00103: Encountered the symbol "(" when expecting one of the
         following:
         := . ) , @ % default character
         The symbol ":=" was substituted for "(" to continue.

SQL> create or replace procedure my_proc (p1 in varchar2)
  2  is
  3  begin
  4      null;
  5  end;
  6  /

Procedure created.

SQL>

当然,我们可以使用 SUBTYPE 定义过程的参数,但 Oracle 会忽略它。函数返回类型也是如此......

SQL> create or replace package my_subtypes as
  2      subtype ltd_string is varchar2(30);
  3  end;
  4  /

Package created.

SQL> create or replace function my_func return my_subtypes.ltd_string
  2  is
  3  begin
  4      return lpad('a', 4000, 'a');
  5  end;
  6  /

Function created.

SQL> select length(my_func) from dual
  2  /

LENGTH(MY_FUNC)
---------------
           4000

SQL>

限制参数和返回类型的唯一方法是在存储过程中使用子类型声明变量。使用包中的变量,并将它们分配给 OUT 参数(或返回函数的变量)。

这是一种冗长的说法,您可以 DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM在代码中使用确信它不会阻止您的函数返回 32 个字符。

但是,它会使查找 SUBTYPE 声明的开发人员感到困惑。在最坏的情况下,这些人将使用子类型来声明他们自己的工作变量,结果如下:

SQL> declare
  2      v my_subtypes.ltd_string;
  3  begin
  4      v := my_func;
  5  end;
  6  /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4


SQL>

所以,最好不要使用不合适的子类型。而是声明你自己的。

于 2011-05-05T12:58:12.773 回答