SQL函数说明大全(转)qanholas

一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果。这些要求包括:执行计算与数学运算、转换数据、解析数值、组合值和聚合一个范围内的值等。

下表给出了T-SQL函数的类别和描述。

函数类别

作用

聚合函数

执行的操作是将多个值合并为一个值。例如COUNT、SUM、MIN和MAX。

配置函数

是一种标量函数,可返回有关配置设置的信息。

转换函数

将值从一种数据类型转换为另一种。

加密函数

支持加密、解密、数字签名和数字签名验证。

游标函数

返回有关游标状态的信息。

数学函数

执行三角、几何和其他数字运算。

元数据函数

返回数据库和数据库对象的属性信息。

排名函数

是一种非确定性函数,可以返回分区中每一行的排名值。

行集函数

返回可在Transact-SQL语句中表引用所在位置使用的行集。

安全函数

返回有关用户和角色的信息。

字符串函数

可更改char、varchar、nchar、nvarchar、binary和varbinary的值。

系统函数

对系统级的各种选项和对象进行操作或报告。

系统统计函数

返回有关SQLServer性能的信息。

文本和图像函数

可更改text和image的值。

函数的目标是返回一个值。大多数函数都返回一个标量值(scalarvalue),标量值代表一个数据单元或一个简单值。实际上,函数可以返回任何数据类型,包括表、游标等可返回完整的多行结果集的类型。本章不准备讨论到这个深度,第12章将讲解如何创建和使用用户自定义函数,以返回更复杂的数据。

Result=Function()

在T-SQL中,一般用SELECT语句来返回值。如果需要从查询中返回一个值,就可以把SELECT当成输出运算符,而不用使用等号:

SELECTFunction()

对于SQL函数而言,参数表示输入变量或者值的占位符。函数可以有任意个参数,有些参数是必须的,而有些参数是可选的。可选参数通常被置于以逗号隔开的参数表的末尾,以便于在函数调用中去除不需要的参数。

在SQLServer在线图书或者在线帮助系统中,函数的可选参数用方括号表示。在下列的CONVERT()函数例子中,数据类型的length和style参数是可选的:

CONVERT(data-type[(length)],expression[,style])

可将它简化为如下形式,因为现在不讨论如何使用数据类型:

CONVERT(date_type,expression[,style])

根据上面的定义,CONVERT()函数可接受2个或3个参数。因此,下列两个例子都是正确的:

SELECTCONVERT(Varchar(20),GETDATE())

SELECTCONVERT(Varchar(20),GETDATE(),101)

以下这些函数是确定性的:

lAVG()(所有的聚合函数都是确定性的)

lCAST()

lCONVERT()

lDATEADD()

lDATEDIFF()

lASCII()

lCHAR()

lSUBSTRING()

以下这些函数与变量是非确定性的:

lGETDATE()

l@@ERROR

l@@SERVICENAME

lCURSORSTATUS()

lRAND()

DECLARE@MyNumberint

SET@MyNumber=144

SELECTSQRT(@MyNumber)

结果是12,即144的平方根。

以下例子使用另一个int型的变量@MyResult,来捕获该函数的返回值。这个技术类似于过程式编程语言中的函数调用样式,即把SET语句和一个表达式结合起来,给参数赋值:

DECLARE@MyNumberint,@MyResultint

--Assignthefunctionresulttothevariable:

SET@MyResult=SQRT(@MyNumber)

--Returnthevariablevalue

SELECT@MyResult

用SELECT给变量赋值

DECLARE@MyNumber1int,@MyNumber2int,

@MyResult1int,@MyResult2int

SELECT@MyNumber1=144,@MyNumber2=121

SELECT@MyResult1=SQRT(@MyNumber1),

@MyResult2=SQRT(@MyNumber2)

SELECT@MyResult1,@MyResult2

DECLARE@RestockNamevarchar(50)

SELECTProductId

,@RestockName=Name+':'+ProductNumber

FROMProduction.Product

这个脚本会产生如下错误:

消息141,级别15,状态1,第2行

向变量赋值的SELECT语句不能与数据检索操作结合使用。

函数经常和查询表达式结合使用来修改列值。这只需将列名作为参数传递给函数即可,随后函数将引用插入到SELECT查询的列的列表中,如下所示:

SELECTTitle,NationalIDNumber,YEAR(BirthDate)ASBirthYear

FROMHumanResources.Employee

在这个例子中,BirthDate列的值被作为参数传递给YEAR()函数。函数的结果是别名为BirthYear的列。

我们需要的功能常常不能仅由一个函数来实现。根据设计,函数应尽量简单,用于提供特定的功能。如果一个函数要执行许多不同的操作,就变得复杂和难以使用。因此,每个函数通常仅执行一个操作,要实现所有的功能,可以将一个函数的返回值传递给另一个函数,这称为嵌套函数调用。

报表的典型用途是从全部数据中提取出代表一种趋势的值或者汇总值,这就是聚合的意义。聚合函数回答数据使用者的如下问题:

上个月鸡雏的总销售量是多少

19~24岁之间的巴西男性在食品调味品上的平均支出是多少

收发室里仍在工作的最老的员工是谁

聚合函数应用特定的聚合操作并返回一个标量值(单一值)。返回的数据类型对应于该列或者传递到函数中的值。聚合经常和分组、累积以及透视等表运算一起使用,生成数据分析结果。第7章将详细介绍这个主题,这里仅讨论简单SELECT查询中的一些常用函数。

聚合函数不仅可用在SELECT查询中,还可以和标量输入值一起使用。那么,这样做的意义是什么呢?在下列代码中,将值15传递给下列聚合函数,每个函数的返回值都相同:

SELECTAVG(15)

SELECTSUM(15)

SELECTMIN(15)

SELECTMAX(15)

它们都返回15。虽然,对同一个值求平均、求和、求最小值、求最大值,所得的结果还是那个值。如果对一个值计数,又会产生什么结果呢?

SELECTCOUNT(15)

得到的值是1,因为函数只计数了一个值。

现在做一些有意义的事。聚合函数只有在处理结果集合中的一组数据时才有意义。每个函数都处理某列的非空值。除非使用分组操作(详见第7章),否则不能在同一个SELECT语句中既返回聚合的值,又返回常规的列值。

AVG()函数用于返回一组数值中所有非空数值的平均值。例如,表6-2包含了体操成绩。

表6-2

体操运动员

项目

成绩

Sara

跳马

9.25

Cassie

8.75

Delaney

Sammi

8.05

Erika

8.60

平衡木

9.70

9.00

8.95

8.85

对这些数据执行以下查询:

SELECTAVG(Score)

结果是8.965。

如果有三个女孩没有完成一些项目,在表中没有记录成绩,则可用NULL来表示(见表6-3)。

表6-3

NULL

脚本:

createtable#GymEvent(Playervarchar(10),[Subject]nvarchar(5),Scoredecimal(4,2))

go

insertinto#GymEventvalues('Sara','跳马',9.25)

insertinto#GymEventvalues('Cassie','跳马',8.75)

insertinto#GymEventvalues('Delaney','跳马',NULL)

insertinto#GymEventvalues('Sammi','跳马',8.05)

insertinto#GymEventvalues('Erika','跳马',8.60)

insertinto#GymEventvalues('Sara','平衡木',9.70)

insertinto#GymEventvalues('Cassie','平衡木',NULL)

insertinto#GymEventvalues('Delaney','平衡木',9.25)

insertinto#GymEventvalues('Sammi','平衡木',NULL)

insertinto#GymEventvalues('Erika','平衡木',8.85)

droptable#GymEvent

在这种情况下,计算平均值时只考虑实际的数值,NULL不参与运算,结果是8.921429。但是,如果把缺少的成绩也算在内,即用数值0代替NULL,则会严重影响最终成绩(6.245),她们能不能进入国家级的比赛就难说了。

COUNT()函数用于返回一个列内所有非空值的个数,这是一个整型值。比如,在上一个例子中,体操数据被保存在#GymEvent表中,要确定Sammi参加的项目数,则可以执行下列查询:

SELECTCOUNT(Score)FROM#GymEventWHEREPlayer='Sammi'

结果是1,因为Sammi只参加了跳马比赛,她的平衡木成绩是NULL。

如果需要确定表中的行数,无论这些行是不是NULL值,都可以使用以下语法:

SELECTCOUNT(*)FROM#GymEvent

以Sammi为例,COUNT(*)查询如下所示:

SELECTCOUNT(*)FROM#GymEventWHEREPlayer='Sammi'

由于COUNT(*)函数会忽略NULL值,所以这个查询的结果是2。

MIN()函数用于返回一个列范围内的最小非空值;MAX()函数用于返回最大值。这两个函数可以用于大多数的数据类型,返回的值根据对不同数据类型的排序规则而定。为了说明这两个函数,假设有一个表包含了两列值,一列是整型值,另一列是字符型值,如表6-4所示。

表6-4

IntegerColumn(int类型)

VarCharColumn(varChar类型)

2

4

12

19

createtable#Temp(IntegerColumnint,VarCharColumnvarchar(10))

