我有一个名为"hash" VARCHAR 10 UNIQUE FIELD
现在我想运行一个查询并自动生成字段内的哈希值。
问题是哈希必须是字母数字,并且必须长10个字符且不完整。
表格结构:
CREATE TABLE `vouchers` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`hash` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `hash` (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
所以我需要将哈希值插入到哈希字段中,它们应该看起来像随机的字母数字随机哈希值,我的意思是用户不应该只看一个哈希就能捕获下一个或前一个哈希,也就是说它们必须是10个字符长和独特的。
有没有人知道这个?
答案 0 :(得分:4)
-- most elegant, has adjustable length 1-32 and probably has best performance
SELECT SUBSTR(REPLACE(UUID(),'-',''),1,10) as randomStringUUID
;
-- generate 10 character [a-z0-9] string, has adjustable letter/nr ratio
SELECT CONCAT(
CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
,CASE WHEN RAND()>=0.5 THEN char(round(RAND()*9+48)) ELSE char(round(RAND()*25+97)) END
) as randomString
;
-- as bonus: generate a variable size letter only string, best for emulating names/words
SELECT SUBSTR(CONCAT(char(RAND()*25+55),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97),char(RAND()*25+97)),1,RAND()*9+4) as RandomName
进行测试
答案 1 :(得分:3)
以下是将戈登的答案包含在函数中的代码(归功于戈登) -
delimiter |
create function hash10() returns varchar(10)
begin
declare chars varchar(36);
set chars = '0123456789abcdefghijklmnopqrstuvwxyz';
return concat(substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1),
substring(chars, floor(rand()*36) + 1, 1)
);
end|
delimiter ;
然后你可以使用......
insert into x (hash) values (hash10()),(hash10()),(hash10());
答案 2 :(得分:2)
我认为最好从应用程序逻辑中处理这个问题。
如果你想以sql方式处理它,请尝试使用mysql函数UUID()(但生成的uuid长度为36个字符)
答案 3 :(得分:2)
如果要为此字段创建唯一值,可以使用自动递增方法,只需使用基数36.以下是一个最多可达数亿个不同值的示例:
update t cross join (select @i := 0, @chars = '0123456789abcdefghijklmnopqrstuvwxyz') const
set hash = concat(substring(@chars, ((@i := @i + 1) %36)+1, 1),
substring(@chars, floor(@i/pow(36, 1))%36 + 1, 1),
substring(@chars, floor(@i/pow(36, 2))%36 + 1, 1),
substring(@chars, floor(@i/pow(36, 3))%36 + 1, 1),
substring(@chars, floor(@i/pow(36, 4))%36 + 1, 1),
substring(@chars, floor(@i/pow(36, 5))%36 + 1, 1),
'0000'
);
编辑:(基于修订后的问题)
你的桌子有一个独特的约束。我只想做以下事情:
insert into vouchers(hash)
select concat(substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1),
substring(@chars, floor(rand()*36) + 1, 1)
);
在循环中(或根据需要)多次执行此操作以填充表。你不太可能得到重复。如果这样做,那个特定的插入将失败。
答案 4 :(得分:1)
只需使用循环:
DROP FUNCTION hash10;
DELIMITER |
CREATE FUNCTION hash10() RETURNS VARCHAR(10)
BEGIN
DECLARE chars VARCHAR(36);
DECLARE result VARCHAR(10);
DECLARE i INT;
SET chars = '0123456789abcdefghijklmnopqrstuvwxyz';
SET result = '';
SET i = 0;
label: LOOP
SET result = CONCAT(result, SUBSTRING(chars, FLOOR(RAND()*36) + 1, 1));
SET i = i + 1;
IF i = 10 THEN
LEAVE label;
END IF;
END LOOP label;
RETURN result;
END|
DELIMITER ;
要生成不同的长度,只需将所有10
替换为不同的数字。