GBase 8a
适配迁移
文章
精选

南大通用GBase 8a之对齐实现oracle函数ora_hash

发表于2026-04-07 17:59:11105次浏览4个评论

问题描述

oracle的函数ora_hash在gbase8a上没有与之对应的函数。在迁移、改造、调试过程中不方便。

 

改造方式

1. 可以通过创建自定义函数进行仿制(仅参考,未充分测试是否可以完全替代)

DELIMITER //
DROP FUNCTION IF EXISTS ora_hash //
CREATE FUNCTION ora_hash(
    expr TEXT,
    max_bucket BIGINT   ,   
    seed_value BIGINT       
) RETURNS BIGINT UNSIGNED
DETERMINISTIC  -- 相同输入一定返回相同结果(符合Oracle)
BEGIN
    DECLARE hash_val BIGINT UNSIGNED;
    DECLARE result_val BIGINT UNSIGNED;
    DECLARE mod_value BIGINT UNSIGNED;
    
    -- 规则1:输入为NULL,直接返回NULL
    IF expr IS NULL THEN
        RETURN NULL;
    END IF;
    
    -- 规则2:限制max_bucket在Oracle合法范围 0 ~ 4294967295
    IF max_bucket > 4294967295 THEN
        SET max_bucket = 4294967295;
    END IF;
    
    -- 规则3:计算哈希值(使用 SHA1 哈希转无符号整数,贴近Oracle行为,无负数)
    -- 拼接种子值,和Oracle种子逻辑一致
    SET hash_val = CAST(CONV(SUBSTRING(SHA1(CONCAT(expr, seed_value)), 1, 16), 16, 10) AS UNSIGNED);
    
    -- 规则4:计算模数(Oracle核心公式)
    SET mod_value = max_bucket + 1;
    
    -- 规则5:计算最终结果
    IF mod_value = 1 THEN  -- 对应 max_bucket=0,直接返回0
        SET result_val = 0;
    ELSE
        SET result_val = hash_val % mod_value;
    END IF;
    
    RETURN result_val;
END //
DELIMITER ;

2. 部分测试效果

gbase> select ora_hash('南大通用',10,0);
+-------------------------------+
| ora_hash('南大通用',10,0)     |
+-------------------------------+
|                             9 |
+-------------------------------+
1 row in set (Elapsed: 00:00:00.00)

gbase>
gbase>
gbase> select ora_hash('南大通用',10,123);
+---------------------------------+
| ora_hash('南大通用',10,123)     |
+---------------------------------+
|                               7 |
+---------------------------------+
1 row in set (Elapsed: 00:00:00.00)

gbase> select ora_hash('ndty',3,0);
+----------------------+
| ora_hash('ndty',3,0) |
+----------------------+
|                    1 |
+----------------------+
1 row in set (Elapsed: 00:00:00.00)

gbase> select ora_hash('ndty',3,999);
+------------------------+
| ora_hash('ndty',3,999) |
+------------------------+
|                      3 |
+------------------------+
1 row in set (Elapsed: 00:00:00.00)
gbase> select ora_hash('2026-04-03',20,0);
+-----------------------------+
| ora_hash('2026-04-03',20,0) |
+-----------------------------+
|                           1 |
+-----------------------------+
1 row in set (Elapsed: 00:00:00.00)

gbase> select ora_hash('2026-04-03',20,123);
+-------------------------------+
| ora_hash('2026-04-03',20,123) |
+-------------------------------+
|                            10 |
+-------------------------------+
1 row in set (Elapsed: 00:00:00.00)
gbase> select ora_hash(12345,20,0);
+----------------------+
| ora_hash(12345,20,0) |
+----------------------+
|                    3 |
+----------------------+
1 row in set (Elapsed: 00:00:00.00)

gbase> select ora_hash(12345,20,123);
+------------------------+
| ora_hash(12345,20,123) |
+------------------------+
|                     13 |
+------------------------+
1 row in set (Elapsed: 00:00:00.00)
gbase> select ora_hash(13.6,20,0);
+---------------------+
| ora_hash(13.6,20,0) |
+---------------------+
|                   8 |
+---------------------+
1 row in set (Elapsed: 00:00:00.00)

gbase> select ora_hash(13.6,20,789);
+-----------------------+
| ora_hash(13.6,20,789) |
+-----------------------+
|                    10 |
+-----------------------+
1 row in set (Elapsed: 00:00:00.00)

 

 原理说明

ORA_HASH 函数说明
(1)参数:
        ORA_HASH(expr [, max_bucket [, seed ]])
            expr:任意标量类型(字符串 / 数字等),为 NULL 则返回 NULL
            max_bucket:返回值上限,默认 4294967295,范围 0 ~ 4294967295
            seed:随机种子,默认 0,相同种子 + 相同输入 = 相同结果
(2)返回值
        范围:0 ~ max_bucket
        max_bucket=0 → 固定返回 0

 

 

 

评论

登录后才可以发表评论
用户头像
柒柒天晴发表于 3个月前
学习下
GBase用户47954发表于 3个月前
感谢作者的精彩分享!
罗小胖发表于 3个月前
学习学习
nodddddd发表于 2个月前
学习了