insertinto#Tempvalues(2,'2')

insertinto#Tempvalues(4,'4')

insertinto#Tempvalues(12,'12')

insertinto#Tempvalues(19,'19')

droptable#Temp

如果分别调用MIN()与MAX()函数将会返回什么值呢?

selectMIN(IntegerColumn),MAX(IntegerColumn)from#Temp

selectMIN(VarCharColumn),MAX(VarCharColumn)from#Temp

因为VarCharColumn中值的存储类型为字符类型,而不是数字,所以结果以每个字符的ASCII值为顺序从左到右排序。这就是12比其他值小、而4比其他值大的原因。

SUM()函数是最常用的聚合函数之一,它的功能很容易理解:和AVG()函数一样,它用于数值数据类型,返回一个列范围内所有非空值的总和。

配置变量不是函数,不过它们的用法和系统函数相同。每个全局变量都能够返回SQLServer执行环境的标量信息。以下是一些常见的例子。

这个变量包含当前连接发生的最后一次错误的代码。在执行的语句没有错误时,@@ERROR变量的值是0。出现标准错误时,错误是由数据库引擎引发的。所有的标准错误代码与消息都保存在sys.messages系统视图中,可以使用如下脚本查询:

SELECT*FROMsys.messages

定制错误可以通过调用RAISERROR语句来手动引发,并调用sp_addmessage系统存储过程将其添加到sysmessages表中。

以下是一个@@ERROR变量的简单例子。先试着将一个数除以0,数据库引擎会引发标准错误号为8134的错误。注意查看Results选项卡中的查询结果。在发生错误时,ManagementStudio的Messages选项卡将默认显示在Results选项卡的上面:

SELECT5/0

SELECT@@ERROR

在成功检索@@ERROR的值后,@@ERROR的值将返回0,因为@@ERROR只保存了上次执行的语句的错误代码。如果希望检索更多的错误信息,可以使用如下脚本从sysmessages视图中得到:

SELECT*FROMmaster.dbo.sysmessagesWHEREerror=@@ERROR

本节的后面部分内容将说明如何通过使用错误函数来更高效地返回错误数据。

除了美国英语之外,SQLServer还默认安装了其他语言。每种语言专用的错误消息都有一个语言标识符(mslangid),对应于syslanguages表中的一种语言,如下图所示。

error

severity

dlevel

description

msglangid

8134

16

0

Dividebyzeroerrorencountered.

1033

FehleraufgrundeinerDivisiondurchNull.

1031

Divisionparzéro.

1036

0除算エラーが発生しました。

1041

Errordedivisiónentrecero.

3082

Erroredidivisioneperzero.

1040

Обнаруженаошибка:делениенаноль.

1049

Errodedivisoporzero.

1046

發現除以零的錯誤。

1028

0.

1042

遇到以零作除数错误。

2052

属性名mslangid被非正式地定义为MicrosoftGlobalLanguageIdentifier。微软公司用这个标识符来标识一种语言或语言和国家的组合,微软公司把语言和国家的组合定义为地区。例如,在随SQLServer安装的英语中,美国英语的mslangid是1033,英国英语的mslangid是2057。要检索出所有已安装的、支持的语言,可以执行下面的查询:

SELECTalias,name,msglangid

FROMsys.syslanguages

这个变量是用于执行和维护当前SQLServer实例的Windows服务名。它通常返回SQLServer默认实例MSSQLSERVER,但SQLServer的指定实例有唯一的服务名。例如在名为WoodVista的计算机上有两个SQLServer实例:默认实例和指定实例AughtEight。如在默认实例上检索@@SERVICENAME全局变量的内容,将返回MSSQLSERVER,但在指定实例上检索,会返回AUGHTEIGHT。

这个变量用于记录从打开当前连接开始发生的总错误次数。和@@ERROR变量一样,它对每个用户会话是唯一的,并将在连接关闭时被重置。

这个变量记录从打开当前连接时开始计算的磁盘读取总数。DBA使用这个变量查看磁盘读取活动的情况。

这个变量包含当前SQLServer实例的完整版本信息。

SELECT@@VERSION

比如,对于运行在Windows7上的SQLServer2008开发版实例,以上脚本能够返回如下信息:

实际的版本号是一个简单的整型值,它在微软公司内部使用。而发行的产品可能有其他的商标名。在本例中,SQLServer2005的版本是9,SQLServer2008的版本是10。WindowsXPProfessional显示为WindowsNT5.l版,而Vista显示为6.0版。构建号用于内部控制,反映beta版和预览版以及正式发行后的补丁包的变化。

前面学习了如何使用@@ERROR全局变量来检索错误信息。而返回所有错误数据的更好方法是使用错误函数。这些函数返回的信息可以存储在错误跟踪表中,以供错误审核。错误函数嵌套在错误处理例程中。第11章将详细讨论错误处理,其实通过使用嵌套在TRY和ENDTRY语句中的代码块,后跟一个放在CATCH和ENDCATCH语句中的代码块就可以实现错误处理。

--Trytodosomething

BEGINTRY

ENDTRY

--Ifitcausesanerror,dothis

BEGINCATCH

PRINTERROR_MESSAGE()

ENDCATCH

所谓的错误捕获,其实就是这个意思。如果运行上面的示例,将不会出现可识别的错误,因为错误将被捕获并在CATCH语句块中进行处理。在编写错误处理代码时,SQL程序员必须把这些代码放在会引发系统错误的catch代码块中。

下列几个错误函数用于返回错误的特定信息:

函数

说明

ERROR_MESSAGE()

返回错误的描述。

ERROR_NUMBER()

返回错误号。

ERROR_SEVERITY()

返回错误的严重级别。错误的严重级别是一个从0到25的整数。

ERROR_STATE()

返回错误的状态号。错误状态是一个整数,可以唯一地表示系统错误的原因。

ERROR_LINE()

返回例程中导致出错的行号。

ERROR_PROCEDURE()

返回发生错误的存储过程名或触发器名。

下表简要描述了严重级别。

严重级别

0~10

信息性消息。不会引发系统错误

11~16

用户可以更正的错误,例如违反了外键或主键规则

17

非致命的、不重要的资源错误

18

非致命的内部错误

致命的、不重要的资源错误

20

当前进程中的致命错误

21

所有进程中的致命数据库错误

22

致命的表完整性错误

23

致命的数据库完整性错误

24

致命的硬件错误

25

致命的系统错误

下面脚本使用T-SQL的内置错误处理功能,来捕获和输出遇到除0错误时返回的错误数据。SELECT命令的结果将显示在ManagementStudio的消息选项卡中。

SELECTERROR_MESSAGE(),ERROR_NUMBER(),ERROR_SEVERITY(),

ERROR_STATE(),ERROR_LINE(),ERROR_PROCEDURE()

可以看出,执行这个脚本会在消息选项卡中返回有关错误的更多详细信息,而不仅仅是错误号本身。

ERROR_PROCEDURE()函数不能返回过程名,因为错误是在ad-hoc查询中生成的。

数据类型转换可以通过CAST()和CONVERT()函数来实现。大多数情况下,这两个函数是重叠的,它们反映了SQL语言的演化历史。这两个函数的功能相似,不过它们的语法不同。虽然并非所有类型的值都能转变为其他数据类型,但总的来说,任何可以转换的值都可以用简单的函数实现转换。

CAST()函数的参数是一个表达式,它包括用AS关键字分隔的源值和目标数据类型。以下例子用于将文本字符串'123'转换为整型:

SELECTCAST('123'ASint)

返回值是整型值123。如果试图将一个代表小数的字符串转换为整型值,又会出现什么情况呢?

SELECTCAST('123.4'ASint)

CAST()函数和CONVERT()函数都不能执行四舍五入或截断操作。由于123.4不能用int数据类型来表示,所以对这个函数调用将产生一个错误:

Server:Msg245,Level16,State1,Line1

Syntaxerrorconvertingthevarcharvalue

'123.4'toacolumnofdatatypeint.

在将varchar值'123.4'转换成数据类型int时失败。

要返回一个合法的数值,就必须使用能处理这个值的数据类型。对于这个例子,存在多个可用的数据类型。如果通过CAST()函数将这个值转换为decimal类型,需要首先定义decimal值的精度与小数位数。在本例中,精度与小数位数分别为9与2。精度是总的数字位数,包括小数点左边和右边位数的总和。而小数位数是小数点右边的位数。这表示本例能够支持的最大的整数值是9999999,而最小的小数是0.01。

SELECTCAST('123.4'ASdecimal(9,2))

decimal数据类型在结果网格中将显示有效小数位:123.40

精度和小数位数的默认值分别是18与0。如果在decimal类型中不提供这两个值,SQLServer将截断数字的小数部分,而不会产生错误。

SELECTCAST('123.4'ASdecimal)

结果是一个整数值:123

在表的数据中转换数据类型是很简单的。下面的例子使用Product表,首先执行如下查询:

SELECTProductNumber,ProductLine,ProductModelID

WHEREProductSubcategoryID<4

