【问题标题】:How to make unique random alphanumeric sequence in SQL Server如何在 SQL Server 中制作唯一的随机字母数字序列
【发布时间】:2015-06-27 02:17:46
【问题描述】:

我想将唯一的随机字母数字序列作为数据库表的主键。

序列中的每个字符都是字母 (a-z) 或数字 (0-9)

我想要的示例:

kl7jd6fgw
zjba3s0tr
a9dkfdue3

我想创建一个可以处理该任务的函数!

【问题讨论】:

  • 请添加到目前为止您尝试过的所有内容
  • 如果您的表要增长到相当大的大小,您不应该这样做。主键应该是 int/bigint 或 GUID,如果你能承受空间/性能损失的话。它们不应该是一个相当短的 VARCHAR - 查找会很昂贵,而且你会用完键。
  • 这是一个非常糟糕的主意。甚至不要考虑使用诸如主键之类的东西。使用具有标识属性的 int/bigint 列。
  • 我将提供一个缩短链接服务,这就是我需要字母数字序列的原因!

标签: sql-server


【解决方案1】:

您可以使用uniqueidentifier。这可以使用 NEWID() 函数生成:

SELECT NEWID()

将返回类似:

BE228C22-C18A-4B4A-9AD5-1232462F7BA9

【讨论】:

    【解决方案2】:

    NewID() 函数将生成唯一的数字。所以我用循环递增它们并使用 Charindex 和 Left 函数拾取字母数字字符的组合

    ;with list as 
        (
            select 1 as id,newid() as val
                 union all
            select id + 1,NEWID()
            from    list   
            where   id + 1 < 100
        ) 
        select ID,left(val, charindex('-', val) - 2) from list
        option (maxrecursion 0)
    

    【讨论】:

    • 几句话的解释会使这个例子更好。
    【解决方案3】:

    对于这个请求,NEWID() 的缺点是它将字符池限制为 0-9 和 A-F。要定义自己的角色池,您必须扮演自定义解决方案的角色。

    本方案改编自Generating random strings with T-SQL

    --Define list of characters to use in random string
    DECLARE @CharPool VARCHAR(255)
    SET @CharPool = '0123456789abcdefghijkmnopqrstuvwxyz'
    
    --Store length of CharPool for use later
    DECLARE @PoolLength TINYINT
    SET @PoolLength = LEN(@CharPool) --36
    
    --Define random string length
    DECLARE @StringLength TINYINT
    SET @StringLength = 9
    
    --Declare target parameter for random string
    DECLARE @RandomString VARCHAR(255)
    SET @RandomString = ''
    
    --Loop control variable
    DECLARE @LoopCount TINYINT
    SET @LoopCount = 0
    
    --For each char in string, choose random char from char pool
    WHILE(@LoopCount < @StringLength)
    BEGIN
        SELECT @RandomString += SUBSTRING(@Charpool, CONVERT(int, RAND() * @PoolLength), 1)
        SELECT @LoopCount += 1
    END
    
    SELECT @RandomString
    

    http://sqlfiddle.com/#!6/9eecb/4354

    但是,我必须重申,我同意其他人的观点:这是一个可怕的想法。

    【讨论】:

      【解决方案4】:

      使用随机字符串作为主键是一个非常糟糕的主意。
      它会影响性能和存储大小,并且使用具有标识属性的 int 或 bigint 会更好。

      然而,在 SQL 中生成随机字符串可能对其他事情有用,这就是我提供此解决方案的原因:

      创建一个表来保存允许的字符值。
      在我的示例中,允许的字符是 0-9 和 A-Z。

      CREATE TABLE Chars (C char(1))
      
      DECLARE @i as int = 0
      WHILE @i < 10
      BEGIN
        INSERT INTO Chars (C) VALUES (CAST(@i as Char(1)))
        SET @i = @i+1
      END
      
      SET @i = 65
      WHILE @i < 91
      BEGIN
        INSERT INTO Chars (C) VALUES (CHAR(@i))
        SET @i = @i+1
      END
      

      然后使用这个简单的选择语句从这个表中生成一个随机字符串:

      SELECT TOP 10 C AS [text()]
      FROM Chars
      ORDER BY NEWID()
      FOR XML PATH('')
      

      优点:

      • 您可以轻松控制允许的字符。
      • 新字符串的生成是一个简单的选择语句,而不是对字符串的操作。

      缺点:

      • 这个选择会产生一个丑陋的名字(即XML_F52E2B61-18A1-11d1-B105-00805F49916B)。这很容易通过将结果设置为局部变量来解决。

      • 字符在每个字符串中只会出现一次。这可以通过添加 union 轻松解决:

      示例:

      SELECT TOP 10 C AS [text()]
        FROM (
          SELECT * FROM Chars
          UNION ALL SELECT * FROM Chars
        ) InnerSelect
        ORDER BY NEWID()
        FOR XML PATH('')
      

      另一种选择是使用STUFF 函数而不是As [Text()] 来消除那些讨厌的XML 标签:

      SELECT STUFF((
       SELECT TOP 100 ''+ C 
       FROM Chars
       ORDER BY NEWID()
       FOR XML PATH('')
      ), 1, 1, '') As RandomString;
      

      这个选项没有列名难看的缺点,可以直接有别名。执行计划稍有不同,但它不应该遭受很多性能损失。

      Play with it yourself in this Sql Fiddle

      如果您认为还有其他优点/缺点,请发表评论。谢谢。

      【讨论】:

        猜你喜欢
        • 2011-02-20
        • 1970-01-01
        • 2015-07-13
        • 2017-12-29
        • 2015-10-22
        • 2015-01-14
        • 2015-07-29
        • 1970-01-01
        • 2011-08-18
        相关资源
        最近更新 更多