【问题标题】:PostgreSQL: Is there a function that will convert a base-10 int into a base-36 string?PostgreSQL:有没有一个函数可以将 base-10 int 转换为 base-36 字符串?
【发布时间】:2011-05-13 20:12:52
【问题描述】:

PostgreSQL 中是否有一个函数可以将基数为 10 的数字(如 30)转换为基数为 36 的表示(如 u)?

【问题讨论】:

  • ints 实际上是二进制的,base 10 仅用于与人类交流..

标签: postgresql


【解决方案1】:

有 base-64 函数(例如 encode),但 base-36 没有。但你可以自己写一个或use this one

CREATE OR REPLACE FUNCTION base36_encode(IN digits bigint, IN min_width int = 0) RETURNS varchar AS $$
DECLARE
    chars char[]; 
    ret varchar; 
    val bigint; 
BEGIN
    chars := ARRAY['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
    val := digits; 
    ret := ''; 
    IF val < 0 THEN 
        val := val * -1; 
    END IF; 
    WHILE val != 0 LOOP 
        ret := chars[(val % 36)+1] || ret; 
        val := val / 36; 
    END LOOP;

    IF min_width > 0 AND char_length(ret) < min_width THEN 
        ret := lpad(ret, min_width, '0'); 
    END IF;

    RETURN ret;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

我认为您应该问问自己,数据库是否是处理此类数据格式的正确位置,但在接近堆栈的最终查看级别时,可能会更好地处理此类表示问题。

【讨论】:

  • 不幸的是,链接的博客文章已死。您碰巧没有为IN digits bytea 表示更长的数字准备好这样的算法吗? :-)
  • @LukasEder:我不确定你在问什么。你有一个bytea 列,你想在数据库中编码为base-36?
  • 如果你有一个 bytea,你想要用像 base32 这样的合理块大小来编码二进制数据的东西。 base36 将超过 31 位转换为 6 个字符,非常适合带符号的 int32_t,但对于二进制数据不太有用。 31 字节 = 48 个字符的块大小有点笨拙。
  • 你是对的,虽然我很欣赏这个解决方案,但这种东西不应该作为函数编码到数据库中
  • 您可以使用abs 函数,这样可以节省几行代码。
【解决方案2】:

这是一个可以接受任意大小数字的版本,它使用数据类型“numeric”,它是 bignum 的 postgresql 实现。

CREATE OR REPLACE FUNCTION base36_encode(IN digits numeric, IN min_width int = 0) RETURNS text AS $$
DECLARE
    chars char[] := ARRAY['0','1','2','3','4','5','6','7','8','9','A','B'
                         ,'C','D','E','F','G','H','I','J','K','L','M','N'
                         ,'O','P','Q','R','S','T','U','V','W','X','Y','Z' ] ;  
    ret text:=''; 
    val numeric:= digits; 
BEGIN
    IF digits < 0 THEN 
        val := -val;
    END IF; 

    WHILE val > 0 OR min_width > 0 LOOP 
        ret := chars[(mod(val,36))+1] || ret; 
        val := div(val,36); 
        min_width := min_width-1;
    END LOOP;
    IF digits < 0 THEN 
        ret := '-'||ret; 
    END IF; 
    RETURN ret;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

【讨论】:

    【解决方案3】:

    修改后的实现


    从其他实现修改以增加可读性。任何类型的更新修改建议都可以增加可读性。

    CREATE OR REPLACE FUNCTION fn_base36_encode(IN base10 bigint)
        RETURNS  varchar
        LANGUAGE plpgsql
    AS $BODY$
    DECLARE
        base36 varchar := '';
        intval bigint  := abs(base10);
        char0z char[]  := regexp_split_to_array('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', '');
    BEGIN
        WHILE intval != 0 LOOP
            base36 := char0z[(intval % 36)+1] || base36;
            intval := intval / 36;
        END LOOP;
    
        IF base10 = 0 THEN base36 := '0'; END IF;
        RETURN base36;
    END;
    $BODY$;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-14
      • 2015-08-09
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 2012-07-08
      相关资源
      最近更新 更多