假定产品经理已经创建了一个系统,用于唯一地标识生产出来的每辆自行车,以便跟踪其型号、类型和类别。他决定合并产品号、产品生产线标识符、产品型号标识符和一个顺序号,为生产出来的每辆自行车创建一个唯一的序列号。在这个过程的第一步,他要求提供包括除顺序号之外的所有属性的所有可能产品的根标识符。

如果使用下面的表达式,就不能得到希望的结果,如图6-2所示。

SELECTProductNumber

+'-'

+ProductLine

+ProductModelIDASBikeSerialNum

消息245,级别16,状态1,第1行

在将nvarchar值'BK-R93R-62-R-'转换成数据类型int时失败。

我们没有得到希望的结果,而得到了有点奇怪的错误消息:请把nvarchar值转换为int。因为之前我们没有要求进行任何转换,所以这个错误很奇怪。这个查询的问题在于我们试图利用第一个连接符来连接字符值ProductNumber,利用第二个连接符连接另一个字符值ProductLine,最后连接的是ProductModelID字符值(它是一个整数)。

查询引擎会把连接符当成一个数学运算符,而不是一个字符。不管结果是什么,都需要更正这个表达式,以确保使用正确的数据类型。以下表达式执行了必要的类型转换,返回如图6-3所示的结果:

+CAST(ProductModelIDASchar(4))ASBikeSerialNum

如果把整型值转换为字符类型就不会增加多余的空格了。查询引擎将把这些值用加号和连接符组合在一起,进行字符串连接运算,而不是和前面的数值进行加法或者减法运算了。

对于简单类型转换,CONVERT()函数和CAST()函数的功能相同,只是语法不同。CAST()函数一般更容易使用,其功能也更简单。CONVERT()函数的优点是可以格式化日期和数值,它需要两个参数:第1个是目标数据类型,第2个是源数据。以下的两个例子和上一节的例子类似:

SELECTCONVERT(int,'123')

SELECTCONVERT(decimal(9,2),'123.4')

如果expression为date或time数据类型,则style可以为下表中显示的值之一。其他值作为0进行处理。SQLServer使用科威特算法来支持阿拉伯样式的日期格式。

yy(1)

yyyy

标准

输入/输出(3)

-

0或100(1,2)

默认

monddyyyyhh:miAM(或PM)

1

101

美国

mm/dd/yyyy

102

ANSI

yy.mm.dd

3

103

英国/法国

dd/mm/yyyy

104

德国

dd.mm.yy

5

105

意大利

dd-mm-yy

6

106(1)

ddmonyy

7

107(1)

mondd,yy

8

108

hh:mi:ss

9或109(1,2)

默认设置+毫秒

monddyyyyhh:mi:ss:mmmAM(或PM)

10

110

mm-dd-yy

11

111

日本

yy/mm/dd

112

ISO

yymmdd

yyyymmdd

13或113(1,2)

欧洲默认设置+毫秒

ddmonyyyyhh:mi:ss:mmm(24h)

14

114

hh:mi:ss:mmm(24h)

20或120(2)

ODBC规范

yyyy-mm-ddhh:mi:ss(24h)

21或121(2)

ODBC规范(带毫秒)

yyyy-mm-ddhh:mi:ss.mmm(24h)

126(4)

ISO8601

yyyy-mm-ddThh:mi:ss.mmm(无空格)

127(6,7)

带时区Z的ISO8601。

yyyy-mm-ddThh:mi:ss.mmmZ

(无空格)

130(1,2)

回历(5)

ddmonyyyyhh:mi:ss:mmmAM

131(2)

dd/mm/yyhh:mi:ss:mmmAM

1.这些样式值将返回不确定的结果。包括所有(yy)(不带世纪数位)样式和一部分(yyyy)(带世纪数位)样式。

2.默认值(style0或100、9或109、13或113、20或120以及21或121)始终返回世纪数位(yyyy)。

3.转换为datetime时输入;转换为字符数据时输出。

4.为用于XML而设计。对于从datetime或smalldatetime到字符数据的转换,其输出格式如上一个表所述。

5.回历是有多种变体的日历系统。SQLServer使用科威特算法。

a)默认情况下,SQLServer基于截止年份2049年来解释两位数的年份。换言之,就是将两位数的年份49解释为2049,将两位数的年份50解释为1950。许多客户端应用程序(如基于自动化对象的应用程序)都使用截止年份2030年。SQLServer提供了“两位数年份截止”配置选项,可通过此选项更改SQLServer使用的截止年份,从而对日期进行一致处理。建议您指定四位数年份。

从smalldatetime转换为字符数据时,包含秒或毫秒的样式将在这些位置上显示零。使用相应的char或varchar数据类型长度从datetime或smalldatetime值转换时,可截断不需要的日期部分。

这个函数的第三个参数是可选的,该参数用于接收格式代码整型值。表中的例子用于对DateTime数据类型进行转换。在转换SmallDateTime数据类型时,格式不变,但一些元素会显示为0,因为该数据类型不支持毫秒。以下的脚本例子将输出格式化的日期:

SELECT'DefaultDate:'+CONVERT(Varchar(50),GETDATE(),100)

DefaultDate:Apr2520051:05PM

SELECT'USDate:'+CONVERT(Varchar(50),GETDATE(),101)

USDate:04/25/2005

SELECT'ANSIDate:'+CONVERT(Varchar(50),GETDATE(),103)

ANSIDate:2005.04.25

SELECT'UK/FrenchDate:'+CONVERT(Varchar(50),GETDATE(),103)

UK/FrenchDate:25/04/2OO5

SELECT'GermanDate:'+CONVERT(Varchar(50),GETDATE(),104)

GermanDate:25.04.2005

格式代码0,1和2也可用于数字类型,它们对小数与千位分隔符格式产生影响。而不同的数据类型所受的影响是不一样的。一般来说,使用格式代码0(或者不指定这个参数的值),将返回该数据类型最惯用的格式。使用1或者2通常显示更为详细或者更精确的值。以下例子使用格式代码0:

DECLARE@NumMoney

SET@Num=1234.56

SELECTCONVERT(varchar(50),@Num,0)

返回结果如下:

1234.56

使用值1则返回如下结果:

1,234.56

使用值2则返回如下结果:

1234.5600

以下例子和上例相同,但是使用Float类型:

DECLARE@Numfloat

SELECTCONVERT(varchar(50),@Num,2)

使用值0不会改变所提供的格式,但是使用值1或2将返回以科学计数法表示的数字,后者使用了15位小数:

1.23456000000000e+003

这是一个将数字转换为字符串的快捷函数。这个函数有3个参数:数值、总长度和小数位数。如果数字的整数位数和小数位数(要加上小数点占用的一个字符)的总和小于总长度,对结果中左边的字符将用空格填充。在下面第1个例子中,包括小数点在内一共是5个字符。结果显示在网格中,显然左边的空格被填充了。这个调用指定,总长度为8个字符,小数位为4位:

SELECTSTR(123.4,8,4)

结果值的右边以0填充:123.4000。

下面给函数传递了一个10字符的值,并指定结果包含8个字符,有4个小数位:

SELECTSTR(123.456789,8,4)

只有将这个结果截断才能符合要求。STR()函数对最后一位进行四舍五入:123.4568。现在,如果为函数传递数字1,并指定结果包含6个字符,有4个小数位,STR()函数将用0补足右边的空位:

SELECTSTR(1,6,4)

1.0000

然而,如果指定的总长度大于整数位数、小数点和小数位数之和,结果值的左边将用空格补齐:

SELECTSTR(1,12,4)

----------1.0000

游标可以处理多行数据,在过程循环中一次访问一行。和基于集合的高效操作相比,这个功能对系统资源的消耗更大。可以用一个函数和两个全局变量来管理游标操作。

这个函数返回一个整型值,表示传递给这个函数的游标类型变量的状态。有很多不同类型的游标会影响这个函数的操作。为简单起见,下表列出了这个函数的常见返回值。

返回值

游标包含一行或多行(动态游标包含0行或者多行)

游标不包含行

-1

游标已关闭

-2

游标未分配

-3

游标不存在

这个变量是一个整型值,表示在当前连接中打开的游标中的行数。根据游标类型,这个值也能不代表结果集中的实际行数。

这个变量是一个标记,用于表示当前游标指针的状态。这个变量主要用来判断某行是否存在,以及在执行了FETCHNEXT语句后,是否已执行到结果集的尾部。打开游标时,@@FETCH_STATUS变量值为-1。一旦把第一个值放在游标中,@@FETCH_STATUS变量值就变成0。当不再把更多的行放在游标中时,该变量的值将变回-1。

数据类型

输出

time

12:35:29.1234567

date

2007-05-08

smalldatetime

2007-05-0812:35:00

datetime

2007-05-0812:35:29.123

datetime2

2007-05-0812:35:29.1234567

datetimeoffset

2007-05-0812:35:29.1234567+12:15

SELECTDATEADD(DAY,90,'4-29-2007')

结果:2007-07-2800:00:00.000

datepart

缩写

year

yy,yyyy

quarter

qq,q

month

mm,m

dayofyear

dy,y

day

dd,d

week

wk,ww

weekday

dw,w

hour

