使用T-SQL的Rand函数生成随机数的艰苦历程
在上一篇《大量数据插入的几种方式的速度比较》里,有一列数据是用Rank函数来生产的,用来造假数据。
现在的问题是,如果要更新这一列的值,怎么办呢?也许全部删除,重新插入一遍就可以。但是太慢了。于是随手就写出了下面的代码。
Update aTable Set aColumn = @MaxInt * RAND()
结果完全出乎意料,这一列的值全是一样的!
好吧,可以要给Rand()一个种子。就随手把ID列的值传给了Rand函数。
Update aTable Set aColumn = @MaxInt * RAND(ID)
结果ID相近的Rand值也很接近,如下所示。
1 1532427136
2 1532467150
3 1532507164
4 1532547178
5 1532587192
6 1532627206
7 1532667220
8 1532707234
9 1532747248
10 1532787262
不会吧,RAND函数居然可以这么线性啊。~~~~~~~~基本上可以计算出ID=11时,Rank函数的值了。还好每次运行的结果是不一样。
那就给Rand函数传一个非线性的值喽。第一感觉就是用个异或运算,和谁异或呢?第一感觉就是和时间。
于是有了下面的代码。
Update aTable Set aColumn = Convert(int, RAND((datediff(MS,'2009-08-28 23:13:00',GETDATE())) ^ ID) * @MaxInt)
下面是运行结果。
1 1194104621
2 1194224663
3 1194184649
4 1194304691
5 1194264677
6 1194384719
7 1194344705
8 1194464748
9 1194424733
10 1194544776
还好,不是线性的了,不过这个值也还是在个小范围里转悠。
本想把Seed搞得再乱点,不过一想,如果能不用Rand函数,搞出个足够乱的Seed来,还要Rand函数干什么呢?难道把一个线性的输入变成非线性的输出不就应该是Seed函数来做的吗?
无奈之余,最后曲线救国的一招了。基本假设aColumn列已经是足够Random了。所以更新这一列,这样就可以了。
Update aTable Set aColumn = @MaxInt * RAND(aColumn)
还是可以在Insert数据时用Rand保证aColumn的随机性的。
有什么办法可以不需要给Rand传一个随机的Seed就能让Rand一定返回一个随机数吗?