使用MySQL生成随机和唯一的8个字符串

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (63)

我正在做一个游戏,在某个时候涉及到车辆。我有一个名为“Vehicles”的MySQL表,其中包含了有关车辆的数据,包括“车牌”栏,其中存储了车辆的车牌。

现在我遇到麻烦了。我需要找到一个未使用的车牌之前,创建一个新的车辆-它应该是一个字母数字8字符随机字符串。我是如何实现这一目标的,我在Lua中使用了一个while循环,它是我正在编程的语言,用于生成字符串并查询DB以查看是否使用它。然而,随着车辆数目的增加,我预计这将变得更加低效---现在是这样。因此,我决定尝试使用MySQL查询来解决这个问题。

我需要的查询应该只是生成一个8字符的字母数字字符串,这个字符串还没有在表中。我再次想到了生成&检查循环方法,但我不会将这个问题限制在这个问题上,以防出现更有效的方法。我已经能够通过定义一个包含所有允许的字符的字符串来生成字符串,并随机地对它进行子串,仅此而已。

任何帮助都是非常感谢的。

提问于
用户回答回答于

这个问题包括两个非常不同的子问题:

  • 字符串必须看起来是随机的。
  • 字符串必须是唯一的。

虽然随机性是很容易实现的,但没有重试循环的唯一性却不是。这就让我们首先关注独特性。非随机唯一性可以通过AUTO_INCREMENT...。因此,使用一个保持唯一性的伪随机变换是很好的:

  • AES-加密也适用
  • 但是有一个很好的:RAND(N)

由同一种子创建的随机数序列被保证为

  • 可复制
  • 前8个迭代不同
  • 如果种子是INT 32
INSERT INTO vehicles VALUES (blah); -- leaving out the number plate
SELECT @lid:=LAST_INSERT_ID();
UPDATE vehicles SET numberplate=concat(
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@lid)*4294967296))*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed)*36+1, 1)
             )
     WHERE id=@lid;
用户回答回答于

只需生成一个随机字符串并检查它是否存在。如果是的话,再试一次,除非你已经分配了大量的车牌,否则你不需要做更多的事情。

另一种在纯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

扫码关注云+社区