PostgreSQL Varchar UID到Int UID,同时保留唯一性

时间:2017-12-03 06:07:23

标签: sql postgresql postgis

假设我有一个VarChar(32)的唯一列。

离。 13bfa574e23848b68f1b7b5ff6d794e1

我希望在将列转换为int时保留其唯一性。我想我可以将所有字母转换为它们的ascii等效字符,同时保留数字和字符位置。为此,我将使用translate函数。

psuedo代码:select translate(uid, '[^0-9]', ascii('[^0-9]'))

我的问题是最初找到VarChar列中的所有字母。 我试过了

select uid, substring(uid from '[^0-9]') from test_table;

但它只返回它遇到的第一个字母。使用上面的例子,我会寻找bfaebfbbffde

感谢任何帮助!

2 个答案:

答案 0 :(得分:0)

创建一个用空格代替包机的功能,你不需要字符串,

CREATE FUNCTION replace_char(v_string VARCHAR(32) CHARSET utf8) RETURNS VARCHAR(32)
     DETERMINISTIC
 BEGIN

   DECLARE v_return_string VARCHAR(32) DEFAULT '';
   DECLARE v_remove_char VARCHAR(200) DEFAULT '1,2,3,4,5,6,7,8,9,0';
   DECLARE v_length, j INT(3) DEFAULT 0;

   SET v_length = LENGTH(v_string);

   WHILE(j < v_length) DO
    IF ( FIND_IN_SET( SUBSTR(v_string, (j+1), 1), v_remove_char ) = 0) THEN
        SET v_return_string = CONCAT(v_return_string, SUBSTR(v_string, (j+1), 1) );
    END IF;
    SET j = j+1;
   END WHILE;

   RETURN v_return_string;

END$$

DELIMITER ;

现在你只需要在查询中调用这个函数

select uid, replace_char(uid) from test_table;

它会为您提供所需的字符串(bfaebfbbffde

如果你只想要int数,即13574238486817567941然后改变变量的值,也改变十进制的列数据类型(50,0),十进制可以存储大数,并且有0小数点,所以它将存储int值为十进制。

v_remove_char  = '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';

答案 1 :(得分:0)

首先,我同意两位评论者说你应该使用UID数据类型。

除此之外......

你的UID看起来像传统的UID,因为它不是字母数字,它是十六进制的。如果是这种情况,您可以使用此解决方案将十六进制转换为数值:

PostgreSQL: convert hex string of a very large number to a NUMERIC

请注意,已接受的解决方案(我的,耻辱)不如列出的其他解决方案好,因为我的这个解决方案不适用于这个大的十六进制值。

那就是说,哎呀,这是一个多么巨大的数字。圣烟。

根据您的表中记录的数量和插入/更新的频率,我会考虑一种截然不同的方法。简而言之,我会创建另一列来存储您的数字ID,其值将由序列确定。

如果你真的想让它变得无懈可击,你也可以创建一个交叉引用表来存储

的关系。
  1. 重复使用ID(我知道UID不会,但这会涵盖错误删除记录,重新显示并且您希望保留原始ID的情况)
  2. 如果UID重复(就像这是一个每个UID有多个记录的子表),它也会覆盖这个案例
  3. 如果这两种情况都不适用,你可能会把它愚蠢一点。

    解决方案看起来像这样:

    添加一个ID列,它将是您的数字等效于UID:

    alter table test_table
    add column id bigint
    

    创建序列:

    CREATE SEQUENCE test_id
    

    创建一个交叉引用表(同样,对于这个愚蠢的版本来说不是必需的):

    create table test_id_xref (
       uid varchar(32) not null,
       id bigint not null,
       constraint test_id_xref_pk primary key (uid)
    )
    

    然后执行一次性更新,为交叉引用表和实际表的每个UID分配代理ID:

    insert into test_id_xref
    with uids as (
      select distinct uid
      from test_table
    )
    select uid, nextval ('test_id')
    from uids;
    
    update test_table tt
    set id = x.id
    from test_id_xref x
    where tt.uid = x.uid;
    

    最后,对于所有未来的插入,创建一个触发器来分配下一个值:

    CREATE OR REPLACE FUNCTION test_table_insert_trigger()
      RETURNS trigger AS
    $BODY$
    BEGIN
      select t.id
      from test_id_xref t
      into NEW.id
      where t.uid = NEW.uid;
    
      if NEW.id is null then
        NEW.id := nextval('test_id');
        insert into test_id_xref values (NEW.uid, NEW.id);
      end if;
    
      return NEW;
    END;
    $BODY$
      LANGUAGE plpgsql VOLATILE
      COST 100;
    
    CREATE TRIGGER insert_test_table_trigger
      BEFORE INSERT
      ON test_table
      FOR EACH ROW
      EXECUTE PROCEDURE test_table_insert_trigger();