【问题标题】:Generate Random values from SQL从 SQL 生成随机值
【发布时间】:2008-11-06 15:41:39
【问题描述】:

看起来SQL Server 和大多数其他产品一样,随机函数确实不是那么随机。所以我们有这个很好的小函数来生成一个 10 字符的值。有没有更好的方法来完成以下工作。我敢打赌。

DECLARE @SaltCount INT;
SELECT @SaltCount = COUNT(*) FROM tmp_NewLogin;
PRINT 'Set Salt values for all records' + CAST(@SaltCount AS VARCHAR(10))
DECLARE @CharPool CHAR(83);
DECLARE @Salt VARCHAR(10);
SET @CharPool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!"#$%&()*+,-./:;<=>?@';

SET NOCOUNT ON;
updateSaltValue:
    SET @Salt = ''
    SELECT @Salt = @Salt + SUBSTRING(@CharPool, number, 1) FROM
    (
    SELECT TOP 10 number FROM MASTER..[spt_values] WHERE TYPE = 'p' AND Number BETWEEN 1 AND 83
    ORDER BY NEWID()
    ) AS t

    UPDATE TOP(1) [table] SET [Salt] = @Salt WHERE [Salt] IS NULL

IF (@@ROWCOUNT > 0)
    GOTO updateSaltValue

SET NOCOUNT OFF;

PRINT 'Completed setting salts for all records';

【问题讨论】:

  • 您以什么方式发现 RAND() 函数不是随机的?您需要正确播种,但可能只是您的播种方法有问题。

标签: sql sql-server tsql


【解决方案1】:

大多数程序员都犯了重新发明随机化功能的错误,最终得到的东西根本不是随机的。我建议您坚持使用内置的 RAND() 函数。播种一次,然后根据需要获取尽可能多的值。

【讨论】:

  • 你的答案中的“once”这个词应该是大的、红色的、闪烁的。
【解决方案2】:

重塑兰德是灾难的根源。您在哪里注意到它的行为不正确?我认为你甚至不需要播种。 SQL Server 应该自己播种它就好了。当您在测试算法等时需要多次生成相同的“随机”序列时,就需要播种。

【讨论】:

    【解决方案3】:

    根据 rand() 函数的在线书籍:如果未指定种子,Microsoft SQL Server 2005 数据库引擎会随机分配一个种子值。对于指定的种子值,返回的结果始终相同。
    您可以通过快速而肮脏的技巧来避免这种情况:

    1. 像这样创建视图:

      create view [dbo].[wrapped_rand_view]
      as
      select rand( ) as random_value
      
    2. 接下来创建从视图读取的函数:

      create function [dbo].[wrapped_rand]()
      returns float
      as
      begin
      declare @f float
      set @f = (select random_value from wrapped_rand_view)
      return @f
      

    这样,您每次调用 Wrapped_rand() 函数时都会获得随机种子,并且随机值介于 0 和 1 之间。

    【讨论】:

    • 这对我来说没有意义。与直接使用 rand() 有何不同?
    • 每次调用 Wrapped_rand() 函数时都会分配新的种子值,因此您不必手动设置随机种子,而直接调用 rand() 时必须这样做。如果您每次都直接调用 rand() 而不分配新种子,您将始终获得相同的值。
    • 这与我很久以前发布的完全相同:sqlserver-tips.blogspot.com/2006/09/…
    【解决方案4】:

    使用 Rand() 函数....并使用其他随机值作为种子,例如当前 sysDate 或当前时间戳中的毫秒数...或调用 NewId() 函数...

    【讨论】:

      【解决方案5】:

      不是你所拥有的全字母随机性,而是一种随机性:

      select substring(replace(newid(),'-',''),0,10)
      

      编辑:我从 cmets 了解到 newid() 对随机性不是很好,尤其是与子字符串结合使用时。

      【讨论】:

      • newid() 一点也不随机。可能有很多结构,具体取决于所使用的算法。
      • 有意思,你知道sql server用的是什么算法吗?
      • 抱歉,我不知道具体使用的是哪种算法。但是这里有一篇很棒的文章:blogs.msdn.com/oldnewthing/archive/2008/06/27/8659071.aspx 提供了大量关于一种算法的 GUID 中大量结构的信息。
      【解决方案6】:

      有时需要使用临时密码重置密码或为新用户生成随机密码。

      以下存储过程根据配置结果的四个参数创建随机字符串。

      > create proc [dbo].uspRandChars
      >     @len int,
      >     @min tinyint = 48,
      >     @range tinyint = 74,
      >     @exclude varchar(50) = '0:;<=>?@O[]`^\/',
      >     @output varchar(50) output as 
      >     declare @char char
      >     set @output = ''
      >  
      >     while @len > 0 begin
      >        select @char = char(round(rand() * @range + @min, 0))
      >        if charindex(@char, @exclude) = 0 begin
      >            set @output += @char
      >            set @len = @len - 1
      >        end
      >     end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多