使用mysql生成一个随机且唯一的8字符字符串

to94eoyn  于 2021-06-18  发布在  Mysql
关注(0)|答案(22)|浏览(453)

我正在做一个游戏,在某个时候涉及到车辆。我有一个名为“vehicles”的mysql表,其中包含有关车辆的数据,包括存储车辆牌照的列“plate”。
现在我遇到的问题来了。我需要找到一个未使用的车牌,然后再创建一个新的车辆-它应该是一个字母数字8字符随机字符串。我是如何做到这一点的,是使用lua中的while循环生成字符串并查询db以查看是否使用了它。然而,随着车辆数量的增加,我预计这将变得更加低效,它是现在。因此,我决定尝试使用mysql查询来解决这个问题。
我需要的查询应该只是生成一个表中还没有的8个字符的字母数字字符串。我又想到了generate&check循环方法,但我并没有把这个问题局限于此,以防有更有效的方法。我已经能够通过定义一个包含所有允许的字符的字符串并随机对其进行子串来生成字符串,仅此而已。
感谢您的帮助。

34gzjxbg

34gzjxbg16#

我不在乎碰撞的可能性。只需生成一个随机字符串并检查它是否存在。如果有,再试一次,你不需要再做几次,除非你已经分配了大量的车牌。
在纯(my)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的评论:上面的代码非常愚蠢,并且会产生连续的数字。
对于稍微不那么愚蠢的随机性,请尝试以下方法:

SELECT LEFT(MD5(RAND()), 8)

对于真正的(加密安全的)随机性,使用 RANDOM_BYTES() 而不是 RAND() (但是我会考虑将这个逻辑移到应用层)。

vpfxa7rd

vpfxa7rd17#

创建随机字符串
下面是一个mysql函数,用于创建给定长度的随机字符串。

DELIMITER $$

CREATE DEFINER=`root`@`%` FUNCTION `RandString`(length SMALLINT(3)) RETURNS varchar(100) CHARSET utf8
begin
    SET @returnStr = '';
    SET @allowedChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    SET @i = 0;

    WHILE (@i < length) DO
        SET @returnStr = CONCAT(@returnStr, substring(@allowedChars, FLOOR(RAND() * LENGTH(@allowedChars) + 1), 1));
        SET @i = @i + 1;
    END WHILE;

    RETURN @returnStr;
END

用法 SELECT RANDSTRING(8) 返回8个字符的字符串。
您可以自定义 @allowedChars .
唯一性是不能保证的-正如你在其他解决方案的评论中看到的,这是不可能的。相反,您需要生成一个字符串,检查它是否已经在使用,如果已经在使用,请重试。
检查随机字符串是否已在使用中
如果我们想将冲突检查代码保留在应用程序之外,我们可以创建一个触发器:

DELIMITER $$

CREATE TRIGGER Vehicle_beforeInsert
  BEFORE INSERT ON `Vehicle`
  FOR EACH ROW
  BEGIN
    SET @vehicleId = 1;
    WHILE (@vehicleId IS NOT NULL) DO 
      SET NEW.plate = RANDSTRING(8);
      SET @vehicleId = (SELECT id FROM `Vehicle` WHERE `plate` = NEW.plate);
    END WHILE;
  END;$$
DELIMITER ;
5cg8jx4n

5cg8jx4n18#

下面是生成随机字符串的另一种方法: SELECT SUBSTRING(MD5(RAND()) FROM 1 FOR 8) AS myrandomstring

dgjrabp2

dgjrabp219#

此函数根据输入长度和允许的字符生成随机字符串,如下所示:

SELECT str_rand(8, '23456789abcdefghijkmnpqrstuvwxyz');

功能代码:

DROP FUNCTION IF EXISTS str_rand;

DELIMITER //

CREATE FUNCTION str_rand(
    u_count INT UNSIGNED,
    v_chars TEXT
)
RETURNS TEXT
NOT DETERMINISTIC
NO SQL
SQL SECURITY INVOKER
COMMENT ''
BEGIN
    DECLARE v_retval TEXT DEFAULT '';
    DECLARE u_pos    INT UNSIGNED;
    DECLARE u        INT UNSIGNED;

    SET u = LENGTH(v_chars);
    WHILE u_count > 0
    DO
      SET u_pos = 1 + FLOOR(RAND() * u);
      SET v_retval = CONCAT(v_retval, MID(v_chars, u_pos, 1));
      SET u_count = u_count - 1;
    END WHILE;

    RETURN v_retval;
END;
//
DELIMITER ;

这段代码是基于“ross smith ii”发送的shuffle字符串函数

f87krz0w

f87krz0w20#

要创建随机的10位字母数字(不包括相像字符01ooli):

LPAD(LEFT(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TO_BASE64(UNHEX(MD5(RAND()))), "/", ""), "+", ""), "=", ""), "O", ""), "l", ""), "I", ""), "1", ""), "0", ""), "o", ""), 10), 10, 0)

这正是我创建凭证代码所需要的。在凭证代码表单中键入时,会删除易混淆的字符以减少错误。
希望这有助于某些人,基于扬乌利格的精彩回答。
请参阅jan的答案,以了解此代码的工作原理。

mmvthczy

mmvthczy21#

考虑到所需的字符总数,生成两个完全相似的车牌的可能性很小。因此,您可能不必在lua中生成数字。
你有36^8个不同的唯一数字板(282110907456,这是很多),即使你已经有一百万个数字板,你也有一个非常小的机会产生一个你已经有了,大约0.000035%
当然,这完全取决于你最终将创建多少个数字板。

xa9qqrwz

xa9qqrwz22#

我使用另一列中的数据来生成“哈希”或唯一字符串

UPDATE table_name SET column_name = Right( MD5(another_column_with_data), 8 )

相关问题