朋友們,我們平時寫SQL腳本時,絕大部分情況下都是一板一眼的。某些情況下,我們可能需要一些隨機性數據。比如我們要寫一個抽獎程序,需要隨機返回某一個號碼,這時就可以使用SQL中的隨機函數來實現了。
SQL Server中有一個數學函數RAND,她可以返回一個介于0 到1(不包括0和1)之間的偽隨機float值。我們先看看RAND函數的語法結構:
RAND ( [ seed ] )
非常簡單,包含一個可選參數seed,該參數可為RAND函數預設種子, 對于指定的種子值,返回的結果始終相同。如果沒有設置種子值,則系統會自動隨機為RAND函數指定一個種子值。為了返回的數據夠隨機,我們一般不使用該參數。
為了驗證RAND函數的返回值確實夠隨機,我們先做一個小測試,使用while循環返回10個隨機數,腳本如下:
declare @i int=1; while @i<=10 begin print RAND(); set @i+=1; end;
運行效果如下:
可見隨機數確實夠隨機,我們就可以放心使用了。下面就以抽獎需求為例,比如存在從1001~1500的500個號碼,我們如何用SQL腳本實現抽獎過程呢?
因RAND返回值是0~1且不含0和1的浮點數,如果我們將RAND的返回值乘上1500會有什么效果呢?這就是簡單的數學概念了,這個隨機數的范圍就變成了0~1500、且不含0和1500的浮點數了。
為了將浮點數轉為整數,我們可以使用round,也可以使用floor和ceiling函數。因我們也要給1500這個邊界值撞到的機會,所以我們最好使用ceiling函數,該函數返回大于等于浮點數的最小整數值。
我們想要的是1001~1500之間的隨機整數,返回值更可能是1~1000的整數,為了過濾掉無效部分,我們需要使用while循環觸碰1001~1500這個范圍。
腳本如下:
declare @begno int=1001; declare @endno int=1500; declare @result int=0; while 1=1 begin set @result=ceiling(rand()*@endno); if @result>=@begno and @result<=@endno begin print @result; break; end; end;
怎么樣,是不是很簡單?下面我們看看運行效果:
為了增加腳本的重用性,我們可以把上述腳本改造成自定義函數,腳本如下:
--創建視圖 create view getrand as select rand() as rand; --創建自定義函數 create function choujiang ( @begno int=1001, @endno int=1500 ) returns int as begin declare @result int=0; while 1=1 begin select @result=ceiling([rand]*@endno) from getrand; if @result>=@begno and @result<=@endno begin break; end; end; return @result; end;
眼尖的朋友會看到,在創建自定義函數時,我們先創建了一個簡單的視圖,這是因為在自定函數中,是無法直接調用諸如RAND這類沒有確定值的系統函數的。除了RAND函數,諸如GETDATE等系統函數在自定義函數中也都是無法直接使用的,創建視圖是最簡單的解決方法。
下面我們調用多次該函數看看返回值,腳本如下:
declare @i int=1; while @i<=20 begin print dbo.choujiang(1001,1500); set @i+=1; end;
下面我們看看運行效果:
怎么樣,一個簡單的抽獎程序用SQL腳本就這樣簡單實現了,有意思吧!