工作中会遇到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代码如下:
SELECT CHECKSUM(NEWID()) AS CheckSumValue, CHECKSUM(NEWID()) AS CheckSumValue2;
GO
执行后的查询结果如下:
 
    从上面的查询结果看到组合生成的整数数值都是9位数的,平时工作中大多使用的随机整数值都是不太大的且都是自然数(0和正整数的集合),这就要求限制随机生成的整数数值。可以使用函数ABS对其结果进行处理得到任意一个自然数。这样,组合一起来的格式就是这样的:ABS(CHECKSUM(NEWID()))。为了便于使用便于使用我们通过将其封装到函数中,但是函数NEWID又不能在函数中使用,那我们就要考虑其他的方式:将函数NEWID封装在单列单行的视图中。其定义视图的T-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 RandomGuid
FROM dbo.vRandomGuid;
GO

执行后的查询结果如下:

        
生成整数区间内的任意一个随机整数
    
    上面的视图定义,我们继续讲解组合函数的进一步封装。我们先讲解如何限制随机生成的数值,取模运算可以实现生成在指定数值区间内的任意一个数值,例如:获取区间[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代码如下:
  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(, );
--==================================
CREATE FUNCTION dbo.ufn_RandNum
(
@intMin INT, -- 随机数值的最小值
@intMax INT -- 随机数值的最大值
) RETURNS INT
--$Encode$--
AS
BEGIN
SET @intMin = ISNULL(@intMin, );
SET @intMax = ISNULL(@intMax, ); DECLARE @guidValue AS UNIQUEIDENTIFIER; SELECT TOP @guidValue = RandomGuid
FROM dbo.vRandomGuid; RETURN ABS(CHECKSUM(@guidValue)) % (@intMax - @intMin + ) + @intMin;
END
GO
调用以上函数的T-SQL代码如下:
 SELECT dbo.ufn_RandNum(, ) AS RandNum, dbo.ufn_RandNum(, ) AS RandNum2;
GO
执行后的查询结果如下:
 
生成日期区间内的任意一个随机日期
 
    那么我们继续讲解 获取指定区间内的任意一个随机日期,不过我们要使用日期和时间的两个函数:DATEADD和DATEDIFF。使用DATEDIFF计算出日期区间的间隔值,同上的思路我们计算得到的一个随机整数值,然后通过DATEADD得到我们期望的一个随机日期。封装函数的T-SQL代码如下:
 IF OBJECT_ID(N'dbo.ufn_RandDate', 'FN') IS NOT NULL
BEGIN
DROP FUNCTION dbo.ufn_RandDate;
END
GO --==================================
-- 功能: 获取日期区间内的任意一个随机日期
-- 说明: 具体实现阐述
-- 作者: XXX
-- 创建: yyyy-MM-dd
-- 修改: yyyy-MM-dd XXX 修改内容描述
-- 调用: SELECT @dtmRand = dbo.ufn_RandDate('2007-02-01', '2007-03-01');
--==================================
CREATE FUNCTION dbo.ufn_RandDate
(
@dtmMin DATETIME, -- 随机日期的最小值
@dtmMax DATETIME -- 随机日期的最大值
) RETURNS DATETIME
--$Encode$--
AS
BEGIN
SET @dtmMin = ISNULL(@dtmMin, '2000-01-01');
SET @dtmMax = ISNULL(@dtmMax, '2000-01-01');
DECLARE @guidVue AS UNIQUEIDENTIFIER; SELECT TOP @guidVue = RandomGuid
FROM dbo.vRandomGuid; -- 可以将HOUR换为DAYS
RETURN DATEADD(HOUR, (ABS(CHECKSUM(@guidVue)) % ( + DATEDIFF(HOUR, @dtmMax, @dtmMin))), @dtmMin);
END
GO
调用以上函数的T-SQL代码如下:
 SELECT dbo.ufn_RandDate('2015-12-01', '2015-12-21') AS RandDate, dbo.ufn_RandDate('2016-12-01', '2016-12-21') AS RandDate2;
GO

执行后的查询结果如下:

 
区间随机数获取的扩展思考
    
    无论是获取数值区间内的随机数值,还是日期区间内的随机日期,我们都使用了视图vRandomGuid。如果有一个连续的数值序列,我们通过查询这个数值序列,结合我们的区间数值和随机排序,也可以实现以上的效果。
    假设该数值序列为SeqDataTable(Num INT),数值区间[@intMin,@intMax],那么该数值区间任意一个随机数值的T-SQL代码如下:
 SELECT TOP  Num
FROM dbo.SeqDataTable
WHERE Num BETWEEN @intMin AND @intMax
ORDER BY NEWID() ASC;
GO

当然也可以利用以上的数字序列SeqDataTable(Num INT),日期区间[@dtmMin,@dtmMax],那个该数字区间任意一个随机日期的T-SQL代码如下:

 SELECT TOP  DATEADD(DAY, Num, @dtmMin)
FROM dbo.SeqDataTable
WHERE Num BETWEEN AND DATEDIFF(DAY, @dtmMin, @dtmMax)
ORDER BY NEWID() ASC;
GO

注意:以上代码无法执行成功的,也算是伪代码的。 

    以后会针对数字序列有专门的详细讲解,这儿暂时作为一个扩展思考吧。
 
补充数字辅助表
  获取指定范围的任意一个数字的T-SQL代码如下:
 SELECT TOP  Num
FROM dbo.ufn_GetNums(@bintMin, @bintMax)
ORDER BY NEWID() ASC;
GO SELECT TOP Num
FROM dbo.ufn_GetNums(, )
ORDER BY NEWID() ASC;
GO

获取指定范围的任意一个日期的T-SQL代码如下:

 SELECT TOP  DATEADD(DAY, Num, @dtmMin)
FROM dbo.ufn_GetNums(, DATEDIFF(DAY, @dtmMax, @dtmMin))
ORDER BY NEWID() ASC;
GO SELECT TOP DATEADD(DAY, Num, '2015-12-01')
FROM dbo.ufn_GetNums(, DATEDIFF(DAY, '2015-12-01', '2015-12-05'))
ORDER BY NEWID() ASC;
GO

以上代码中的表函数ufn_GetNums可以参看这篇博文SQL Server数字辅助表的实现

 

SQL Server中的RAND函数的介绍和区间随机数值函数的实现的更多相关文章

  1. ylb:SQL Server中的时间函数

    ylbtech-SQL Server:SQL Server-SQL Server中的时间函数 SQL Server中的时间函数. 1,SQL Server中的时间函数 返回顶部 1.   当前系统日期 ...

  2. SQL Server中的DATEPART函数的使用

    下面文章来自:http://blog.csdn.net/hello_world_wusu/article/details/4632049 定义和用法 DATEPART() 函数用于返回日期/时间的单独 ...

  3. SQL Server中建立自定义函数

    在SQL Server中用户可以自定义函数,像内置函数一样返回标量值,也可以将结果集用表格变量返回.用户自定义函数的2种类型:1.标量函数:返回一个标量值:2.表格值函数{内联表格值函数.多表格值函数 ...

  4. SQL Server中追踪器Trace的介绍和简单使用

    一.What is Trace? 对于SQL Profiler这个工具相信大家都不是很陌生,没用过的朋友可以在SQL Server Management Studio>工具>SQL Ser ...

  5. SQL Server中存储过程与函数的区别

    本质上没区别.只是函数有如:只能返回一个变量的限制.而存储过程可以返回多个.而函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程不行.执行的本质都一样. 函数限制比较多,比如不能用临 ...

  6. SQL SERVER 中的 object_id()函数

    在SQLServer数据库中,如果查询数据库中是否存在指定名称的索引或者外键约束等,经常会用到object_id('name','type')方法,做笔记如下: ? 语法:object_id('obj ...

  7. SQL Server中使用表值函数

    函数有很多限制,不能使用动态语句,不能使用临时表等等...细看一下,直接写语句就行了,不用动态语句 insert into @re select id,parid,@I from videoclass ...

  8. SQL Server中,with as使用介绍

    一.WITH AS的含义      WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到.有的时候 ...

  9. sql server中的开窗函数over、视图、事物

    一.开窗函数over的作用有两个: 1.排序order by,row_number,翻页 2.划区partition by,结合聚合函数针对某部分数据进行汇总 翻页的sql server 语句: an ...

随机推荐

  1. 轻量级权限管理系统(renren-security)

    renren-security是一个轻量级权限管理系统,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.使用renren-security搭建项目,只需编写30%左右代码,其余的代码交给系统自动生 ...

  2. Spring中的事务

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...

  3. 两个与spring事务相关的问题

    有些spring相关的知识点之前一直没有仔细研究:比如spring的事务,并不是没有使用,也曾经简单的在某些需要事务处理的方法上通过增加事务注解来实现事务功能,仅仅是跟随使用(甚至并未测试过事务的正确 ...

  4. 很实用的baguetteBox.js 图片弹出层

    lightbox JS插件--baguetteBox.js,它是用纯Javascript创建的图像展示效果,拥有图像放大缩小并带有相应的CSS3过度,并能在触摸屏等设备上完美展示. baguetteB ...

  5. 分享22款响应式的 jQuery 图片滑块插件

    响应式(Responsive)设计的目标是要让产品界面能够响应用户的行为,根据不同终端设备自动调整尺寸,带给用户良好的使用体验.这篇文章收集了22款优秀的响应式 jQuery 幻灯片插件,它们能够帮助 ...

  6. button与input[type=”button”]的区别

    button与input[type="button"]的区别 特别感谢 @守护晴天 ,指出了博客中不细致不严谨的地方,也让我学到了更多,更多是觉得抱歉,由于自己的不细致可能误导了一 ...

  7. ubuntu环境变量

    在Ubuntu中有如下几个文件可以设置环境变量1./etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行.2. ...

  8. Android Action Bar简介

    Android Action Bar简介 Design: Action Bar Action Bar是在屏幕顶端的一部分内容,通常在整个app进行中都保持存在. 它提供了几个关键的功能: 1.使得重要 ...

  9. ubuntu 安装 swoole 和mac 安装swoole 扩展

    ubuntu php 安装swoole 比较容易 1. 从git下载源码 2. 下载pcre http://sourceforge.net/projects/pcre/files/pcre/8.36/ ...

  10. objective-c系列-单例

    // 地球只有一个,所以声明一个地球对象就可以了,千万不能声明两个啊!同理,有时候一个类也有只能有一个对象的情况,例如服务器,只想存到一个里 // 面,这样子,下次才可以取出上次存的数据. //用全局 ...