我正在开发一款游戏,在某些时候涉及到车辆。我有一个名为" vehicles“的MySQL表,其中包含有关车辆的数据,其中包括存储车辆牌照的列”vehicles“。
现在我遇到问题的部分来了。我需要在创建新车之前找到一个未使用的车牌-它应该是一个由8个字符组成的字母数字随机字符串。我是通过在Lua中使用while循环来生成字符串并查询DB以查看是否使用了它,这是我正在编程的语言。然而,随着车辆数量的增加,我预计这将变得更加低效。因此,我决定尝试使用MySQL查询来解决这个问题。
我需要的查询应该只是生成一个8个字符的字母数字字符串,该字符串还不在表中。我再次想到了生成和检查循环的方法,但我不会将这个问题限制在这个范围内,以防有更有效的方法。我已经能够通过定义一个包含所有允许的字符的字符串来生成字符串,并随机地对其进行子化,仅此而已。
任何帮助都是非常感谢的。
发布于 2013-05-24 15:16:36
我不关心碰撞的可能性。只需生成一个随机字符串并检查它是否存在。如果是这样,再试一次,除非你已经分配了大量的车牌,否则你不需要做更多的次数。
用纯(我的)SQL生成8字符长的伪随机字符串的另一种解决方案:
SELECT LEFT(UUID(), 8);
您可以尝试执行以下操作(伪代码):
DO
SELECT LEFT(UUID(), 8) INTO @plate;
INSERT INTO plates (@plate);
WHILE there_is_a_unique_constraint_violation
-- @plate is your newly assigned plate number
由于这篇文章受到了意想不到的关注,让我强调一下ADTC's comment:上面的代码非常愚蠢,并产生了连续的数字。
对于稍微不那么愚蠢的随机性,可以试着这样做:
SELECT LEFT(MD5(RAND()), 8)
对于真正的(加密安全的)随机性,使用RANDOM_BYTES()
而不是RAND()
(但是我会考虑将此逻辑上移到应用层)。
发布于 2013-05-24 15:05:43
如何计算连续整数的MD5 (或其他)散列,然后获取前8个字符。
i.e
MD5(1) = c4ca4238a0b923820dcc509a6f75849b => c4ca4238
MD5(2) = c81e728d9d4c2f636f067f89cc14862c => c81e728d
MD5(3) = eccbc87e4b5ce2fe28308fd9f2a7baf3 => eccbc87e
等。
警告:我不知道在冲突之前你可以分配多少(但它将是一个已知的常量值)。
编辑:这是一个旧的答案,但随着时间的推移,我又看到了它,所以,从观察来看…
所有数字的概率= 2.35%
所有字母的概率= 0.05%
当MD5(82945) = "7b763dcb...“时第一次冲突(结果与MD5(25302)相同)
发布于 2013-05-24 15:07:01
以下是一种使用字母数字作为有效字符的方法:
select concat(substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1)
) as LicensePlaceNumber;
注意:不能保证唯一性。你得单独检查一下。
https://stackoverflow.com/questions/16737910
复制相似问题