SqlServer的RAND()问题(SqlServer Rand() question)

2019-10-18 03:20发布

我写一个程序,其中每个调用它需要获得一个随机数。 这个过程是从我们的.NET Web服务调用。

我试图实现这种使用兰特()。 然而,当我必须在几毫秒内存储过程的多个调用,我得到了很多的碰撞在产生相同随机数。 如果有后续调用之间大约20或30毫秒的空间,它似乎工作确定。

看来,兰特()补种通过SqlServer的每个存储过程调用。 据我了解,这是一个问题,因为一个人应该一次播种随机数生成器,如果一个补种每次调用兰特一个没有得到伪随机数的好序。 此外,似乎在同一SP在1个或2毫秒调用get接种相同的值。

这是在存储过程中的语句本身。

DECLARE @randomNumber char(9)

SET @randomNumber = RIGHT('00000' + CAST(CAST(rand()*100000 AS INT) AS VARCHAR(5)),5)
+ RIGHT('00000' + CAST(CAST(rand()*10000 AS INT) AS VARCHAR(4)),4)

有没有人有解决这个建议?

我将不得不写接种一次,在整个电话表保存其状态我自己的随机数发生器? SQL Server如何种子兰特()? 它是完全随机的,或者如果你调用内互相单独连接的1或2毫秒的SP将它使用相同的种子发生碰撞接种?

Answer 1:

如果您在使用SQL Server 2008,那么你可以使用CRYPT_GEN_RANDOM()函数。 这将随机数据的每一行,即使你试图计算出数以百万计的随机数在一个查询执行,并没有任何问题,播种:

SELECT CAST(RIGHT(CAST(CAST(CRYPT_GEN_RANDOM(1) AS INT) AS VARCHAR(100)), 1) AS INT)

这里的链接到BOL文章:

http://msdn.microsoft.com/en-us/library/cc627408.aspx



Answer 2:

在你的榜样,代替rand()*10000ABS(CHECKSUM(NEWID())) % 9999

然而,对于char(9):

SELECT RIGHT('000000000' + CAST(ABS(CHECKSUM(NEWID()) % 999999999) AS char(9), 9)

种子RAND 随机 ...

RAND(CHECKSUM(NEWID()))

编辑:

注意,RAND被严重在SQL Server中实现。 不要使用它。



Answer 3:

你可以使用一个表只是一个标识符字段创建独特nunbers作为种子使用方法:

declare
  @randomNumber char(9),
  @seed1 int,
  @seed2 int

insert into SeedTable () values ()
set @seed1 = scope_identity()

insert into SeedTable () values ()
set @seed2 = scope_identity()

set @randomNumber = right('00000' + 
    cast(cast(rand(@seed1) * 100000 as int) as varchar(5)), 5) +
    right('00000' + 
    cast(cast(rand(@seed2) * 10000 as int) as varchar(4)), 4)

if (@seed2 > 10000) truncate table SeedTable


Answer 4:

该RAND()函数有,你可以使用这个可选的种子参数。 如果你通过了最后生成的随机值作为种子到兰特()的下一次调用,可以保证得到一个新的随机数。

由于GBN用于指出所述种子是一个整数,而RAND()返回float。 有了这些知识,这里有一个工作的例子! 首先创建一个表:

create table RandomNumber (number float)
insert into RandomNumber values (rand())

然后抓住一个随机数,并存储在一个事务中新的电话号码:

declare @new float
begin transaction
select @new = rand(-2147483648 + 4294967295 * number)
    from RandomNumber with (updlock, holdlock)
update RandomNumber set number = @new
commit transaction
print 'Next bingo number is: ' + cast(cast(@new*100 as int) as varchar)

一个SQL Server的整数-2147483648到2147483647之间变化,并且随机数为0.0和1.0之间的浮动。 所以-2147483648 + 4294967295 * number应覆盖全部可用整数。

该交易可确保只有一次一个连接读取并存储一个新号码。 所以数字是随机的,甚至到SQL Server的不同连接。 (顺便说一句,我投GBN的回答,似乎要容易得多。)



文章来源: SqlServer Rand() question