1. 程式人生 > 其它 >SQL Server中如何實現區間隨機數值函式的實現?

SQL Server中如何實現區間隨機數值函式的實現?

技術標籤:常見問題資料庫資源sql資料庫

工作中會遇到SQL Server模擬資料生成以及數值列值(如整型、日期和時間資料型別)隨機填充等等任務,這些任務中都要使用到隨機數。鑑於此,本文將對SQL Server中隨機數的使用簡單做個總結。

T-SQL 隨機有關的三個函式

RAND([seed]此函式生成從0到1之間隨機float值(詳細說明檢視https://technet.microsoft.com/zh-cn/library/ms177610(v=sql.90).aspx)。

CHECKSUM ( * | expression [ ,...n ] )此函式生成按照表的某一行或一組表示式計算出來的int

校驗和值,CHECKSUM 用於生成雜湊索引(詳細說明檢視https://technet.microsoft.com/zh-cn/library/ms189788(v=sql.90).aspx)。

NEWID ( )此函式生成uniqueidentifier型別的唯一值(詳細說明檢視https://technet.microsoft.com/zh-cn/library/ms190348(v=sql.90).aspx)。

生成任意一個隨機數值(如整數、日期和時間資料型別)

如果獲得任意一個隨機整數值?函式RAND生成的結果是float資料型別的,顯然很難滿足要求,不過可以通過對函式RAND的結果繼續加工(比如其結果乘以某一個值保留整數部分等等)得到要求。很顯然,函式CHECKSUM生成的結果是int資料型別,很容易滿足我們的結果,不過其引數如果固定(表的某一行值相同或一組表示式值相同),那麼其結果也是相同的。函式NEWID可以保證結果的唯一,但是其結果是unigueidentifer資料型別的。

從以上三個函式的結果值分析:函式RNAD和CHECKSUM的結果是能獲得整數數值的。如果我們將函式NEWID的結果值作為函式CHECKSUM的引數,那麼其每次生成的結果值都是不一樣的int資料型別的數值。以下T-SQL程式碼如下:

SELECTCHECKSUM(NEWID())ASCheckSumValue,CHECKSUM(NEWID())ASCheckSumValue2;

GO

執行後的查詢結果如下:

82100-20151221152011546-1083387472.png

從上面的查詢結果看到組合生成的整數數值都是9位數的,平時工作中大多使用的隨機整數值都是不太大的且都是自然數(0和正整數的集合),這就要求限制隨機生成的整數數值。可以使用函式ABS對其結果進行處理得到任意一個自然數。這樣,組合一起來的格式就是這樣的:ABS(CHECKSUM(NEWID()))。為了便於使用便於使用我們通過將其封裝到函式中,但是函式NEWID又不能在函式中使用,那我們就要考慮其他的方式:將函式NEWID封裝在單列單行的檢視中。其定義檢視的T-SQL程式碼如下:

SQL

IF OBJECT_ID(N'dbo.vRandomGuid', 'V') IS NOT NULL
BEGIN
    DROP VIEW dbo.vRandomGuid;
END
GO

--==================================
-- 功能: 隨機Guid檢視
-- 說明: 具體實現闡述
-- 作者: XXX
-- 建立: yyyy-MM-dd
-- 修改: yyyy-MM-dd XXX 修改內容描述
--==================================
CREATE VIEW dbo.vRandomGuid
    --$Encode$--
AS
    SELECT RandomGuid = NEWID();
GO

--呼叫該檢視的T-SQL程式碼如
SELECT TOP 1 RandomGuid
FROM dbo.vRandomGuid;
GO

執行後的查詢結果如下:

82100-20151221152023827-1033869727.png

生成整數區間內的任意一個隨機整數

上面的檢視定義,我們繼續講解組合函式的進一步封裝。我們先講解如何限制隨機生成的數值,取模運算可以實現生成在指定數值區間內的任意一個數值,例如:獲取區間[3,5]內任意一個數字,我們設為區間的最小值為@intMin:3,最大值為@intMax,則該區間的間隔值為 @intMax - @intMin + 1: 5 - 3 + 1(3),那麼針對任意的整數值設為為@intValue,然後對這個間隔值先進行取模運算在加上區間最小值,最後得到的值為: @intValue % (@intMax - @intMin +1) + @intMin。如果@intValue為8,則結果值為5;如果@intValue為9,則結果值為3;如果@intValue為10,則結果值為4……

針對以上的分析我們封裝的T-SQL程式碼如下:

SQL

IF OBJECT_ID(N'dbo.ufn_RandNum', 'FN') IS NOT NULL
BEGIN
    DROP FUNCTION dbo.ufn_RandNum;
END
GO

--==================================
-- 功能: 獲取區間內的任意一個隨機數值
-- 說明: 具體實現闡述
-- 作者: XXX
-- 建立: yyyy-MM-dd
-- 修改: yyyy-MM-dd XXX 修改內容描述
-- 呼叫: SELECT dbo.ufn_RandNum(0, 1);
--==================================
CREATE FUNCTION dbo.ufn_RandNum
(
    @intMin INT,            -- 隨機數值的最小值
    @intMax INT                -- 隨機數值的最大值
) RETURNS INT
    --$Encode$--
AS
BEGIN
    SET @intMin = ISNULL(@intMin, 0);
    SET @intMax = ISNULL(@intMax, 0);

    DECLARE @guidValue AS UNIQUEIDENTIFIER;

    SELECT TOP 1 @guidValue = RandomGuid
    FROM dbo.vRandomGuid;

    RETURN ABS(CHECKSUM(@guidValue)) % (@intMax - @intMin + 1) + @intMin;
END
GO

呼叫以上函式的T-SQL程式碼如下:

SQL

 SELECT dbo.ufn_RandNum(0, 1) AS RandNum, dbo.ufn_RandNum(10, 13) AS RandNum2 from dbo.HIS_Item

執行後的查詢結果如下:

82100-20151221152039968-2106350012.png