【问题标题】:Oracle STANDARD_HASH not available in PLSQL?Oracle STANDARD_HASH 在 PLSQL 中不可用?
【发布时间】:2025-12-02 17:10:02
【问题描述】:

我正在尝试在 PL/SQL 中使用 STANDARD_HASH Oracle (12c) 函数,但似乎不可用:

SQL> exec   dbms_output.put_line(STANDARD_HASH('test'));
BEGIN dbms_output.put_line(STANDARD_HASH('test')); END;

                           *
ERROR at line 1:
ORA-06550: line 1, column 28:
PLS-00201: identifier 'STANDARD_HASH' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

来自 sql 的工作正常:

SQL> select STANDARD_HASH('test') from dual;

STANDARD_HASH('TEST')
----------------------------------------
A94A8FE5CCB19BA61C4C0873D391E987982FBBD3

为什么?在 PLSQL 中实现 STANDARD_HASH 的最佳方式是什么?

问候

【问题讨论】:

  • 并非所有 SQL 函数都在 PL/SQL 中可用;不是on this list,但也许应该是。可能与 LNNVL 属于同一类别。
  • 这是比使用自定义包装函数更正确的答案,这是对*的重新发明。绝对必须将这个变体标记为正确答案。

标签: oracle hash plsql


【解决方案1】:

似乎它还不是12c 中 PL/SQL 的一部分。

作为一种解决方法,在 PL/SQL 中使用 SELECT INTO

SQL> set serveroutput on
SQL> DECLARE
  2    str VARCHAR2(40);
  3  BEGIN
  4    SELECT STANDARD_HASH('test') INTO str FROM dual;
  5    dbms_output.put_line(str);
  6  END;
  7  /
A94A8FE5CCB19BA61C4C0873D391E987982FBBD3

PL/SQL procedure successfully completed.

SQL>

我建议创建一个函数,并在 PL/SQL 中需要时使用它。

例如,

SQL> CREATE OR REPLACE FUNCTION STANDARD_HASH_OUTPUT(str IN VARCHAR2)
  2    RETURN VARCHAR2
  3  AS
  4    op VARCHAR2(40);
  5  BEGIN
  6    SELECT STANDARD_HASH(str) INTO op FROM dual;
  7    RETURN op;
  8  END;
  9  /

Function created.

直接在PL/SQL块中调用函数

SQL> BEGIN
  2     dbms_output.put_line(STANDARD_HASH_OUTPUT('test'));
  3  END;
  4  /
A94A8FE5CCB19BA61C4C0873D391E987982FBBD3

PL/SQL procedure successfully completed.

SQL>

【讨论】:

  • 感谢拉利特!似乎我将实现此方法,因为 dbms_crypto.hash 函数似乎要慢得多(平均 43%)。我更喜欢避免从双重(个人意见)中选择,但在这种情况下,我会选择这个解决方案。
  • 19c 还是一样
【解决方案2】:

对于文本,STANDARD_HASH 与带有 SHA1 的 DBMS_CRYPTO.HASH 相同:

begin
  dbms_output.put_line(dbms_crypto.hash(cast('test' as clob), dbms_crypto.hash_sh1));
end;
/

输出:

A94A8FE5CCB19BA61C4C0873D391E987982FBBD3

对于其他数据类型,没有记录它们是如何传递给哈希函数的。

【讨论】:

  • 感谢科多!由于某种原因,这种方法比使用 STANDARD_HASH 函数从对偶中选择要慢(因为强制转换为 clob?)。我很惊讶!
  • 这确实很有趣。我本来预计 SELECT 会更慢,因为它涉及上下文切换。但衡量总比假设好。感谢您的更新。
【解决方案3】:

标准散列允许您指定散列算法。算法有 SHA1、SHA256、SHA384、SHA512 和 MD5。如果省略此参数,则使用 SHA1。

要获得比 sys_guid 提供的更熟悉的 GUID:

LOWER (CAST (standard_hash (SYS_GUID (), 'MD5') AS VARCHAR2 (40)))

我已经测试了 2050 万条记录,没有发生冲突...

【讨论】:

  • 另一个好处是这个方法使用了所有的内置函数并且可以用于一列DEFAULT。由于您不能在 DEFAULT 值中使用用户定义的函数、过程和包,因此我一直在寻找一种方法来坚持使用内置函数将 SYS_GUID 变形为更具视觉可区分性的格式。