Oracle ORA_HASH函数,结果是否为常量?[重复]

twh00eeo  于 2023-11-17  发布在  Oracle
关注(0)|答案(2)|浏览(193)

此问题在此处已有答案

Is ora_hash deterministic?(2个答案)
8天前关闭。
我们有给予一个唯一的(每个表)NUMERIC ID给我们的ERP系统中的多个表的要求,因为到第三方系统的接口需要它.这些oracle表中的键,包括Objid通常是Varchar 2.我不想在20多个表中创建一个新的列,如果它可以被阻止,所以我想知道ORA_HASH是否会做的伎俩.
我的问题是:如果我跑,例如。

Select  ora_hash(order_no || release_no || line_no)  from purchase_order_line

字符串
随着表中数据的变化,对于某个order_no,我总是得到相同的哈希值吗?||版本号||line_no combination?或者,如果表中的整体数据发生变化,哈希值在不同的时间会不同吗?如果哈希值保持不变,我可以将其限制为第三方系统所需的bigint的最大大小,并且总是为特定的组合获得相同的唯一值,对吗?我的思路有什么问题吗?如果我们切换到一个新的数据库,迁移我们所有的数据会发生什么?我强烈认为我们会得到不同的数据集,然后再组合,对吗?
表中的行数不会超过BIGINT的最大值。
我尝试了多次查询,同时从表中添加和删除数据,它总是返回相同的哈希。

Select  ora_hash(order_no || release_no || line_no)  from purchase_order_line


我还快速检查了几个包含更多数据的表,我们似乎在主键上没有冲突。

9q78igpj

9q78igpj1#

您需要向表中添加唯一的数字ID,并且您希望避免这种情况,因为您的表已经具有唯一的ID(尽管是字母数字)。您正在寻找获得确定性数字ID的方法。
根据这些ID中允许的不同字符数以及这些ID的长度,以下PL/SQL函数可能足以从字母数字ID获取数字ID。(允许的字符太多或字母数字ID太长将导致溢出异常。)

CREATE OR REPLACE FUNCTION get_unique_id(p_objid VARCHAR2) RETURN INTEGER DETERMINISTIC
IS
  PRAGMA UDF;
  v_allowed  VARCHAR2(4000) := 'ABCDEDGIJKLMNOPQRSTUVWXYZ1234567890';
  v_factor   INTEGER     := 1;
  v_result   INTEGER     := 0;
BEGIN
  FOR i IN 1 .. LENGTHC(p_objid) LOOP
    v_result := v_result + INSTRC(v_allowed, SUBSTRC(p_objid, i, 1)) * v_factor;
    v_factor := v_factor * (LENGTHC(v_allowed) + 1);
  END LOOP;
  RETURN v_result;
END get_unique_id;

字符串
这毕竟是相当简单的。你有一个字符串的允许字符,你可以用来从你的objid字符到一个数字。
假设有99个允许的字符。objid中的第一个字符将根据其在允许字符串中的位置获得从1到99的值。下一个字符将获得从1到99乘以100的值。等等。所有这些值的总和是结果的数字ID。(当然,如果你觉得这样更直观的话,你也可以从右向左遍历你的objid字符串。)
如何测试函数:

select get_unique_id('0000000000') from dual;


将'0000000000'更改为objid中允许的最大字符数和v_allowed中允许的最后一个字符的字符串。您会得到结果还是异常?结果数字是否太大或足够小以满足要求?
最后,看看ORA_HASH的文档(docs.oracle.com/../ORA_HASH.html):

ORA_HASH(expr [,max_bucket])


expr表示的数据长度没有限制
可选的max_bucket参数确定哈希函数返回的最大存储桶值。您可以指定0到4294967295之间的任何值。默认值为4294967295。
这意味着有无限数量的输入值和有限数量的结果哈希值。换句话说,不同的输入可以产生相同的输出。因此,您不能将此函数用于您的目的。对于您可以找到的所有通用哈希函数都是如此。只有当编写哈希函数来为已知的有限输入数据集生成唯一结果时,在这种情况下,你可以在一个非通用的哈希函数之上调用我的函数。
关于确定性函数的一个注解:Oracle知道明确声明确定性的确定性函数,就像我声明的那样。这些函数保证返回确定性结果,即对于相同的输入值总是相同的输出值。因此,如果ORA_HASH是确定性的,这意味着当您在Oracle版本中使用它时,无论你用相同的输入调用它,它都会可靠地产生相同的输出。不管你的Oracle版本是12 c、19 c还是21 c,都没有关系。但是,这并不能保证,Oracle从不改变算法。因此,尽管该函数在Oracle 12 c中可能是确定性的,在21 c中仍然是确定性的,但不能保证两个版本将产生相同的结果。因此,除非Oracle明确表示,该函数不能保证跨数据库版本是确定性的。

mgdq6dx1

mgdq6dx12#

ora_hash可能会导致一些冲突。最好使用standard_hash。它返回raw,但不太可能有冲突。而且,如果您对列的串联进行散列,最好执行类似standard_hash(order_no)的操作||'|'||版本号||'|'|| line_no,'MD5')。使用串联与|以避免混淆,例如“ab”||“c”给出的结果与“a”相同||“bc”。

相关问题