hh

minute

mi,n

second

ss,s

millisecond

ms

microsecond

mcs

nanosecond

ns

18年后:

SELECTDATEADD(YEAR,18,'4-29-198810:30AM')

2006-04-2910:30:00.000

18年前:

SELECTDATEADD(YY,-18,'4-29-198810:30AM')

1970-04-2910:30:00.000

9000秒后:

SELECTDATEADD(SECOND,9000,'4-29-198810:30AM')

1988-04-2913:00:00.000

9000000毫秒前:

SELECTDATEADD(MS,-9000000,'4-29-198810:30AM')

1988-04-2908:00:00.000

可以将CONVERT()函数和DATEADD()函数组合在一起,来对1989年9月8日9个月前的日期值进行格式化。

SELECTCONVERT(varchar(20),DATEADD(M,-9,'9-8-1989'),101)

12/08/1988

这将返回一个可变长度的字符值,比前面例子结果中的默认日期更易容易理解。这是一个函数嵌套调用,DATEADD()函数的返回值(一个DateTime类型的值)被作为值参数传递给CONVERT()函数。

SELECTDATEDIFF(MONTH,'9-8-1989','10-17-1991')

结果是25个月。如果以日期为单位呢

SELECTDATEDIFF(DAY,'9-8-1989','10-17-1991')

结果是769天。

1996年7月2日和1997年8月4日之间差几个星期

SELECTDATEDIFF(WEEK,'7-2-1996','8-4-1997')

57星期。甚至可以算出自己的年龄是多少秒:

DECLARE@MyBirthDatedatetime

SET@MyBirthDate='7-16-1962'

SELECTDATEDIFF(SS,@MyBirthDate,GETDATE())

结果显示有些人已经活了15亿秒了!

可以将列名作为参数,把这个函数用在查询中。首先建立一个简单的表,其中包含一些人的姓名和生日:

SELECTc.FirstName

,c.LastName

,e.BirthDate

,DATEDIFF(YEAR,e.BirthDate,GETDATE())ASApproximateAge

FROMHumanResources.Employeeaseinnerjoin

Person.Contactascone.ContactID=c.ContactID

orderbyc.LastName

下图显示了结果:

初看起来结果是对的,但存在的问题是年龄值没有精确到日。比如,根据表中的数据,Nancy的生日是12月21日,他今年将庆祝第32个生日(这个查询在2010年8月运行)。如果依据上述计算结果来确定他的年龄何时变化,就应在一月份的某天给他发生日卡片,这比实际日期提前了11个月。

,CONVERT(int,DATEDIFF(DAY,e.BirthDate,GETDATE())/365)ASAge

比较这次的结果和上一个例子的结果,看看有什么不同。

这两个函数用于返回datetime或者shortdatetime值的日期部分。DATEPART()函数返回一个整型值;DATENAME()函数返回一个包含描述性文字的字符串。比如,将日期4-29-1988传递给DATEPART()函数,如指定返回月份值,则返回数字4:

SELECTDATEPART(MONTH,'4-29-1988')

而使用相同的参数,DATENAME()函数返回04(这取决于你的机器的本地语言,如果是英文版,那么将返回April):

SELECTDATENAME(MONTH,'4-29-1988')

SELECTGETDATE()

SELECTGETUTCDATE()

执行这两个函数,都将返回未经格式化的结果,见下图:

SELECTDATEDIFF(HOUR,GETDATE(),GETUTCDATE())

这两个SQLServer2008函数等价于GETDATE()和GETUTCDATE()函数,但不是返回datetime数据类型的结果,而是返回SQLServer2008新的datetime2数据类型的结果,该数据类型可以精确到100纳秒,当然这取决于服务器安装的硬件。

SELECTSYSDATETIME()

SELECTSYSUTCDATETIME()

这三个函数分别返回以整数表示的datetime或者smalldatetime类型值的日、月、年。它们的用途很广泛,如可以创建独特的个性化日期格式。假设需要创建一个自定义的日期值作为字符串,通过将这三个函数的输出结果转换成字符类型,然后进行连接操作,就可以对输出结果以任何形式进行组合了:

SELECT'Year:'+CONVERT(varchar(4),YEAR(GETDATE()))

+',Month:'+CONVERT(varchar(2),MONTH(GETDATE()))

+',Day:'+CONVERT(varchar(2),DAY(GETDATE()))

这个脚本生成下列结果:

Year:2008,Month:2,Day:20

字符串函数可以解析、替换、操纵字符型值。在处理原始字符数据时,最大的挑战之一是如何可靠地提取出有意义的信息。有很多字符串解析函数可用于标识和解析子字符串(一个大字符型值的一部分)。我们一直在做这种事,在我们阅读文件、发票或者书面材料时,就会本能地标识、分离出有意义的信息片段。这个过程的自动化非常困难,即使是处理不太复杂的文本,也很困难。这些函数包含几乎所有必需的工具,而挑战在于如何找出最简单、最高效的方法。

这四个函数是相似的,它们都可以在字符和字符的标准数字表示之间转换。美国标准信息交换码(AmericanStandardCodeforInformationInterchange,ASCII)标准字符集包含128个字母、数字和标点符号。这个字符集是IBMPC体系结构的基础,虽然有些字符现在看来已经很古老了,但还是被保留了下来,且仍是现代计算机技术的核心。如果在计算机上使用英语,则键盘上的每个字符都是用ASCII码表示的。这对说英语(至少以英语打字)的计算机用户来说是有利的,但是其他人又该怎么办呢

ASCII()和CHAR()是两个基于ASCII的函数,这两个函数可将计算机上应用的每个字符表示为数字。要确定代表一个字符的数字是什么,就应给ASCII()函数传送只包含一个字符的字符串,如下:

SELECTASCII('A')

结果是65。

如要将一个已知数字转换为字符,又该怎么办?使用CHAR()函数即可:

SELECTCHAR(65)

结果是字母A。

要得到完整的ASCII字符值列表,可以对一个临时表填充从0到127的数字,然后调用CHAR()函数返回相应的字符。为了节省空间,我们对以下这个脚本进行了删节,但包含整个结果集,并以多栏格式给出。

--创建一个临时表来保存ASCII码:

CreateTable#ASCIIVals(ASCIIValuesmallint)

--插入数字0-127到临时表中:

declare@Numberint

set@Number=0

while(@Number<128)

begin

InsertInto#ASCIIVals(ASCIIValue)Select@Number

set@Number=@Number+1

end

--查询所有的整型数字与其对应的ASCII码:

SELECTASCIIValue,CHAR(ASCIIValue)ASCharacterFROM#ASCIIVals

droptable#ASCIIVals

表6-12是以多栏网格重新格式化的结果集。需要注意的是这里将不可印刷的控制字符以方括号表示。由于许多因素限制,如所安装的字体或语言不同,下表的显示可能会有稍许差异。

UNICODE()函数是ASCII()的Unicode等价函数,NCHAR()函数和CHAR()函数的功能相同,只不过NCHAR()是用于Unicode字符的。SQLServer的nchar与nvarchar类型能存储任何Unicode字符,可以和这两个函数一起使用。对于特别大的值,ntext类型和nvarchar(max)类型也支持Unicode字符。

要返回扩展字符编码集中的字符,可以将字符编码传递给NCHAR()函数:

SELECTNCHAR(220)

返回字母ü。

SELECTNCHAR(233)

返回带重音符号的小写e:é。

SELECTNCHAR(241)

当然,ASCII标准也支持所有的欧洲字符,所以使用CHAR()函数也可以返回这些扩展字符。如果对256~65536之间的值使用CHAR()函数,返回值就很有趣了。例如,下面的查询返回希腊字符Ω:

SELECTNCHAR(433)

下面的查询返回西里尔字母Ya(Я)。

SELECTNCHAR(1071)

CHARINDEX()是原始的SQL函数,用于寻找在一个字符串中某子字符串第一次出现的位置。如函数名所示,这个函数返回一个整型值,表示某子字符串的第一个字符在整个字符串中的位置索引。以下脚本用于在字符串Washington中寻找子字符串sh的出现位置:

SELECTCHARINDEX('sh','Washington')

返回的结果是3,表明s是字符串Washington中的第3个字符。这说明CHARINDEX函数匹配字符的索引是从1开始的。如果没有匹配到任何结果,函数将返回0。在这个例子中使用两个字符作为子字符串并没有特别意义,但是如果字符串包含多个s字符,就有意义了。

PATINDEX()函数和CHARINDEXO函数类似,它执行相同的操作,但方法稍许不同,该函数增加了对通配符(即Like运算符中使用的字符)的支持。顾名思义,它将返回一个字符模式的索引。这个函数也可以和ntext、nchar(max)和nvarchar(max)等大字符类型一起使用。注意,如果和这些大字符类型一起使用,PATINDEX()函数将返回bigint类型的值,而不是int类型的值。以下是一个例子:

SELECTPATINDEX('%M_rs%','ThestarsnearMarsarefarfromours')

注意,如果想找到一个字符串,在所比较的字符串的前后各有0个或者多个字符,则两个百分符都是必须的。下划线表明这个位置上的字符不必匹配,它可以是任意字符。

