现在的位置: 首页 > 数据库 > 正文

SQL–多的是,你不知道的事

2020年05月05日 数据库 ⁄ 共 2582字 ⁄ 字号 评论关闭

本文不是SQL教程,只是关于T-SQL的一点小结及吐槽。
对于SQL入门的学习,推荐一本32开大小的小巧书目《SQL Server编程必知必会》,对于每个知识点介绍得很简单但很到位,如果你不想阅读那些动辄四五百页的大作的话,这本书完全够用。另外一本进阶的书目 《The Art of SQL》很出名,那是我打算看的但还没有看。
这里讨论和所有例子都基于微软对SQL的一个实现版本T-SQL。表是基于manage sutio自带的Northwind数据库。
对于初学者来说,只知道SQL不知道T-SQL,T-SQL是什么,感觉像方言。对头,它就是个方言。
SQL 的全称是结构化查询语言Structured Query Language,专门设计来与数据进行通信,就好比HTML被设计来展示网页。它不是一种专利语言,不属于哪个公司,好比你无法说出HTML是微软的, 还是IBM的。有专门的标准委员会来制定SQL语言的标准及对它进行维护。而我们真正使用的,是各个数据库管理软件对它的一个实现。就是说SQL是标准, 其他人在遵守这一标准的前提下给出自己的一个实现版本。微软的数据库产品所实现的版本就叫Transact-SQL,简称T-SQL,Oracle的是 PL/SQL等。当然,各个DBMS版本间会新增自己的一些特性,这也是为什么Oracle下写的SQL脚本可能在SQL Server上不兼容的原因,但大部分语句都是可以在各平台移植的。

SQL中的随机

SQL中,大部分查询都是通过SELECT语句返回,最熟悉的莫过于从一张表中进行查询返回结果,但其实还有一些返回是可以通过启用函数的,比如GETDATE()。
GETDATE()方法返回当前系统时间,准确说是你的数据库服务器的时间。如果有人问程序员What’s the time? 那我想《程序员装逼指南》(如果有这本书的话)会告诉你,程序员才不会带表或者看手机呢,他会优雅地输入SELECT GETDATE();

只是在单独使用诸如GETDATE(),RAND()等函数时表忘了加上SELECT .
上面提到RAND()方法,它默认生成的是0到1且后面拖了一长串精度的浮点数。同时它也可以接收一个种子值,如果指定了种子值,居然每次产生的随机数都是一样的!真的是坑爹的随机函数.

但 其实很多时候我们需要让这个产生的随机数更符合我们的需要一点,比如只想要一个0到10之间的随机数,这时候可以联想到CEILING()和 FLOOR()这两个函数,前者返回大于等于给定参数的最小整数,后者相反,返回小于等于给定参数的最大整数。有点绕口,比如CEILING(0.3), 那么比0.3大的整数就是1,2,3….最小的是1,返回1.  而FLOOR(1.5)呢,对头,返回1.
接着上面的思路,要返回0到10之间的一个随机数,我们需要做的就是把RAND()返回的数先乘以10,这样返回的就是几点几的一个数,再用CEILING()或者FLOOR()就可以只取到一个整数部分的数字。

用CEILING()还是FLOOR(), 抑或两者没有区别。必需有区别,用CEILING()你永远得不到0这个数,而且FLOOR()又永远得不到10这个数。
还有种方法就是使用字符串处理函数LEFT()或者RIGHT(),将RAND()返回的数同样乘10后用LEFT()取左边一位就是我们想要的了,RIGHT()同理。

想到这里,甚至可以用SUBSTRING(),它接收三个参数,第一个是字符串,所以首先我们需要把RAND()返回的数通过CONVERT()转成字符型,第二参数是要取的子字符串的开始位置,第三个参数为子字符串长度。

除非你真的是闲的,否则没有必需用这种方法来做,这里只是提供一种思路,说明科学的道路其实很宽阔的。
至于要返回1到100,10到100随机数等的情况,相信通过各位码农的智慧也是完全可能的了,这里就不赘述鸟。
SQL主要功能不是返回数字,更多是返回表中的行。同样,也可以实现从表中返回随机抽取的数据行。
通过NEWID()这个方法用如下语句轻松实现。

NEWID()是个什么样的函数,可以实验一把来看看:

返回一串字符类似于GUID,唯一的标识。每次运行返回的都是一个不同的值。在上面的例子中,从ORDERS表中取三条数据,数据是通过NEWID()产生的值到表中取到的,当然就是随机的了。
其实,SQL SERVER有个专门从大量数据中返回随机样本的函数TABLESAMPLE(),通过参数可以指定返回多少条随机样本数据或者百分之几的数据:

但 诡异的是,居然提示语法错误。这有点让人摸不着北。后来发现,TABLESAMPLE() 是SQL SERVER 2005 新增的内容,而Northwind数据库又是2005版本以前自带的一个样本数据库,所以它只能兼容级别为80,也就是说在这个数据库上能执行2000或 更老的SQL SERVER所以支持的命令但无法执行更新的命令。像SQL SERVER 2005之后的版本中都用Adventureworks数据库代替了Northwind的。于是转到Adventureworks数据库进行尝试。

果然是兼容性的问题,那么能不能在老版本SQL SERVER中创建的数据库上执行呢,其实还是可以的,只要把数据库的兼容性改到更高即可:

需要说明的是TABLESAMPLE()每次返回的结果数目是不一样的,在给定的参数上下跳动,所以如果表本身的数据量很小的话,比如只有两三百条,使用此命令一行结果也没有返回是很正常的。

日期与时间

GETDATE()可以方便地获得时间日期,DATEPART()则会返回指定的日期的某部分,比如只想要一条完事日期信息中的月分,星期等:

但我们看到返回的星期其实不够人性化,贴心的显示应该是星期几而不是本周的第几天,这时就可以用DATENAME()了,它返回的是日期的名字。

其实更人性化一点的显示应该是这样的,如果在中国,应该返回星期一,十月!
运行Sp_helplanguage可以看到SQL SERVER中保存了各种语言对日期时间的显示设置。当然中文的习惯称呼也可以在里面找到。

再看我们数据库当前的语言环境:

当前语言环境是英语,所以返回的是英文的日期相关名称,那思路应该就是把默认语言环境改成中文。

可以看到,现在系统默认语言已经设置成了简体中文,NOW,就是见证奇迹的时刻。

抱歉!评论已关闭.