http://5dblog.me
在查询中使用函数
函数经常和查询表达式结合使用来修改列值。这只需将列名作为参数传递给函数即可,随后函数将引用插入到SELECT查询的列的列表中,如下所示:
SELECT Title, NationalIDNumber, YEAR(BirthDate) AS BirthYear FROM HumanResources.Employee 在这个例子中,BirthDate列的值被作为参数传递给YEAR()函数。函数的结果是别名为BirthYear的列。 嵌套函数
我们需要的功能常常不能仅由一个函数来实现。根据设计,函数应尽量简单,用于提供特定的功能。如果一个函数要执行许多不同的操作,就变得复杂和难以使用。因此,每个函数通常仅执行一个操作,要实现所有的功能,可以将一个函数的返回值传递给另一个函数,这称为嵌套函数调用。
以下是一个简单的例子:GETDATE()函数的作用是返回当前的日期与时间,但不能返回经过格式化的数据,因为这是CONVERT()函数的功能。要想同时使用这两个函数,可以把GETDATE()函数的输出作为CONVERT()函数的输入参数。
SELECT CONVERT(Varchar(20), GETDATE(), 101) 聚合函数
报表的典型用途是从全部数据中提取出代表一种趋势的值或者汇总值,这就是聚合的意义。聚合函数回答数据使用者的如下问题:
上个月鸡雏的总销售量是多少?
19~24岁之间的巴西男性在食品调味品上的平均支出是多少? 上季度所有订单中从订购到运输的最长时间是多少? 收发室里仍在工作的最老的员工是谁?
聚合函数应用特定的聚合操作并返回一个标量值(单一值)。返回的数据类型对应于该列或者传递到函数中的值。聚合经常和分组、累积以及透视等表运算一起使用,生成数据分析结果。第7章将详细介绍这个主题,这里仅讨论简单SELECT查询中的一些常用函数。
聚合函数不仅可用在SELECT查询中,还可以和标量输入值一起使用。那么,这样做的意义是什么呢?在下列代码中,将值15传递给下列聚合函数,每个函数的返回值都相同:
SELECT AVG(15) SELECT SUM(15) SELECT MIN(15) SELECT MAX(15) 它们都返回15。虽然,对同一个值求平均、求和、求最小值、求最大值,所得的结果还是那个值。如果对一个值计数,又会产生什么结果呢?
SELECT COUNT(15)
得到的值是1,因为函数只计数了一个值。
现在做一些有意义的事。聚合函数只有在处理结果集合中的一组数据时才有意义。每个函数都处理某列的非空值。除非使用分组操作(详见第7章),否则不能在同一个SELECT语句中既返回聚合的值,又返回常规的列值。 AVG()函数
http://5dblog.me
AVG()函数用于返回一组数值中所有非空数值的平均值。例如,表6-2包含了体操成绩。 表 6-2 体操运动员 Sara Cassie Delaney Sammi Erika Sara Cassie Delaney Sammi Erika 对这些数据执行以下查询: SELECT AVG(Score) 结果是8.965。
如果有三个女孩没有完成一些项目,在表中没有记录成绩,则可用NULL来表示(见表6-3)。 表 6-3 体操运动员 Sara Cassie Delaney Sammi Erika Sara Cassie Delaney Sammi Erika 脚本:
项 目 跳马 跳马 跳马 跳马 跳马 平衡木 平衡木 平衡木 平衡木 平衡木 成 绩 9.25 8.75 NULL 8.05 8.60 9.70 NULL 9.25 NULL 8.85 项 目 跳马 跳马 跳马 跳马 跳马 平衡木 平衡木 平衡木 平衡木 平衡木 成 绩 9.25 8.75 9.25 8.05 8.60 9.70 9.00 9.25 8.95 8.85 create table #GymEvent(Player varchar(10),[Subject] nvarchar(5),Score decimal(4,2)) http://5dblog.me
go insert into #GymEvent values('Sara','跳马',9.25) insert into #GymEvent values('Cassie','跳马',8.75) insert into #GymEvent values('Delaney','跳马',NULL) insert into #GymEvent values('Sammi','跳马',8.05) insert into #GymEvent values('Erika','跳马',8.60) insert into #GymEvent values('Sara','平衡木',9.70) insert into #GymEvent values('Cassie','平衡木',NULL) insert into #GymEvent values('Delaney','平衡木',9.25) insert into #GymEvent values('Sammi','平衡木',NULL) insert into #GymEvent values('Erika','平衡木',8.85) go drop table #GymEvent 在这种情况下,计算平均值时只考虑实际的数值,NULL不参与运算,结果是8.921429。 但是,如果把缺少的成绩也算在内,即用数值0代替NULL,则会严重影响最终成绩(6.245),她们能不能进入国家级的比赛就难说了。 COUNT()函数
COUNT()函数用于返回一个列内所有非空值的个数,这是一个整型值。比如,在上一个例子中,体操数据被保存在#GymEvent表中,要确定Sammi参加的项目数,则可以执行下列查询:
SELECT COUNT(Score) FROM #GymEvent WHERE Player='Sammi' 结果是1,因为Sammi只参加了跳马比赛,她的平衡木成绩是NULL。 如果需要确定表中的行数,无论这些行是不是NULL值,都可以使用以下语法:
SELECT COUNT (*) FROM #GymEvent
以Sammi为例,COUNT(*)查询如下所示:
SELECT COUNT(*) FROM #GymEvent WHERE Player='Sammi'
由于COUNT(*)函数会忽略NULL值,所以这个查询的结果是2。 MIN()与MAX()函数
MIN()函数用于返回一个列范围内的最小非空值;MAX()函数用于返回最大值。这两个函数可以用于大多数的数据类型,返回的值根据对不同数据类型的排序规则而定。为了说明这两个函数,假设有一个表包含了两列值,一列是整型值,另一列是字符型值,如表6-4所示。
表 6-4
IntegerColumn(int类型) 2 4 12 19 2 4 12 19 VarCharColumn(varChar类型) http://5dblog.me
脚本:
create table #Temp(IntegerColumn int,VarCharColumn varchar(10)) go insert into #Temp values(2,'2') insert into #Temp values(4,'4') insert into #Temp values(12,'12') insert into #Temp values(19,'19') go drop table #Temp 如果分别调用MIN()与MAX()函数将会返回什么值呢?
select MIN(IntegerColumn),MAX(IntegerColumn) from #Temp select MIN(VarCharColumn),MAX(VarCharColumn) from #Temp
因为VarCharColumn中值的存储类型为字符类型,而不是数字,所以结果以每个字符的ASCII值为顺序从左到右排序。这就是12比其他值小、而4比其他值大的原因。 SUM()函数
SUM()函数是最常用的聚合函数之一,它的功能很容易理解:和AVG()函数一样,它用于数值数据类型,返回一个列范围内所有非空值的总和。
配置变量
配置变量不是函数,不过它们的用法和系统函数相同。每个全局变量都能够返回SQL Server执行环境的标量信息。以下是一些常见的例子。 @@ERROR变量
这个变量包含当前连接发生的最后一次错误的代码。在执行的语句没有错误时,@@ERROR变量的值是0。出现标准错误时,错误是由数据库引擎引发的。所有的标准错误代码与消息都保存在sys.messages系统视图中,可以使用如下脚本查询:
SELECT * FROM sys.messages
定制错误可以通过调用RAISERROR语句来手动引发,并调用sp_addmessage系统存储过程将其添加到sysmessages表中。
以下是一个@@ERROR变量的简单例子。先试着将一个数除以0,数据库引擎会引发标准错误号为8134的错误。注意查看Results选项卡中的查询结果。在发生错误时,Management Studio的Messages选项卡将默认显示在Results选项卡的上面:
SELECT 5 / 0 http://5dblog.me
SELECT @@ERROR 在成功检索@@ERROR的值后,@@ERROR的值将返回0,因为@@ERROR只保存了上次执行的语句的错误代码。如果希望检索更多的错误信息,可以使用如下脚本从sysmessages视图中得到:
SELECT 5 / 0 SELECT * FROM master.dbo.sysmessages WHERE error = @@ERROR 本节的后面部分内容将说明如何通过使用错误函数来更高效地返回错误数据。
除了美国英语之外,SQL Server还默认安装了其他语言。每种语言专用的错误消息都有一个语言标识符(mslangid),对应于syslanguages表中的一种语言,如下图所示。 error 8134 8134 8134 8134 8134 8134 8134 severity 16 16 16 16 16 16 16 0 0 0 0 0 0 0 dlevel description Divide by zero error encountered. Fehler aufgrund einer Division durch Null. Division par zéro. 0 除算エラーが発生しました。 Error de división entre cero. Errore di divisione per zero. Обнаружена ошибка: деление на ноль. 8134 8134 8134 8134 16 16 16 16 0 0 0 0 Erro de divis?o por zero. 發現除以零的錯誤。 0?? ??? ??? ??????. 遇到以零作除数错误。 1046 1028 1042 2052 msglangid 1033 1031 1036 1041 3082 1040 1049 属性名mslangid被非正式地定义为Microsoft Global Language Identifier。微软公司用这个标识符来标识一种语言或语言和国家的组合,微软公司把语言和国家的组合定义为地区。例如,在随SQL Server安装的英语中,美国英语的mslangid是1033,英国英语的mslangid是2057。要检索出所有已安装的、支持的语言,可以执行下面的查询:
SELECT alias, name, msglangid FROM sys.syslanguages @@SERVICENAME变量
这个变量是用于执行和维护当前SQL Server实例的Windows服务名。它通常返回SQL Server默认实例
MSSQLSERVER,但SQL Server的指定实例有唯一的服务名。例如在名为WoodVista的计算机上有两个SQL Server实例:默认实例和指定实例AughtEight。如在默认实例上检索@@SERVICENAME全局变量的内容,将返回MSSQLSERVER,但在指定实例上检索,会返回AUGHTEIGHT。 @@TOTAL_ERRORS变量