和使用相同字符串的CHARINDEX()函数作一下比较:

SELECTCHARINDEX('Mars','ThestarsnearMarsarefarfromours')

这两个函数都返回索引值16。请注意这些函数的执行过程。下一节将把这两个函数和SUBSTRING()函数组合在一起,演示如何使用界定符解析字符串。

LEN()函数用于返回一个代表字符串长度的整型值。这是一个简单、有用的函数,经常与其他函数一起使用,来应用业务规则。以下例子将月份和日期转换为字符类型,然后测试它们的长度。如果月份日期只有一个字符,就填充字符0,然后组合成一个8字符的美国格式的日期字符串(MMDDYYYY)。

DECLARE@MonthCharvarchar(2),@DayCharvarchar(2),@DateOutchar(8)

SET@MonthChar=CAST(MONTH(GETDATE())ASvarchar(2))

SET@DayChar=CAST(DAY(GETDATE())ASvarchar(2))

--Makesuremonthanddayaretwocharlong:

IFLEN(@MonthChar)=1

SET@MonthChar='0'+@MonthChar

IFLEN(@DayChar)=1

SET@DayChar='0'+@DayChar

--Builddatestring:

SET@DateOut=@MonthChar+@DayChar+CAST(YEAR(GETDATE())ASchar(4))

SELECT@DateOutASOutputDate

这个脚本将返回代表日期的8个字符:

08152010

LEFT()与RIGHT()函数是相似的,它们都返回一定长度的子字符串。这两个函数的区别是,它们返回的分别是字符串的不同部分。LEFT()函数返回字符串最左边的字符,顺序从左数到右。RIGHT()函数正好相反,它从最右边的字符开始,以从右到左的顺序返回特定数量的字符。看一看使用这两个函数返回"GeorgeWashington"这个字符串的子字符串的例子。

如果使用LEFT()函数返回一个5字符的子字符串,则函数先定位最左边的字符,向右数5个字符,然后返回这个子字符串,如下所示。

DECLARE@FullNamevarchar(25)

SET@FullName='GeorgeWashington'

SELECTLEFT(@FullName,5)

结果为:Georg

如果使用RIGHT()函数返回一个5字符的子字符串,则函数先定位最右边的字符,向左数5个字符,然后返回这个子字符串,如下所示。

SELECTRIGHT(@FullName,5)

结果为:ngton

要想返回字符串中有意义的部分,这两个函数都不是特别有用。如果想返回全名中的姓氏或者名字,该怎么办?这需要多做一点工作。如果能确定每个姓名中空格的位置,就可以使用LEFT()函数在全名中读取名字。在这种情况下,可以使用CHARINDEX()或者PATINDEX()函数来定位空格,然后使用LEFT()函数返回空格前的字符。下面是第一个用过程方法编写的例子,它将处理过程分解成以下步骤:

DECLARE@FullNamevarchar(25),@SpaceIndextinyint

--Getindexofthedelimitingspace:

SET@SpaceIndex=CHARINDEX('',@FullName)

--Returnallcharacterstotheleftofthespace:

SELECTLEFT(@FullName,@SpaceIndex-1)

结果为:George

如果不想在结果中包含空格,就需要从@SpaceIndex值中减去1,这样结果中就只有名字了。

SUBSTRING()函数能够从字符串的一个位置开始,往右数若干字符,返回一个特定长度的子字符串。和LEFT()函数不同之处是,该函数可以指定从哪个位置开始计数,这样就可以在字符串的任何位置摘取子字符串了。这个函数需要三个参数:要解析的字符串、起始位置索引、要返回的子字符串长度。如果要返回到所输入字符串尾部的所有字符,可以使用比所需长度更大的长度值。SUBSTRING()函数将返回最大可能长度的字符数,而不会将多出的长度以空格填充。

只要指定字符串最左边的字符(1)为起始索引,就可以用SUBSTRING()函数替代LEFT()函数。

继续上一节的例子。可以设置起始位置与长度,返回姓名字符串中间的值。在这个例子中,从位置4开始,返回一个6字符的子字符串"rgeWa"。

SELECTSUBSTRING(@FullName,4,6)

现在将上述各函数组合在一起,即可从名字+空格+姓氏格式的全名字符串中解析出名字和姓氏。使用先前的逻辑,通过函数嵌套来减少脚本的行数,并去掉@SpaceIndex变量。下面用SUBSTRING()函数替代LEFT()函数:

--Returnfirstname:

SELECTSUBSTRING(@FullName,1,CHARINDEX('',@FullName)-1)

类似的逻辑可以用于解析姓氏,但是必须将起始位置更改为空格后的那个字符。如果空格在第7个位置上,那么姓氏将从第8个位置开始。这就意味着起始位置是CHARINDEX()的返回结果加上1。

--Returnlastname:

SELECTSUBSTRING(@FullName,CHARINDEX('',@FullName)+1,

LEN(@FullName))

把上述步骤组合在一起,就可以运行下面的查询,从全名变量中提取出名字和姓氏:

SELECTSUBSTRING(@FullName,1,CHARINDEX('',@FullName)-1)ASFirstName,

SUBSTRING(@FullName,CHARINDEX('',@FullName)+1,LEN(@FullName))

ASLastName

传递给SUBSTRING()函数的值是空格所在位置加上1,并将该值作为起始位置,这将是姓氏的第1个字母。由于不可能总是知道名字的长度,所以将LEN()函数的结果作为子字符串长度参数传递进来,当SUBSTRING()函数到达这个位置时,就到达了字符串的末尾,这样就可以将字符串中从空格后面开始的所有字符都包含进来了。

为了举例方便,先创建并填充一个临时表:

CREATETABLE#MyNames(FullNamevarchar(50))

GO

INSERTINTO#MyNames(FullName)SELECT'FredFlintstone'

INSERTINTO#MyNames(FullName)SELECT'WilmaFlintstone'

INSERTINTO#MyNames(FullName)SELECT'BarneyRubble'

INSERTINTO#MyNames(FullName)SELECT'BettyRubble'

INSERTINTO#MyNames(FullName)SELECT'GeorgeJetson'

INSERTINTO#MyNames(FullName)SELECT'JaneJetson'

--droptable#MyNames

下面执行一个使用函数调用来解析名字和姓氏值的单行查询表达式。这里对@FullName变量的引用被表中的FullName列所替代:

SELECT

SUBSTRING(FullName,1,CHARINDEX('',FullName)-1)ASFirstName

,SUBSTRING(FullName,CHARINDEX('',FullName)+1,LEN(FullName))ASLastName

FROM#MyNames

在下图所示的结果中,显示了两个不同的列,分别是名字和姓氏。

这两个函数很容易理解,它们用于将字符串中所有字符分别都转换为小写和大写,这在比较用户输入或者存储用于比较的字符串时是非常有用的。字符串比较通常是区分大小写的,这取决于SQLServer安装时的设置。如果和其他的字符串操纵函数一起使用,就可以将字符串转换为合适的大小写,以便存储或显示。以下例子说明混合大小写的名字,假设名字中的第2个大写子字符串前只包含一个空格,但在特殊情况下也有一些名字是没有空格的。这个例子很容易通过扩展来处理包含其他类型的混合大小写名字(如以MC开头的名字,带连接号的名字等)。

DECLARE@LastNamevarchar(25),@SpaceIndextinyint

SET@LastName='mcdonald'--Testvalue

--Findspaceinname:

SET@SpaceIndex=CHARINDEX('',@LastName)

IF@SpaceIndex>0--Space:Capitalizefirst&substring

SELECTUPPER(LEFT(@LastName,1))

+LOWER(SUBSTRING(@LastName,2,@SpaceIndex-1))

+UPPER(SUBSTRING(@LastName,@SpaceIndex+1,1))

+LOWER(SUBSTRING(@LastName,@SpaceIndex+2,LEN(@LastName)))

ELSE--Nospace:Caponlyfirstchar.

+LOWER(SUBSTRING(@LastName,2,LEN(@LastName)))

这个脚本将返回MCDonald。还可以对这个例子进行扩展,以处理姓氏包含撇号的情况。在这个例子的业务规则中,空格是不考虑的。如果找到了撇号,就将后面的字符全部转为大写。请注意如果要在脚本中测试撇号,就必须输入两次撇号(''),以表明这是一个文字,而不是一对单引号。姓氏中只存储一个撇号。

DECLARE@LastNamevarchar(25),@SpaceIndextinyint,@AposIndextinyint

SET@LastName='o''malley'--Testvalue

--Findliteral'inname:

