Pregunta

Estoy tratando de componer una función para obtener hashes MD5 de bits que he reunido aquí y allá. Quiero obtener la representación hexadecimal de caso inferior del hash. Tengo esto hasta ahora:

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;

No estoy seguro sobre el tipo de retorno de la función. DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM Parece la elección apropiada y, por lo que puedo decir, funciona como se esperaba, pero la definición del paquete para dbms_obfuscation_toolkit como lo muestra el desarrollador de SQL muestra esto:

SUBTYPE varchar2_checksum IS VARCHAR2(16);

La salida tiene 32 caracteres, por lo que debo estar haciendo algo mal. Mis preguntas:

  • ¿Cuál es el tipo correcto para el RETURN ¿declaración?
  • ¿Estoy haciendo conversiones innecesarias para calcular el hash?
¿Fue útil?

Solución

Es una peculiaridad de Oracle PL/SQL que los parámetros de procedimiento y los tipos de retorno de la función no pueden limitarse. Es decir, no podemos tener un procedimiento con una firma como esta:

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>

Claro que podemos definir el parámetro del procedimiento usando un subtipo, pero Oracle lo ignorará. Lo mismo ocurre con los tipos de retorno de la función ...

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>

La única forma de limitar los parámetros y los tipos de retorno es declarar variables utilizando subtipos dentro del procedimiento almacenado. Use las variables dentro del paquete y asignarlas a los parámetros de salida (o devolver la variable para las funciones).

Que es una forma de decir de largo aliento, puedes usar DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM En su código, confía en que no evitará que su función devuelva 32 caracteres.

Sin embargo, confundirá a los desarrolladores que buscarán la declaración de subtipo. En el peor de los casos, estas personas usarán el subtipo para declarar sus propias variables de trabajo con el siguiente resultado trágico:

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>

Por lo tanto, es mejor no usar un subtipo inapropiado. En su lugar, declare el suyo propio.

Otros consejos

Aquí tienes:

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;

La longitud 32 se debe a que es una representación hexadecimal del valor crudo (16). O bien, modifique anteriormente para emitir la versión RAW y almacenar la RAW en una columna RAW (menos espacio utilizado, pero hará conversiones futuras de RawToX y Hextoraw, créeme).

Salud

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top