【问题标题】:Best way for Unique Random String for MySQL Long tableMySQL长表的唯一随机字符串的最佳方法
【发布时间】:2010-12-11 15:21:22
【问题描述】:

我知道如何在 PHP 和 MySQL 中创建随机字符,但问题是我必须为大约 10000 行的表创建一个 4 字符的随机字符串。确保它保持独特性的最佳方法是什么?

如果需要,我可以使用更长的字符串,但不能超过 12 个。

为了简单起见,表存在我需要添加一个额外的列并用 4 字符随机字符串填充它,并且键必须保持唯一。

【问题讨论】:

  • 要求不明确 - 您是否尝试使用这个新的随机长度随机值字符串更新表,并确保它对每一行都是唯一的?听起来每个新行都必须获得一个新的随机长度随机值字符串?
  • 我是否在下面的回答中误解了您的问题?您希望每个整个字符串都是唯一的,还是希望字符串中的 4 个以上字符中的每一个都是唯一的?。
  • 我已经阅读了这个问题 4 次,但没有明确说明。它是问题和 cmets 中的片段语句的集合,它们没有紧密结合在一起以清楚地列出需要的内容。 小心不要与愿意提供帮助的人交谈,以免您的问题无人回答。

标签: mysql database random relational-database


【解决方案1】:

一个选项:

将所有可能的字符放在一个只有一列的表格中。

val
------
0
1
...
9
a
b
...
z

使用这个查询

SELECT CONCAT(a.val,b.val,c.val,d.val)
FROM chars AS a
JOIN chars AS b
JOIN chars AS c
JOIN chars AS d
ORDER BY RAND()
LIMIT 10000

另一方面,如果您需要一次获取一个 ID,我会看到两种方法。

A.如果您有很多未分配的 ID 可用。

在这种情况下,您只需生成一个 ID 并查看它是否免费。如果没有,请尝试另一个。

B.如果您希望将分配的 ID 和可用的 ID 保持在同一数量级。

在这种情况下,最好预先生成所有 ID,将它们随机排列,然后在需要时选择下一个可用的 ID。假设将它们全部放在一个表中,当您从该表中分配一个时,您将其删除,因此无法再次选择它。

如果您允许的字符是0-9a-z,这意味着表格将占据 364。这只是几 MB。

【讨论】:

  • @Alin:感谢您的回答,但问题是表格并没有像我每天都要插入数据那样停在那里。
  • 答案取决于有多少个可能的 ID 和/或您一次需要检索多少个。
  • 现在大约 10,000 个,并且每天增长 20-50 个。
  • @Omeid Herat 不,我的意思是你怎么能用这 4 个字符生成?允许的字符是什么?
  • 您拥有在答案中做出决定所需的所有信息。我会根据我对您的场景的理解为您提供个人偏好:使 ID 6 字符长,当您添加某些内容时生成 ID,直到找到一个免费的。如果您想确保在添加时只尝试一次,您可以保留一份预先生成的免费 ID 列表。并且有一个 cron 或其他东西会不时地添加到该列表中。
【解决方案2】:

由于这些字符串需要是唯一的,为什么不使用数字自动增量值,然后将其转换为基于字符的值,类似于将十进制转换为十六进制。

如果您选择例如所有字符和数字,您只需要创建一个将整数转换为“base 62”数字的例程。

【讨论】:

  • 一个好主意。唯一的问题是生成的字符串不是随机的。
  • 当我需要根据该信息检索行时,我必须正确解码它?
  • @Alin:是的,但是“随机”和“独特”在一定程度上是自相矛盾的。 @Omeid:不一定,因为您也可以使用“生成”值来检索数据。
  • 随机 对我来说似乎是真正需要解决的问题。两者都可以,但不是直截了当。请参阅我的答案以了解更多信息。
【解决方案3】:

您可以使用DISTINCT 关键字。

例如,以下查询将仅返回唯一行,您可以通过这些行验证您的 4 字符随机字符串是否保持唯一:

mysql> SELECT DISTINCT random_strings FROM chars;

【讨论】:

  • 感谢您的回答,但希望我有那里的值,我不想为每行创建长度为 4 的随机字符。
【解决方案4】:

这可能很长,但可以让您创建所需的内容:

 CREATE FUNCTION gen_alphanum () RETURNS CHAR(4)
    RETURN 
    ELT(FLOOR(1 + (RAND() * (50-1))), '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',
    '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',);
    )

【讨论】:

    【解决方案5】:

    听起来您已经在 MySQL 中获得了用于创建这些随机值字符串的代码。

    考虑这个选项:

    • 创建一个User Defined Function in MySQL。让这个函数运行 SQL 语句来生成并返回这个新的随机字符串。确保在该创建语句中使用 NOT EXISTS(SELECT MyRandomString FROM MyTable) 来检查随机字符串是否已存在于表中。

    • 插入新行时,使用此函数的返回值分配给MyRandomString 列。

    • 要更新现有数据,只需:

     UPDATE MyTable
     SET    MyRandomString = fn_CreateSomeRandomString()
    
    • 插入时:
     INSERT INTO MyTable (foo, bar, MyRandomString) 
     VALUES ('','', fn_CreateSomeRandomString());
    

    这是sample of that UDF on PasteBin

    【讨论】:

      【解决方案6】:

      如果你有 MySQL 5.6,你可以使用 TO_BASE64 如下:

      select LEFT( TO_BASE64( SHA(rand()) ), 6 ) ;
      

      或者,如果您没有 5.6,

      DELIMITER //
      
      drop function if exists randChr //
      create function randChr()
      returns char
      BEGIN
        IF RAND() <= 0.5 THEN -- Lowercase
          return CHAR( 97 + 25*rand() ) ;
        ELSE -- uc
          return CHAR( 65 + 25*rand() ) ;
        END IF;
      END //
      
      drop function if exists randString //
      create function randString( len int )
      returns varchar(255)
      BEGIN
        SET @n = 0;
        SET @res = '' ;
        REPEAT
          SET @res = concat( @res, randChr() ) ;
          set @n = @n + 1 ;
        UNTIL @n >= len END REPEAT;
        return @res ;
      END //
      
      DELIMITER ;
      
      -- USE:
      select randString( 5 );
      select randString( 60 );
      

      【讨论】:

        猜你喜欢
        • 2011-12-15
        • 1970-01-01
        • 1970-01-01
        • 2018-07-03
        • 2010-11-04
        • 2011-09-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多