在MySQL中将存储的md5字符串转换为十进制值

时间:2009-12-17 21:52:41

标签: mysql md5 type-conversion

我在MySQL中有一个非常大的表。我正在使用CHAR(32)字段,其中包含MD5作为字符串。我遇到了一个需要使用MySQL将其转换为十进制值的问题。第三方工具运行查询,因此编写代码来执行此操作实际上不是一种选择。

MySQL确实支持本机存储十六进制值并将它们转换为整数。但它会挂起来从字符串中转换它。这是我到目前为止所尝试的内容(md5_key是我的专栏名称)

首先我只是尝试了UNHEX函数,但它返回一个字符串,所以它给了我gooblygoop。我不会把它放在这里。接下来我尝试了CAST功能

SELECT CAST( CONCAT('0x',md5_key) AS UNSIGNED ) FROM bigtable limit 1

结果= 0 显示警告给我:“截断的INTEGER值不正确:'0x000002dcc38af6f209e91518db3e79d3'”

但如果我这样做:

SELECT CAST( 0x000002dcc38af6f209e91518db3e79d3 AS UNSIGNED );

我得到正确的十进制值。

所以我想我需要知道的是,有没有办法让MySQL将该字符串视为十六进制值? (我也尝试将其转换为BINARY,然后转换为UNSIGNED,但这也无效)。

提前致谢!

3 个答案:

答案 0 :(得分:5)

conv()仅限于64位整数。您可以将高和低部分转换为十进制,然后将它们一起添加:

> select cast(conv(substr("000002dcc38af6f209e91518db3e79d3", 1, 16), 16, 10) as
              decimal(65))*18446744073709551616 +
         cast(conv(substr("000002dcc38af6f209e91518db3e79d3", 17, 16), 16, 10) as
              decimal(65));
58055532535286745202684464101843

其中18446744073709551616 = 2 ^ 64。所以在你的情况下:

> select cast(conv(substr(md5_key, 1, 16), 16, 10) as 
              decimal(65))*18446744073709551616 +
         cast(conv(substr(md5_key, 17, 16), 16, 10) as
              decimal(65))
         from bigtable limit 1;

答案 1 :(得分:1)

当心MD5是16字节长,BIGINT UNSIGNED是8字节长,所以即使在你的第二种情况下你没有得到正确的答案,数字不适合你正在接收最低8字节的值= > 09e91518db3e79d3。

答案 2 :(得分:0)

我编写了一个函数来将大十六进制数转换为十进制数 (65)。

CREATE FUNCTION `hexnum_to_decimal`(hex varchar(66)) RETURNS decimal(65,0)
    DETERMINISTIC
BEGIN
    declare group1 decimal(65);
    declare group2 decimal(65);
    declare group3 decimal(65);
    declare group4 decimal(65);
    declare multiplier decimal(65);
  
    if (substr(hex, 1, 2) = "0x") then
        set hex = substr(hex, 3); -- trim 0x if exists
    end if;
    
    set hex = trim(LEADING  '0' from hex);
    
    if (length(hex) > 54) then
        return null; -- too big number
    end if;
    
    set hex = lpad(hex, 64, 0);
    
    set group1 = cast(conv(substr(hex, 49, 16), 16, 10) as decimal(65));
    set group2 = cast(conv(substr(hex, 33, 16), 16, 10) as decimal(65));
    set group3 = cast(conv(substr(hex, 17, 16), 16, 10) as decimal(65));
    set group4 = cast(conv(substr(hex,  1, 16), 16, 10) as decimal(65));
    set multiplier = 18446744073709551616; -- 2 ^ 16
    
    -- check for overflow
    if (
        (group4 > 15930919) or
        (group4 = 15930919 and group3 > 2053574980671369030) or
        (group4 = 15930919 and group3 = 2053574980671369030 and group2 > 5636613303479645705) or
        (group4 = 15930919 and group3 = 2053574980671369030 and group2 = 5636613303479645705 and group1 > 18446744073709551615)
    ) then
        return null;
    end if;
    
    return cast(
        group1 +
        group2 * multiplier +
        group3 * multiplier * multiplier +
        group4 * multiplier * multiplier * multiplier
     as decimal(65));
END

在你的情况下 000002dcc38af6f209e91518db3e79d3

select hexnum_to_decimal("000002dcc38af6f209e91518db3e79d3");
<块引用>

58055532535286745202684464101843

select hexnum_to_decimal('F316271C7FC3908A8BEF464E3945EF7A253609FFFFFFFFFFFFFFFF');
<块引用>

9999999999999999999999999999999999999999999999999999999999999999

如果传递更大的十六进制数,函数将返回空值。