#oracle #plsql #md5 #oracle-xe #subtype
#Oracle #plsql #md5 #oracle-xe #подтип
Вопрос:
Я пытаюсь составить функцию для получения хэшей 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_toolkit
, отображаемое разработчиком SQL, показывает это:
SUBTYPE varchar2_checksum IS VARCHAR2(16);
Выходные данные содержат 32 символа, поэтому я, должно быть, делаю что-то не так. Мои вопросы:
- Какой правильный тип для
RETURN
инструкции? - Выполняю ли я ненужные преобразования для вычисления хэша?
Комментарии:
1. Это один из случаев, когда я хотел бы иметь возможность принять два ответа…
Ответ №1:
Вот так:
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 объясняется тем, что это шестнадцатеричное представление необработанного значения (16). Или измените выше, чтобы вывести необработанную версию и сохранить необработанную в необработанном столбце (используется меньше места, но вы будете выполнять будущие преобразования rawtohex и hextoraw, поверьте мне).
Приветствия
Комментарии:
1. Отлично! Я, наконец, использовал вариант этого. Самое главное, это, наконец, помогло мне разобраться, как работают внутренние компоненты.
MD5(INPUT_STRING => CADENA)
Я использовал на самом деле возвращает строку, но она содержит0x5F4D...
байты, а не буквальное"5F4D"
представление. Таким образом, мы прибегаем кRAW
в качестве промежуточного формата, чтобы мы могли использоватьRAWTOHEX()
. (Принудительное автоматическое преобразование из RAW в VARCHAR, похоже, также работает.)2. каким будет сценарий, когда мы захотим передать как
CLOB
вместоVARCHAR2
Ответ №2:
Особенностью 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>
Конечно, мы можем определить параметр процедуры, используя ПОДТИП, но 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 символа.
Однако это собьет с толку разработчиков, которые будут просматривать объявление подтипа. В худшем случае эти люди будут использовать подтип для объявления своих собственных рабочих переменных со следующим трагическим результатом:
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>
Таким образом, лучше не использовать неподходящий подтип. Вместо этого объявите свой собственный.