首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SqlServer Rand()问题

SqlServer Rand()问题
EN

Stack Overflow用户
提问于 2009-11-01 23:47:42
回答 4查看 5K关注 0票数 1

我正在编写一个过程,其中每次调用都需要获得一个随机数。此过程从我们的.net web服务调用。

我尝试使用rand()实现此功能。然而,当我在毫秒内多次调用存储过程时,我得到了许多冲突,因为生成的是相同的随机数。如果在随后的调用之间有大约20或30毫秒的间隔,则看起来工作正常。

看起来,SqlServer在每次调用存储过程时都会对rand()进行补种。据我所知,这是一个问题,因为人们应该对随机数生成器进行一次播种,如果每次对rand调用都重新播种,就不会得到良好的伪随机数序列。此外,在1或2毫秒内对同一sp的呼叫似乎会被植入相同的值。

下面是存储过程中的语句本身。

代码语言:javascript
运行
复制
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种子rand()是如何实现的?它是否真的是随机的,或者如果您在不同的连接上在1或2毫秒内调用sp,它是否会被播种相同的种子,从而导致冲突?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-11-02 01:03:38

如果您使用的是SQL Server2008,那么可以使用CRYPT_GEN_RANDOM()函数。这将使每一行的数据随机化,即使您试图在一次查询执行中计算数百万个随机数,并且没有任何种子问题:

代码语言:javascript
运行
复制
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

票数 9
EN

Stack Overflow用户

发布于 2009-11-02 00:00:59

在您的示例中,将rand()*10000替换为ABS(CHECKSUM(NEWID())) % 9999

但是,对于char(9):

代码语言:javascript
运行
复制
SELECT RIGHT('000000000' + CAST(ABS(CHECKSUM(NEWID()) % 999999999) AS char(9), 9)

随机播种兰德。

代码语言:javascript
运行
复制
RAND(CHECKSUM(NEWID()))

编辑:

请注意,RAND在SQL Server中的实现很糟糕。不要用它。

票数 5
EN

Stack Overflow用户

发布于 2009-11-02 00:01:22

RAND() function有一个可选的种子参数,您可以为此使用该参数。如果将上一次生成的随机值作为种子传递给下一次调用rand(),则可以保证获得一个新的随机数。

感谢gbn指出种子是一个整数,而rand()返回一个浮点数。有了这些知识,下面是一个有效的示例!首先创建一个表:

代码语言:javascript
运行
复制
create table RandomNumber (number float)
insert into RandomNumber values (rand())

然后抓取一个随机数并将新数存储在事务中:

代码语言:javascript
运行
复制
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的答案,似乎容易多了。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1657474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档