SET@AposIndex=CHARINDEX('''',@LastName)

ELSEIF@AposIndex>0--Apostrophe:Capfirst&substring

+LOWER(SUBSTRING(@LastName,2,@AposIndex-1))

+UPPER(SUBSTRING(@LastName,@AposIndex+1,1))

+LOWER(SUBSTRING(@LastName,@AposIndex+2,LEN(@LastName)))

这个脚本返回O'Malley。

这两个函数分别返回将字符串的左边和右边的空白修剪掉之后的字符串:

DECLARE@Value1char(10),@Value2char(10)

SET@Value1='One'

SET@Value2='Two'

SELECT@Value1+@Value2

SELECTCONVERT(varchar(5),LEN(@Value1+@Value2))

+'characterslong.'

SELECTRTRIM(@Value1)+RTRIM(@Value2)

SELECTCONVERT(varchar(5),LEN(RTRIM(@Value1)+RTRIM(@Value2)))

+'characterslongtrimmed.'

结果如下:

REPLACE()函数可以把字符串中的某个字符或某个子字符串替换为另一个字符或者子字符串,该函数可以用于全局查找和替换工具中。

DECLARE@Phrasevarchar(1000)

SET@Phrase='Iaintgunnausepoorgrammarwhencommentingscriptand

Iaintgunnacomplainaboutit.'

SELECTREPLACE(@Phrase,'aint','amnot')

在需要将一些字符重复填充进一个字符串时,这两个函数是非常有用的。这里也使用SUBSTRING()例子中的临时表为每个名字填满20个字符,然后将20减去各个字符串的长度,以便将正确的值传递给REPLICATE()函数:

SELECTFullName+REPLICATE('*',20-LEN(FullName))

结果是每个名字后面都填满了星号,各个名字的总长度都是20个字符:

FredFlintstorle*****

WilrnaFlintstone****

BarneyRubble*******

BettyRubble********

GeorgeJetson********

JaneJetson**********

SPACE()函数与上述函数类似,区别在于该函数使用空格进行填充。它返回一个由空格组成的字符串,空格的个数由参数定义。

SELECTFullName+SPACE(20-LEN(FullName))

如果返回"#MyNames表不存在"的错误,只需再次运行本文前面"SUBSTRING()函数"一节的CREATETABLE脚本即可。

顾名思义,这个函数用于将字符串中的字符颠倒过来。这在处理连接列表中的单个字符值时将会被用到。

SELECTREVERSE('ThestarsnearMarsarefarfromours.')

结果为:.sruomorfraferasraMraensratsehT

这个函数可将字符串中的一部分替换为另一个字符串。它本质上是将一个字符串以特定的长度插入另一个字符串中的特定位置上。这对于源值与目的值的长度不一样的字符串替换是很有用的。下列代码用于将字符串中的价格替换为109.95:

Pleasesubmityourpaymentfor99.95immediately.

价格值是从第32个字符开始的,有5个字符长。在这个位置上插入的子字符串有多长并不重要,只需要知道需要删除多少个字符就可以了。

SELECTSTUFF('Pleasesubmityourpaymentfor99.95immediately.',32,5,'109.95')

结果为:Pleasesubmityourpaymentfor109.95immediately.

这个函数和SQLServer对象名组合使用,以将结果传递给表达式。它只用于给输入的字符串加一对方括号,并返回新形成的字符串。如果参数包含保留的分隔符或者封装字符(比如引号或括号),这个函数将修改字符串,以便SQLServer能将结果字符串中的这类字符当成文本字符。如下面的例子所示,查询的结果如图6-10所示。

SELECTQUOTENAME(COLUMN_NAME)ASColumnName

FROMINFORMATION_SCHEMA.COLUMNS

下表中列出的函数用于执行多种普通与特殊的数学运算,可以执行代数、三角、统计、估算与财政运算等运算。

ABS()

返回一个数的绝对值

ACOS()

计算一个角的反余弦值,以弧度表示

ASIN()

计算一个角的反正弦值,以弧度表示

ATAN()

计算一个角的反正切值,以弧度表示

ATN2()

计算两个值的反正切,以弧度表示

CEILING()

返回大于或等于一个数的最小整数

COS()

计算一个角的正弦值,以弧度表示

COT()

计算一个角的余切值,以弧度表示

DEGREES()

将一个角从弧度转换为角度

EXP()

指数运算

FLOOR()

返回小于或等于一个数的最大整数

LOG()

计算以2为底的自然对数

LOG10()

计算以10为底的自然对数

PI()

返回以浮点数表示的圆周率

POWER()

幂运算

RADIANS()

将一个角从角度转换为弧度

RAND()

返回以随机数算法算出的一个小数,

可以接收一个可选的种子值

ROUND()

对一个小数进行四舍五入运算,

使其具备特定的精度

SIGN()

根据参数是正还是负,返回–1或者1

SIN()

SQRT()

返回一个数的平方根

SQUARE()

返回一个数的平方

TAN()

计算一个角正切的值,以弧度表示

这是一些工具函数,它们返回SQLServer配置细节、服务器与数据库设置细节的信息,包括一组用于返回不同对象的属性状态的通用以及专用函数,这些函数把对Master数据库中系统表以及用户数据库的查询封装在函数中。建议读者使用这些函数以及其他的系统函数,而不是自己创建对系统表的查询,以防今后SQLServer版本对模式进行更改。

这些函数被用于以与结果集顺序无关的特定顺序,枚举已排序的或排在前面的结果集。

ROW_NUMBER()函数根据作为参数传递给这个函数的ORDERBY子句的值,返回一个不断递增的整数值。如果ROW_NUMBER的ORDERBY的值和结果集中的顺序相匹配,返回值将是递增的,以升序排列。如果ROW_NUMBER的ORDERBY子句的值和结果集中的顺序不同,这些值将不会按顺序列出,但它们表示ROW_NUMBER函数的ORDERBY子句的顺序。如下面的例子和结果所示:

SELECTProductCategoryID

,Name

,ROW_NUMBER()OVER(ORDERBYName)ASRowNum

FROMProduction.ProductCategory

ORDERBYName

由于ROW_NUMBER()调用中的ORDERBY子句和查询结果的顺序匹配,所以对这些结果按顺序列出,如下图所示:

不过,在函数调用中使用另一个ORDERBY子句时,这些值就是无序的了。

ORDERBYProductCategoryID

这是了解如何使用ORDERBY子句对结果进行排序的有效方法。如下图所示:

这两个函数与ROW_NUMBER()函数类似,因为它们都返回一个基于ORDERBY子句的值。不过这些值不一定永远是唯一的。排列值对于所提供的ORDERBY子句中的重复结果而言也是重复的,而且唯一性是仅仅基于ORDERBY列表中的唯一值的。这些函数用不同的方法来处理重复的值。RANK()函数保留列表中行的位置序号,对于每个重复的值,该函数会跳过下面与其相邻的值,于是就可以将下一个不重复的值保留在正确的位置上。

其行为类似于短跑比赛中的并列成绩。例如刘翔与DayronRobles(古巴)在110栏的比赛中都跑出了12’92的成绩,那他们就是并列第一,而其后的一名选手将会获得第三名的成绩。

SELECTProductID

,ListPrice

,RANK()OVER(ORDERBYListPriceDESC)AS[Rank]

ORDERBY[Rank]

注意在下图的结果列表中,重复的价格值所对应的结果是相同的,而每个连接之后的值都被跳过了。比如,产品"Road-150Red,52"和"Road-150Red,56"都排在第1,而接下来的行"Mountain-100Silver,38"就排在第6了。

DENSE_RANK()函数的工作方式与RANK()函数相同,不过它不会跳过每个连接后的值,这样就不会有值被跳过了,但是在连接处排列序号位置将会丢失。

,DENSE_RANK()OVER(ORDERBYListPriceDESC)AS[Rank]

下图的结果重复了排列值,但是不会跳过列中的任何数字。

这个函数也用于对结果进行排列,并返回一个整型的排列值,但是它不会对结果以唯一的排列顺序进行枚举,而是将结果切分为有限数量的排列组。比如,一个表有10000行,使用1000为参数值调用NTILE()函数,即NTILE(1000),并将结果分成以10为单位的1000个组,每个组赋予相同的排列值。和本节讨论的其他排列函数一样,NTILE()函数也支持OVER(ORDERBY…)语法。下面的例子根据产品价格,按照从高到低的顺序把Product表分为50组产品:

,NTILE(50)OVER(ORDERBYListPriceDESC)ASGroupedProducts

ORDERBYGroupedProducts

结果为:

fn_trace_geteventinfo()

为指定的跟踪ID返回一个填充事件信息的表类型值

fn_trace_getfilterinfo()

为指定的跟踪ID返回一个填充与过滤器有关的信息的表类型值

fn_trace_getinfo()

为指定的跟踪ID返回一个填充跟踪信息的表类型值

fn_trace_getable()

为指定的跟踪ID返回一个填充文件信息的表类型值

HAS_DBACCESS()

返回一个表明当前用户是否有访问指定数据库权限的标志

IS_MEMBER()

返回一个表明当前用户是Windows组用户还是SQLServer用户的标志

IS_SRVROLEMEMBER()

返回一个表明当前用户是否是数据库服务器角色成员的标志

SUSER_SID()

SUSER_SNAME()

USER_ID()

返回指定用户名的用户ID,或者(如果参数被忽略的话)返回当前用户的用户ID

USER_NAME()

返回指定用户ID的用户名

本节讨论具有多种用途的工具函数,包括值比较、值类型测试等功能。这个类别的函数也包罗了其他函数:

APP_NAME()

COALESCE()

从以逗号分隔的表达式列表中返回第一个非空值

COLLATIONPROPERTY()

返回一个特定字符集排序规则的特定属性的值。这些属性包括CodePage、LCID、ComparisonStyle

CURRENT_TIMESTAMP()

C1UJRRENT_USER()

返回当前用户的名字。与USER_NAME()函数相同

DATALENGTH()

返回存储或处理一个值所需的字节数。对于ANSI字符串类型,这个函数返回的值与LEN()函数相同,但对于其他数据类型而言就可能不一定相同了

fn_helpcollations()

返回一个填充有由当前SQLSewer版本支持的字符集排序规则的表类型值

fn_servershareddrives()

返回一个填充有服务器共享的驱动列表的表类型值

fn_virtualfilestats()

返回一个填充有包括日志文件在内数据库文件的I/O状态的表类型值

FORMATMESSAGE()

从sysmessages表中为指定的信息代码和以逗号分隔的参数列表返回错误信息

GETANSINULL()

根据ANSLNULL_DFLT_ON与ANSLNULL_DFLT_OFF数据库设置返回数据库的可空性设置

HOST_ID()

返回当前会话的工作站ID

HOST_NAME()

返回当前会话的工作站名

IDENT_CURRENT()

返回最后一个为指定的表生成的标识(ID)值。与会话、范围无关

IDENT_INCR()

返回最后一次创建的标识(ID)列中定义的增量值

IDENT_SEED()

返回最后一次创建的标识(ID)列中定义的种子值

IDENTITY()

用在SELECT…INTO语句中,在一个列中插入自动生成的标识值

ISDATE()

返回一个表明指定的值是否可被转换为日期值的标志

ISNULL()

判断指定的值是否是空值,然后返回一个事先提供的替代值

ISNUMERIC()

返回一个表明指定的值是否可被转换为数字值的标志

NEWID()

返回一个新生成的UniqueIdentifier类型的值。这是一个128位的整型、全球唯一的值,通常以字母或数字十六进制来表示(如89DE6247·C2E242DB-8CE8·A787E505D7EA)。这个类型经常被用作复制的和半连接系统中的主键.

NULLIF()

两个特定的参数的值如果是相同的,则返回NULL

PARSENAME()

返回一个具有4部分对象名的特定部分

PERMISSIONS()

返回一个整型值,该值是一个表示当前用户在指定的数据库对象上权限或者权限组合的位映像

ROWCOUNT_BIG()

与@@RowCount变量一样,这个函数返回被最后一条语句修改或返回的行数量。返回值类型是bigint

SCOPE_IDENTITY()

与@@IDENTIY变量一样,这个函数返回限制在当前会话与范围内的最后一次生成的标识值

SERVERPROPERTY()

返回一个表示服务器属性状态的标记。属性包括Collation、Edition、EngineEdition、InstanceName、IsClustered、IsFullTextInstalled、IsIntegrated-SecurityOnly、IsSingleUser、IsSyncWithBackup、LicenseTYpe、MachineName、NumLicenses、ProcessID、ProductLevel、ProductVersion、ServerName

SESSION_USER

返回当前用户名。调用本函数不需要括号

SESSIONPROPERTY()

返回表示一个会话属性状态的标记。属性包括:ANSL_NULLS,ANSI_PADDING,ANSL_WARNINGS,ARITHABORT,CONCAT_NULL_YIELDS_NULL,NUMERIC_ROUNDABORT,QUOTED_IDENTIFIER

STATS_DATE()

SYSTEM_USER

为一个指定的用户ID返回用户名。如果没有提供ID号则返回当前的数据库用户

COALESCE()函数是非常有用的,它返回其参数中第一个非空表达式。它能够节省颇多IF或者CASE分支逻辑。以下例子用产品数据填充一个表,每个产品最多有3种价格:

CREATETABLE#ProductPrices(ProductNamevarchar(25),SuperSalePriceMoneyNULL,SalePriceMoneyNULL,ListPriceMoneyNULL)

INSERTINTO#ProductPricesVALUES('StandardWidget',NULL,NULL,15.95)

INSERTINTO#ProductPricesVALUES('EconomyWidget',NULL,9.95,12.95)

INSERTINTO#ProductPricesVALUES('DeluxeWidget',19.95,20.95,22.95)

INSERTINTO#ProductPricesVALUES('SuperDeluxeWidget',29.45,32.45,38.95)

INSERTINTO#ProductPricesVALUES('ExecutiveWidget',NULL,45.95,54.95)

所有的产品都有定价,有些有销售价,有些还有促销价。一项产品的当前价格是所有己有价格的最低价,或者在读取每个价格列时以列出顺序读到的第一个非空值:

SELECTProductName,COALESCE(SuperSalePrice,SalePrice,ListPrice)ASCurrentPrice

FROM#ProductPrices

这个方法比使用多行分支与判断逻辑要简洁得多,而结果也是同样简单,如下图所示:

DATALENGTH()函数返回一个用于对值进行管理的字节数,这有助于揭示不同数据类型间的一些有趣差别。当把varchar类型传递给DATALENGTH()和LEN()函数时,它们将返回相同的值:

DECLARE@Valuevarchar(20)

SET@Value='abc'

SELECTDATALENGTH(@Value)

SELECTLEN(@Value)

这些语句的返回值都为3。因为varchar类型使用了3个单字节字符来存储三个字符的值。然而,如果使用nVarchar类型来管理相同长度的值,就要占用多一倍的字节:

DECLARE@Valuenvarchar(20)

DATALENGTH()函数返回值为6,因为每个使用Unicode字符集的字符都要占用2个字节。LEN()函数返回值为3,因为这个函数返回字符数,不是字节数。以下是一个有趣的测试:要存储一个值为2的整型变量,要占用多少个字节?而如果要存储一个值为20亿的整型变量,又将占用多少个字节呢?试一下:

DECLARE@Value1int,@Value2int

SET@Value1=2

SET@Value2=2000000000

SELECTDATALENGTH(@Value1)

SELECTLEN(@Value1)

SELECTDATALENGTH(@Value2)

SELECTLEN(@Value2)

在这两种情况下,DATALENGTH()函数都返回4。因为int类型不论值是多少,总是使用4个字节。LEN()函数本质上将整型值当成已转换成字符型的数据来处理,所以,在这个例子中,它分别返回1和10,即值的位数。

在下表中的全局系统变量都将返回int类型的值。这些变量可用于存储过程和其他实现定制业务逻辑的编程对象。

变量

@@ERROR

当前会话最后一次发生的错误代码

@@IDENTITY

当前会话最后一次生成的标识值

@@ROWCOUNT

当前会话中最后一次返回结果集的执行操作所返回的行数

@@TRANCOUNT

下表描述了用于确定数据库系统使用信息与环境信息的管理工具:

@@CONNECTIONS

返回打开连接的次数

@@CPU_BUSY

从上次启动服务器开始,SQLServer一共工作的毫秒数

@@IDLE

从上次启动服务器开始,SQLServer一共空闲的毫秒数

@@IO_BUSY

从上次启动服务器开始,SQLServer一共处理I/0的毫秒数

@@PACK_RECEIVED

从上次启动服务器开始,SQLServer一共收到的网络数据包数

@@PACK_SENT

从上次启动服务器开始,SQLServer一共发送的网络数据包数

@@PACKET_ERRORS

从上次启动服务器开始,SQLServer一共收到的网络数据包错误数

@@TIMETICKS

每个时钟滴答有多少毫秒

@@TOTAL_ERRORS

从上次启动服务器开始,SQLServer一共收到的磁盘I/O错误数

@@TOTAL_READ

从上次启动服务器开始,SQLServer一共进行的物理磁盘读取次数

@@TOTAL_WRITE

从上次启动服务器开始,SQLServer一共进行的物理磁盘写入次数

函数用于实现业务逻辑,并且能够将编程功能带入查询中。许多有用而且强大的函数是T-SQL的标准功能。和面向过程、面向对象语言中的函数一样,SQL函数也将程序功能封装到一个简单的可重用的包中,这就减少了查询设计人员的很多工作。由于Transact-SQL是面向任务的语言,而不是过程语言。虽然函数可以进行过程编程,可以在查询中构建颇为复杂的逻辑,但是SQL语言的优势在于让设计人员表达出设计意图,而不是完成一项任务的确切步骤与方法。只要使用方法正确,这些步骤和方法都可以由函数来实现。

在T-SQL中,参数用于将值传递给函数,大多数函数的返回结果是一个标量,或者说单一值。函数分为确定性函数与非确定性函数。在使用相同的参数时,确定性函数总是返回相同的值,而非确定性函数的返回值则与其他资源有关,所以SQLServer必须显式地执行这种函数。因此,在定制的SQL编程对象中,对非确定性函数的使用是有限制的。

SQL函数执行种类繁多的重要任务,包括数学运算、比较、日期解析与操纵、高级字符串操纵等。

THE END
1.2024年即食海鲜零食十大品牌排行榜即食海鲜零食哪个牌子好上榜理由:湖北良品铺子食品有限公司,湖北省著名商标,集休闲食品研发、加工分装及零售服务于一体,中部地区的休闲食品大型连锁企业。 6牧民纯中国官方旗舰店 国内品牌品牌热度:较好 上榜理由:牧民纯品牌成立于2016年,品牌牧民纯产品主要有猪蹄膀,奶疙瘩,柿子干,桂圆姜茶,纯魔芋粉饼干,无油饼干,蒙古奶酪,酸奶酪,烤鳗鱼...https://www.paizi10.com/paihang/jishihaixianlingshi.html
2.食品品牌命名及食品品牌名字大全食品饮料品牌命名大全食品品牌命名及食品品牌名字大全 从我们降临到这个龙头起,就离不开吃。随着生活条件的提高,人们对食品及饮食方面就更是很有讲究,在我们选择食物的时候,会看下食品品牌的名称,有些度很高的品牌,不用看我就知道是什么,这样即省下了看品牌与包装的的时间,还增加了人们的选购欲望,所以食品品牌命名对品牌的影响力很高...https://www.xianzhi.net/spylgsdq/36589.html
3.餐饮名字大全10000个,好听的餐饮商标名字大全大家给餐饮公司取名,也希望名字是好读顺口,能让顾客记住的,大家可以利用叠音给餐饮公司取名,这样取得的公司名字更加顺口,容易记住。这对餐饮公司的传播更加有利,可以让公司有更好的宣传、推广。下面是食品品牌名的取名方法,希望可以帮助大家。 餐饮名字大全10000个:好爱、思罗、浩易、圆方、宝盛、巨仕、具频、晖通...http://www.8882088.com/html/94.htm
4.法语名字大全.doc文档介绍:法语名字大全AAdélaïde阿代拉伊德(ādàilāyīdé)Adèle阿黛尔(ādàiěr)Adélie阿德丽(ādélì)Adeline阿德琳(ādélín)Adriana阿德里亚娜(ādélǐyànà)Adrienne阿德里安娜(ādélǐānnà)...https://m.taodocs.com/p-278818586.html
5.英文蔬菜水果名称大全.doc下载4. 探索水果和蔬菜的生长... 水果蔬菜动物类英语词汇大全-带音标.doc 这篇文档是关于水果、蔬菜和动物类的英语词汇列表,主要涵盖了常见的水果种类以及与之相关的术语。这个列表对于学习英语、尤其是食品和农业领域的英语非常有帮助。下面将详细解释其中的一些关键词汇: 1. **Almond*......https://bbs.csdn.net/wap/topics/602015112
6.食品店名字大全食品店名字洋气食品店名字大全 食品店名字洋气 泰茂食品店 仁达食品店 好吃吖 三慧食品店 香海食品店 逸香格 广益食品店 觅食阁 新润食品店 满福食品店 金冠食品店 赏美食品店 恒盛食品店 云鹏食品 美客多食品店 华清食品店 华美食品店 兆龙食品店 腾雄零食店 曼喜都...http://mingzi.jb51.net/qiming/dianpu/2654.html
7.食品商标名字大全,食品厂取名字大全好听大气食品商标名字大全,食品厂取名字大全好听大气 从事食品行业,是有很多要求的,食品质量最重要有,一定要质量达标,食品品牌名也同样重要,一定要取好了,品牌才能宣传出去,食品的商标品牌名怎么取呢? 食品商标名字大全:宏啸、名晶、辉迎、美高、林腾、财太、莱巨、航航、欧博、元康、利太、时磊、威雅、恒利、旺振、运...http://www.gongsiqiming.cn/htm/1397.htm
1.十大膨化食品品牌膨化食品品牌排行榜经专业评测的2024年膨化食品十大品牌名单发布啦!居前十的有:Lay’s乐事、Oishi上好佳、旺旺WantWant、可比克CAPICO、盼盼食品、Cheetos奇多、Pringles品客、Doritos多力多滋、Calbee卡乐比、小王子等,上榜膨化食品十大品牌榜单和著名膨化食品品牌名单的是口碑好或知名度高、有实力的品牌,排名不分先后,仅供借鉴参考,想知道...https://m.maigoo.com/maigoo/9308phsp_index.html
2....有多少个国家和地区?世界上国家和地区一览表在奥运会历史上有个惯例,开幕式各代表团入场次序的排定,除了固定的希腊第一,东道主最后,其他大多根据举办国的文字进行排序,例如1988年汉城奥运按照韩语排序,2004年雅典奥运会按照希腊语来排序,2008年北京奥运会上按照中文名字的笔画来排序,2012年伦敦奥运会以英文字母顺序排序,2015年里约热内卢奥运会按照葡萄牙语顺序排...http://114.xixik.com/country/
3.100种蔬菜大全名称绿意盎然探索全球百种蔬菜的魅力在撰写这篇文章时,我意识到我仍然只触及了冰山一角——《100种蔬菜大全名称》中的每一个都有其独特之处,每一种都值得我们去探索。如果你对学习更多关于这些宝贵资源感到好奇,那么翻阅这本全面的指南将是一个极佳开始。这不是一个简单列表,而是一个前往未知世界旅程,一次发现新的风味和健康生活方式之旅。https://www.yoocw.cn/zhan-hui-zi-xun/460069.html
4.生活中常见的动物名称大全生活中常见的动物名称大全-动物名字大全可爱 作文一:《生存中罕见的植物称号大全》400字 生存中罕见的植物称号大全哺乳植物虎 狼鼠鹿 貂猴貘 树懒斑马 狗狐熊象 豹子 麝牛 狮子小熊猫 疣猪 羚羊 驯鹿 考拉 犀牛 猞猁 穿山甲 长颈鹿 熊猫 食蚁兽 猩猩 海牛 水獭 灵猫 海豚 海象 鸭嘴兽 刺猬 北极狐 无尾熊 北极熊...https://www.xdyy8.com/wenxue/zuowen/60017.html
5.名称的造句大全名称的造句916:罗列出团队成员的名字及具体的软件名称,你甚至可以说“管理层的赞同”等等。 名称的造句917:我反对简称什么中华民国,这是一个祸国殃民的、群众对它没有好感的名称,20多年来更被蒋介石搞得不堪言状了。 名称的造句918:将数据源列的名称自动用作列标头文本。 https://www.zuowenku.net/zaoju/151503_19.shtml
6.蔬菜名称大全1000种我来教你每天吃的那些超级食材都叫啥名字简介在日常生活中,我们总是习惯性地叫一些蔬菜“萝卜”、“黄瓜”、“西红柿”,但你知道吗,这些只是我们常见的几种。其实,蔬菜的世界远比我们想象的要丰富得多。今天,我就来带你一探究竟,看看那些超级食材都叫啥名字! 首先,让我们从最基础的开始,一些大家都很熟悉的一些蔬菜,比如芹苣、菠菜、生姜等,它们不仅营...https://www.6lcvwvufw.cn/yin-shi-jian-kang/270998.html
7.主题亲自告诉你这些蔬菜的名字100种超详细大全在日常生活中,蔬菜不仅是我们营养均衡饮食不可或缺的一部分,也是美味健康餐桌上必不可少的元素。然而,有时候,我们可能会对那些蔬菜的名字感到好奇,不知道它们到底叫什么,或者记住它们的名称时总感觉手忙脚乱。这篇文章就来帮你一网打尽,列出100种蔬菜大全名称,让你的心头那份迷茫和困惑彻底消散。 https://www.werutwt.cn/yu-ye-shui-chan/203994.html
8.注册食品公司名字大全「食品公司的名字大全」最直接的方式是,公司明确自己的经营理念,如一个教育培训机构公司起名字,其公司理念是育人,立志培养出更多出人意料的、好的学生,那么其公司起名可参照成语一鸣惊人来起名,提取一鸣或惊鸣作为公司名字,都是很不错的选择。因为,联系公司经营理念可以帮助公司推广,让客户明确公司的特征。 https://agoodv.cn/news/12142.html
9.食品名字大全最新赞不绝口的企业名称糕点店名字大全 蛋糕店可爱名字大全2014 甜甜圈圈圆圆 最有名的蛋糕店名字 北京好利来蛋糕店 好利来企业创建于1992年9月,现为拥有上亿元固定资产,七千多名员工,及北京好利来企业投资管理有限公司、北京好利来工贸有限公司、北京好利来商贸有限公司等三家控股公司的大型食品专营连锁企业集团。 好利来的核心业务由两大部分组成...https://cai.verywind.com/xx/icemdiywmcyermdwne.htm
10.适合食品公司名称大全(免费简单大气)诺维、品霖、亚仁、品平、铭平、明雪食品、三叔公、美鲜食品、茂源堂、南岭、品寿香、昌源、泰冠、圣都食品、麦芒食品、泰晨、牛拾叁、浩祥、泰顺斋。 适合食品商标名字大全:顺利食品、绿野食品、美焕食品、尊东、君安食品、秋达、峰润、立盛、诺海、顺群、百盈、双威、仁德立、天河海、天庆食品、力丰、千...https://www.1566.cn/gongsimingzi/32852.html