假设我有一个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
感谢任何帮助!
答案 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,其值将由序列确定。
如果你真的想让它变得无懈可击,你也可以创建一个交叉引用表来存储
的关系。如果这两种情况都不适用,你可能会把它愚蠢一点。
解决方案看起来像这样:
添加一个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();