函数类别
作用
聚合函数
执行的操作是将多个值合并为一个值。例如 COUNT、SUM、MIN和 MAX。
配置函数
是一种标量函数,可返回有关配置设置的信息。
转换函数
将值从一种数据类型转换为另一种。
加密函数
支持加密、解密、数字签名和数字签名验证。
游标函数
返回有关游标状态的信息。
日期和时间函数
可以更改日期和时间的值。
数学函数
执行三角、几何和其他数字运算。
元数据函数
排名函数
是一种非确定性函数,可以返回分区中每一行的排名值。
行集函数
返回可在 Transact-sql语句中表引用所在位置使用的行集。
返回有关用户和角色的信息。
字符串函数
可更改 char、varchar、nchar、nvarchar、binary和 varbinary 的值。
系统函数
对系统级的各种选项和对象进行操作或报告。
文本和图像函数
可更改 text 和 image的值。
函数的组成
Result=Function()
SELECT Function()
一个论点
CONVERT (data-type [(length)],expression[,style])
可将它简化为如下形式,因为现在不讨论如何使用数据类型:
CONVERT(date_type,style])
根据上面的定义,CONVERT()函数可接受2个或3个参数。因此,下列两个例子都是正确的:
SELECTCONVERT(Varchar(20),GETDATE())
SELECTCONVERT(Varchar(20),GETDATE(), 101)
确定性函数
由于数据库引擎的内部工作机制,sql Server必须根据所谓的确定性,将函数分成两个不同的组。这不是一种新时代的信仰,只和能否根据其输入参数或执行对函数输出结果进行预测有关。如果函数的输出只与输入参数的值相关,而与其他外部因素无关,这个函数就是确定性函数。如果函数的输出基于环境条件,或者产生随机或者依赖结果的算法,这个函数就是非确定性的。例如,GETDATE()函数是非确定性函数,因为它不会两次返回相同的值。为什么要把看起来简单的事弄得如此复杂呢?主要原因是非确定性函数与全局变量不能在一些数据库编程对象中使用(如用户自定义函数)。部分原因是sql Server缓存与预编译可执行对象的方式。例如,即席查询可以使用任何函数,不过如果打算构建先进的、可重用的编程对象,理解这种区别很重要。
以下这些函数是确定性的:
lAVG()(所有的聚合函数都是确定性的)
lCAST()
lCONVERT()
lDATEADD()
lDATEDIFF()
lASCII()
lCHAR()
lSUBSTRING()
以下这些函数与变量是非确定性的:
lGETDATE()
l@@ERROR
l@@SERVICENAME
lCURSORSTATUS()
lRAND()
DECLARE@MyNumberint
SET@MyNumber=144
SELECTSQRT(@MyNumber)
结果是12,即144的平方根。
用SET给变量赋值
DECLARE@MyNumberint,@MyResultint
SET@MyNumber= 144
-- Assign the function result to the variable:
SET@MyResult= SQRT(@MyNumber)
-- Return the variable value
SELECT@MyResult
用SELECT给变量赋值
使用SELECT的另一种形式也可以获得同样的结果。对变量要在赋值前要先声明。使用SELECT语句来替代SET命令的主要优点是,可以在一个操作内同时给多个变量赋值。执行下面的SELECT语句,通过SELECT语句赋值的变量就可以用于任何操作了。
DECLARE@MyNumber1int,@MyNumber2int,
@MyResult1int,@MyResult2 int
SELECT@MyNumber1= 144,@MyNumber2= 121
-- Assign the function result to the variable:
SELECT@MyResult1= SQRT(@MyNumber1),
@MyResult2=SQRT(@MyNumber2)
-- Return the variable value
SELECT@MyResult1,@MyResult2
DECLARE@RestockNamevarchar(50)
SELECTProductId
,@RestockName=Name + ':' + ProductNumber
FROMProduction.Product
这个脚本会产生如下错误:
消息141,级别15,状态1,第2行
向变量赋值的SELECT 语句不能与数据检索操作结合使用。
SELECTTitle,NationalIDNumber,YEAR(BirthDate)ASBirthYear
FROMHumanResources.Employee
嵌套函数
SELECTCONVERT(Varchar(20), 101)
聚合函数
上个月鸡雏的总销售量是多少?
19~24岁之间的巴西男性在食品调味品上的平均支出是多少?
上季度所有订单中从订购到运输的最长时间是多少?
收发室里仍在工作的最老的员工是谁?
SELECTAVG(15)
SELECTSUM(15)
SELECTMIN(15)
SELECTMAX(15)
SELECTCOUNT(15)
AVG()函数
AVG()函数用于返回一组数值中所有非空数值的平均值。例如,表6-2包含了体操成绩。
表 6-2
对这些数据执行以下查询:
SELECT AVG(score)
结果是8.965。
如果有三个女孩没有完成一些项目,在表中没有记录成绩,则可用NULL来表示(见表6-3)。
表 6-3
脚本:
createtable#GymEvent(Playervarchar(10),[Subject]nvarchar(5),scoredecimal(4,2))
go
insertinto#GymEvent values('Sara','跳马',9.25)
insertinto#GymEvent values('Cassie',8.75)
insertinto#GymEvent values('Delaney',NULL)
insertinto#GymEvent values('Sammi',8.05)
insertinto#GymEvent values('Erika',8.60)
insertinto#GymEvent values('Sara','平衡木',9.70)
insertinto#GymEvent values('Cassie',NULL)
insertinto#GymEvent values('Delaney',9.25)
insertinto#GymEvent values('Sammi',NULL)
insertinto#GymEvent values('Erika',8.85)
go
droptable#GymEvent
在这种情况下,计算平均值时只考虑实际的数值,NULL不参与运算,结果是8.921429。但是,如果把缺少的成绩也算在内,即用数值0代替NULL,则会严重影响最终成绩(6.245),她们能不能进入国家级的比赛就难说了。
COUNT()函数
SELECTCOUNT(score)FROM#GymEvent WHERE Player='Sammi'
结果是1,因为Sammi只参加了跳马比赛,她的平衡木成绩是NULL。
如果需要确定表中的行数,无论这些行是不是NULL值,都可以使用以下语法:
SELECTCOUNT(*) FROM #GymEvent
以Sammi为例,COUNT(*)查询如下所示:
SELECTCOUNT(*)FROM #GymEvent WHEREPlayer='Sammi'
MIN()与MAX()函数
表 6-4
IntegerColumn(int类型)
VarCharColumn(varChar类型)
2
2
4 4
12 12
19 19 脚本:
createtable#Temp(IntegerColumnint,VarCharColumnvarchar(10))
go
insertinto#Temp values(2,'2')
insertinto#Temp values(4,'4')
insertinto#Temp values(12,'12')
insertinto#Temp values(19,'19')
go
droptable#Temp
selectMIN(IntegerColumn),MAX(IntegerColumn)from#Temp
selectMIN(VarCharColumn),MAX(VarCharColumn)from#Temp
因为VarCharColumn中值的存储类型为字符类型,而不是数字,所以结果以每个字符的ASCII值为顺序从左到右排序。这就是12比其他值小、而4比其他值大的原因。
SUM()函数
配置变量
@@ERROR变量
SELECT*FROM sys.messages
SELECT 5/ 0
SELECT@@ERROR
SELECT 5/ 0
SELECT*FROM master.dbo.sysmessagesWHEREerror = @@ERROR
error
severity
dlevel
description
msglangid
8134
16
0
Divide by zero error encountered.
1033
8134 16 0 Fehler aufgrund einer Division durch Null. 1031 Division par zéro.
1036 0 除算エラーが発生しました。 1041 Error de división entre cero. 3082 Errore di divisione per zero. 1040 Обнаружена ошибка:делениенаноль.
1049 Erro de divisão por zero. 1046 發現除以零的錯誤。
1028 0으로나누기오류가 발생했습니다. 1042 遇到以零作除数错误。
2052
SELECTalias,name, msglangid
FROMsys.syslanguages
@@SERVICENAME变量
@@TOTAL_ERRORS变量
@@TOTAL_READ变量
这个变量记录从打开当前连接时开始计算的磁盘读取总数。DBA使用这个变量查看磁盘读取活动的情况。
@@VERSION变量
这个变量包含当前sql Server实例的完整版本信息。
SELECT@@VERSION
比如,对于运行在Windows 7上的sql Server 2008开发版实例,以上脚本能够返回如下信息:
--Try to do something
BEGINTRY
SELECT 5/ 0
ENDTRY
--If it causes an error,do this
BEGINCATCH
PRINTERROR_MESSAGE()
ENDCATCH
下表简要描述了严重级别。
--Try to do something
BEGINTRY
SELECT 5/ 0
ENDTRY
--If it causes an error,do this
BEGINCATCH
SELECTERROR_MESSAGE(),ERROR_NUMBER(),ERROR_SEVERITY(),
ERROR_STATE(),ERROR_LINE(),ERROR_PROCEDURE()
ENDCATCH
转换函数
CAST()函数
SELECTCAST('123'ASint)
SELECTCAST('123.4'ASint)
Server: Msg 245, Level 16,State 1,Line 1
Syntax error converting thevarchar value
'123.4' to acolumn of data typeint.
在将varchar值'123.4' 转换成数据类型int时失败。
SELECTCAST('123.4'ASdecimal(9,2))
decimal数据类型在结果网格中将显示有效小数位:123.40
SELECTCAST('123.4'ASdecimal)
结果是一个整数值:123
在表的数据中转换数据类型是很简单的。下面的例子使用Product表,首先执行如下查询:
SELECTProductNumber,ProductLine, ProductModelID
FROMProduction.Product
WHEREProductSubcategoryID< 4
如果使用下面的表达式,就不能得到希望的结果,如图6-2所示。
SELECTProductNumber
+'-'
+ProductLine
+'-'
+ProductModelIDASBikeSerialNum
FROMProduction.Product
WHEREProductSubcategoryID< 4
消息245,级别16,状态1,第1行
在将nvarchar值'BK-R93R-62-R -'转换成数据类型int时失败。
SELECTProductNumber
+'-'
+ProductLine
+'-'
+CAST(ProductModelIDASchar(4))ASBikeSerialNum
FROMProduction.Product
WHEREProductSubcategoryID< 4
CONVERT()函数
SELECTCONVERT(int,'123')
SELECTCONVERT(decimal(9,2),'123.4')
yy(1)
yyyy
标准
输入/输出 (3)
-
0 或 100 (1,2)
默认
mon dd yyyy hh:miAM(或 PM)
1 101
美国
mm/dd/yyyy 2 102
ANSI
yy.mm.dd
3 103 英国/法国
dd/mm/yyyy 4 104
德国
dd.mm.yy
5 105 意大利
dd-mm-yy 6 106 (1)
-
dd mon yy
7 107 (1) - mon dd,yy 8 108
hh:mi:ss
- 9 或 109 (1,2)
默认设置 +毫秒
mon dd yyyy hh:mi:ss:mmmAM(或 PM)
10 110
美国
mm-dd-yy
11 111 日本
yy/mm/dd 12 112
ISO
yymmdd
yyyymmdd
13 或 113 (1,198) currentColor; padding:0cm 5.4pt"> 欧洲默认设置dd mon yyyy hh:mi:ss:mmm(24h)
14 114
hh:mi:ss:mmm(24h)
20 或 120 (2) ODBC 规范 yyyy-mm-dd hh:mi:ss(24h) 21 或 121 (2)
ODBC 规范(带毫秒)
yyyy-mm-dd hh: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,198) currentColor; padding:0cm 5.4pt"> 回历 (5)
dd mon yyyy hh:mi:ss:mmmAM 131 (2)
回历 (5)
dd/mm/yy hh:mi:ss:mmmAM
1.这些样式值将返回不确定的结果。包括所有 (yy)(不带世纪数位)样式和一部分 (yyyy)(带世纪数位)样式。
2.默认值(style 0或 100、9 或 109、13或 113、20或 120 以及 21或 121)始终返回世纪数位 (yyyy)。
3.转换为 datetime时输入;转换为字符数据时输出。
5.回历是有多种变体的日历系统。sql Server使用科威特算法。
6.仅支持从字符数据转换为 datetime或 smalldatetime。仅表示日期或时间成分的字符数据转换为 datetime或 smalldatetime数据类型时,未指定的时间成分设置为 00:00:00.000,未指定的日期成分设置为 1900-01-01。
7.使用可选的时间区域指示符 (Z)更便于将具有时区信息的 XML datetime 值映射到没有时区的 sql Server datetime值。Z 是时区 UTC-0的指示符。其他时区则以 + 或 -方向的 HH:MM 偏移量来指示。例如:2006-12-12T23:45:12-08:00。
从样式包含时间的字符数据转换为 datetimeoffset时,将在结果末尾追加时区偏移量。
SELECT'Default Date:'+ CONVERT(Varchar(50), 100)
Default Date: Apr 25 2005 1:05PM
SELECT'US Date:'+ CONVERT(Varchar(50), 101)
US Date: 04/25/2005
SELECT'ANSI Date:'+ CONVERT(Varchar(50), 103)
ANSI Date: 2005.04.25
SELECT'UK/french Date:'+CONVERT(Varchar(50), 103)
UK/french Date: 25/04/2OO5
SELECT'German Date:'+ CONVERT(Varchar(50), 104)
German Date: 25.04.2005
DECLARE@NumMoney
SET@Num= 1234.56
SELECTCONVERT(varchar(50),@Num, 0)
返回结果如下:
1234.56
使用值1则返回如下结果:
1,234.56
使用值2则返回如下结果:
1234.5600
以下例子和上例相同,但是使用Float类型:
DECLARE@Numfloat
SET@Num= 1234.56
SELECTCONVERT(varchar(50), 2)
使用值0不会改变所提供的格式,但是使用值1或2将返回以科学计数法表示的数字,后者使用了15位小数:
1.23456000000000e+003
SELECTSTR(123.4, 8, 4)
结果值的右边以0填充:123.4000。
SELECTSTR(123.456789, 4)
SELECTSTR(1, 6, 4)
1.0000
然而,如果指定的总长度大于整数位数、小数点和小数位数之和,结果值的左边将用空格补齐:
SELECTSTR(1, 4)
1.0000
SELECTSTR(1, 12, 4)
---------- 1.0000
游标函数与变量
CURSOR_STATUS()函数
返回 值
说明
1
游标包含一行或多行(动态游标包含0行或者多行)
0 游标不包含行
-1 游标已关闭
-2 游标未分配
-3 游标不存在
@@CURSOR_ROWS全局变量
这个变量是一个整型值,表示在当前连接中打开的游标中的行数。根据游标类型,这个值也能不代表结果集中的实际行数。
@@FETCH_STATUS全局变量
日期函数
数据类型
time
12:35:29. 1234567
date 2007-05-08 smalldatetime 2007-05-08 12:35:00 datetime 2007-05-08 12:35:29.123 datetime2 2007-05-08 12:35:29. 1234567 datetimeoffset 2007-05-08 12:35:29.1234567 +12:15 DATEADD()函数
SELECTDATEADD(DAY, 90,'4-29-2007')
结果:2007-07-28 00:00:00.000
可以把下表的值作为时间间隔参数传递给DATEADD()函数。
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-1988 10:30 AM')
2006-04-29 10:30:00.000
18年前:
SELECTDATEADD(YY,-18,'4-29-1988 10:30 AM')
1970-04-29 10:30:00.000
9000秒后:
SELECTDATEADD(SECOND, 9000,'4-29-1988 10:30 AM')
1988-04-29 13:00:00.000
9000000毫秒前:
SELECTDATEADD(MS,-9000000,'4-29-1988 10:30 AM')
1988-04-29 08:00:00.000
SELECTCONVERT(varchar(20),DATEADD(M,-9,'9-8-1989'), 101)
12/08/1988
DATEDIFF()函数
SELECTDATEDIFF(MONTH,'9-8-1989','10-17-1991')
结果是25个月。如果以日期为单位呢?
SELECTDATEDIFF(DAY,'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())AS ApproximateAge
FROMHumanResources.Employeease inner join
Person.Contactasc on e.ContactID=c.ContactID
orderbyc.LastName
下图显示了结果:
初看起来结果是对的,但存在的问题是年龄值没有精确到日。比如,根据表中的数据,Nancy的生日是12月21日,他今年将庆祝第32个生日(这个查询在2010年8月运行)。如果依据上述计算结果来确定他的年龄何时变化,就应在一月份的某天给他发生日卡片,这比实际日期提前了11个月。
除非用更小的时间单位来计算这些日期的差,否则结果只在雇员实际生日的一年以内是精确的。以下例子将用差值除以一年(包括闰年)的天数,并将结果值转换为int类型,进行取整运算,而不是四舍五入。
SELECTc.FirstName
,GETDATE())AS ApproximateAge
,CONVERT(int,DATEDIFF(DAY,GETDATE())/365)ASAge
FROMHumanResources.Employeease inner join
Person.Contactasc on e.ContactID=c.ContactID
orderbyc.LastName
比较这次的结果和上一个例子的结果,看看有什么不同。
DATEPART()与DATENAME()函数
SELECTDATEPART(MONTH,'4-29-1988')
而使用相同的参数,DATENAME()函数返回04(这取决于你的机器的本地语言,如果是英文版,那么将返回April):
SELECTDATENAME(MONTH,'4-29-1988')
GETDATE()与GETUTCDATE()函数
SELECTGETDATE()
SELECTGETUTCDATE()
执行这两个函数,都将返回未经格式化的结果,见下图:
我在北京,和UTC时间相差8个小时,和标准时间相差9个小时。可以使用如下DATEDIFF()函数来验证这个时间差值:
SELECTDATEDIFF(HOUR,GETUTCDATE())
SYSDATETIME()和SYSUTCDATETIME()函数
SELECTSYSDATETIME()
SELECTSYSUTCDATETIME()
DAY()、MONTH()和YEAR()函数
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
字符串操纵函数
ASCII()、CHAR()、UNICODE()和NCHAR()函数
在计算机的发展过程中, ASCII字符集发布没多长时间便过时了。人们很快将它扩展成为256个字符的ANSI字符集,一个字符用一个字节来保存。这个扩展的字符列表满足了许多其他用户的需求,可以支持主要的欧洲语言字符,不过仍是美国标准(由美国国家标准学会持有),仍建立在最初的英语字符集的基础上。为了支持所有可印刷的语言,人们制订了Unicode标准,它支持多种语言特定的字符集。每个Unicode字符需要2个字节的存储空间,是ASCII与ANSI字符的两倍。但是使用2个字就可以表示超过65 000个不同的字符,完全能够支持东欧和亚洲字符。sql Server同时支持ASCII与Unicode两种标准。
SELECTASCII('A')
结果是65。
SELECTCHAR(65)
结果是字母A。
--创建一个临时表来保存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)ASCharacter FROM #ASCIIVals
droptable#ASCIIVals
表6-12是以多栏网格重新格式化的结果集。需要注意的是这里将不可印刷的控制字符以方括号表示。由于许多因素限制,如所安装的字体或语言不同,下表的显示可能会有稍许差异。
要返回扩展字符编码集中的字符,可以将字符编码传递给NCHAR()函数:
SELECTNCHAR(220)
返回字母ü。
SELECTNCHAR(233)
返回带重音符号的小写e:é。
SELECTNCHAR(241)
SELECTNCHAR(433)
下面的查询返回西里尔字母Ya(Я)。
SELECTNCHAR(1071)
CHARINDEX()和PATINDEX()函数
SELECTCHARINDEX('sh','Washington')
SELECTPATINDEX('%M_rs%','The stars near Mars are far from ours')
注意,如果想找到一个字符串,在所比较的字符串的前后各有0个或者多个字符,则两个百分符都是必须的。下划线表明这个位置上的字符不必匹配,它可以是任意字符。
和使用相同字符串的CHARINDEX()函数作一下比较:
SELECTCHARINDEX('Mars','The stars near Mars are far from ours')
LEN()函数
DECLARE@MonthCharvarchar(2),@DayCharvarchar(2),@DateOutchar(8)
SET@MonthChar= CAST(MONTH(GETDATE())ASvarchar(2))
SET@DayChar= CAST(DAY(GETDATE())ASvarchar(2))
-- Make sure month and day are two char long:
IFLEN(@MonthChar)= 1
SET@MonthChar= '0' + @MonthChar
IFLEN(@DayChar)= 1
SET@DayChar= '0' + @DayChar
-- Build date string:
SET@DateOut= @MonthChar + @DayChar+CAST(YEAR(GETDATE())ASchar(4))
SELECT@DateOutAS OutputDate
这个脚本将返回代表日期的8个字符:
08152010
LEFT()和RIGHT()函数
DECLARE@FullNamevarchar(25)
SET@FullName= 'George Washington'
SELECTLEFT(@FullName, 5)
结果为:Georg
DECLARE@FullNamevarchar(25)
SET@FullName= 'George Washington'
SELECTRIGHT(@FullName, 5)
结果为:ngton
结果为:George
如果不想在结果中包含空格,就需要从@SpaceIndex值中减去1,这样结果中就只有名字了。
SUBSTRING()函数
DECLARE@FullNamevarchar(25)
SET@FullName= 'George Washington'
SELECTSUBSTRING(@FullName, 4, 6)
DECLARE@FullNamevarchar(25)
SET@FullName= 'George Washington'
-- Return first name:
SELECTSUBSTRING(@FullName, 1,CHARINDEX(' ',@FullName)- 1)
类似的逻辑可以用于解析姓氏,但是必须将起始位置更改为空格后的那个字符。如果空格在第7个位置上,那么姓氏将从第8个位置开始。这就意味着起始位置是CHARINDEX()的返回结果加上1。
DECLARE@FullNamevarchar(25)
SET@FullName= 'George Washington'
--Return last name:
SELECTSUBSTRING(@FullName,@FullName)+ 1,
LEN(@FullName))
为了举例方便,先创建并填充一个临时表:
CREATETABLE#MyNames (FullNamevarchar(50))
GO
INSERTINTO#MyNames (FullName)SELECT'Fred Flintstone'
INSERTINTO#MyNames (FullName)SELECT'Wilma Flintstone'
INSERTINTO#MyNames (FullName)SELECT'Barney Rubble'
INSERTINTO#MyNames (FullName)SELECT'Betty Rubble'
INSERTINTO#MyNames (FullName)SELECT'George Jetson'
INSERTINTO#MyNames (FullName)SELECT'Jane Jetson'
go
--drop table #MyNames
SELECT
SUBSTRING(FullName,FullName)- 1) AS FirstName
,SUBSTRING(FullName,FullName)+ 1, LEN(FullName))ASLastName
FROM#MyNames
在下图所示的结果中,显示了两个不同的列,分别是名字和姓氏。
LOWER()和UPPER()函数
DECLARE@LastNamevarchar(25),@SpaceIndextinyint
SET@LastName= 'mc donald' -- Test value
-- Find space in name:
SET@SpaceIndex= CHARINDEX(' ',@LastName)
IF@SpaceIndex> 0 -- Space: Capitalize first & substring
SELECTUPPER(LEFT(@LastName, 1))
+LOWER(SUBSTRING(@LastName, 2,@SpaceIndex - 1))
+UPPER(SUBSTRING(@LastName,@SpaceIndex+ 1,@SpaceIndex+ 2,LEN(@LastName)))
ELSE-- No space: Cap only first char.
SELECTUPPER(LEFT(@LastName, 1))
+LOWER(SUBSTRING(@LastName,LEN(@LastName)))
DECLARE@LastNamevarchar(25),@SpaceIndextinyint,@AposIndextinyint
SET@LastName= 'o''malley' -- Test value
-- Find space in name:
SET@SpaceIndex= CHARINDEX(' ',@LastName)
-- Find literal ' in name:
SET@AposIndex= CHARINDEX('''',LEN(@LastName)))
ELSEIF@AposIndex > 0 -- Apostrophe: Cap first & substring
SELECTUPPER(LEFT(@LastName,@AposIndex - 1))
+UPPER(SUBSTRING(@LastName,@AposIndex+ 1,@AposIndex+ 2,LEN(@LastName)))
ELSE-- Nospace: Cap only first char.
SELECTUPPER(LEFT(@LastName,LEN(@LastName)))
这个脚本返回O'Malley。
LTRIM()和RTRIM()函数
这两个函数分别返回将字符串的左边和右边的空白修剪掉之后的字符串:
结果如下:
REPLACE()函数
DECLARE@Phrasevarchar(1000)
SET@Phrase= 'I aint gunna use poorgrammar when commenting script and
I aint gunna complain about it. '
SELECTREPLACE(@Phrase,'aint','am not')
REPLICATE()和SPACE()函数
SELECTFullName+ REPLICATE('*', 20-LEN(FullName))
FROM#MyNames
结果是每个名字后面都填满了星号,各个名字的总长度都是20个字符:
Fred Flintstorle*****
Wilrna Flintstone****
Barney Rubble*******
Betty Rubble********
George Jetson********
Jane Jetson**********
SELECTFullName+ SPACE(20-LEN(FullName))
FROM#MyNames
REVERSE()函数
顾名思义,这个函数用于将字符串中的字符颠倒过来。这在处理连接列表中的单个字符值时将会被用到。
SELECTREVERSE('The stars near Mars are far from ours. ')
结果为:.sruo morf raf era sraM raen srats ehT
STUFF()函数
Please submit your payment for 99.95 immediately.
SELECTSTUFF('Please submit your payment for 99.95 immediately. ', 32, 5,'109.95')
结果为:Please submit your payment for 109.95 immediately.
QUOTENAME()函数
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() 计算一个角正切的值,以弧度表示
元数据函数
排列函数
这些函数被用于以与结果集顺序无关的特定顺序,枚举已排序的或排在前面的结果集。
ROW_NUMBER()函数
SELECTProductCategoryID
,Name
,ROW_NUMBER()OVER(ORDERBYName)ASRowNum
FROMProduction.ProductCategory
ORDERBYName
SELECTProductCategoryID
,ROW_NUMBER()OVER(ORDERBYName)ASRowNum
FROMProduction.ProductCategory
ORDERBYProductCategoryID
这是了解如何使用ORDER BY子句对结果进行排序的有效方法。如下图所示:
RANK()与DENSE_RANK()函数
其行为类似于短跑比赛中的并列成绩。例如刘翔与Dayron Robles(古巴)在110栏的比赛中都跑出了12’92的成绩,那他们就是并列第一,而其后的一名选手将会获得第三名的成绩。
SELECTProductID
,ListPrice
,RANK()OVER(ORDERBYListPrice DESC)AS [Rank]
FROMProduction.Product
ORDERBY[Rank]
注意在下图的结果列表中,重复的价格值所对应的结果是相同的,而每个连接之后的值都被跳过了。比如,产品"Road-150 Red,52"和"Road-150 Red,56"都排在第1,而接下来的行"Mountain-100 Silver,38"就排在第6了。
SELECTProductID
,DENSE_RANK()OVER(ORDERBYListPrice DESC)AS [Rank]
FROMProduction.Product
ORDERBY[Rank]
下图的结果重复了排列值,但是不会跳过列中的任何数字。
NTILE(n)函数
SELECTProductID
,NTILE(50)OVER(ORDERBYListPrice DESC)AS GroupedProducts
FROMProduction.Product
ORDERBYGroupedProducts
结果为:
函数
说明
fn_trace_geteventinfo()
为指定的跟踪ID返回一个填充事件信息的表类型值
fn_trace_getfilterinfo() ID返回一个填充与过滤器有关的信息的表类型值 fn_trace_getinfo() ID返回一个填充跟踪信息的表类型值 fn_trace_getable() ID返回一个填充文件信息的表类型值 HAS_dbaccess() IS_MEMBER() IS_SRVROLEMEMBER() SUSER_SID() 返回指定用户的登录名的安全ID,或者(如果参数被忽略)返回当前用户的安全ID。返回指定用户的用户(如果参数被忽略的话)返回当前用户的用户ID
SUSER_SNAME() USER_ID() 系统函数与系统变量
函数
说明
APP_NAME()
返回与当前连接相关联的应用程序的名字
COALESCE()
从以逗号分隔的表达式列表中返回第一个非空值
COLLATIONproperty() CURRENT_TIMESTAMP() C1UJRRENT_USER()
DATALENGTH() 返回存储或处理一个值所需的字节数。对于ANSI字符串类型,这个函数返回的值与LEN()函数相同,但对于其他数据类型而言就可能不一定相同了
fn_helpcollations() fn_servershareddrives() 返回一个填充有服务器共享的驱动列表的表类型值
fn_virtualfilestats()
FORMATMESSAGE() GETANSINULL() HOST_ID() 返回当前会话的工作站ID
HOST_NAME() 返回当前会话的工作站名
IDENT_CURRENT() IDENT_INCR() 返回最后一次创建的标识(ID)列中定义的增量值
IDENT_SEED() 返回最后一次创建的标识(ID)列中定义的种子值
IDENTITY() ISDATE() 返回一个表明指定的值是否可被转换为日期值的标志
ISNULL() 判断指定的值是否是空值,然后返回一个事先提供的替代值
ISNUMERIC() 返回一个表明指定的值是否可被转换为数字值的标志
NEWID() 返回一个新生成的UniqueIdentifier类型的值。这是一个128位的整型、全球唯一的值,通常以字母或数字十六进制来表示(如89DE6247·C2E242DB-8CE8·A787E505D7EA)。这个类型经常被用作复制的和半连接系统中的主键.
NULLIF() 两个特定的参数的值如果是相同的,则返回NULL
PARSENAME() 返回一个具有4部分对象名的特定部分
PERMISSIONS() ROWCOUNT_BIG() ScopE_IDENTITY() 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 USER_NAME() COALESCE()函数
CREATETABLE#ProductPrices(ProductNamevarchar(25),SuperSalePriceMoneyNULL, SalePrice Money NULL,ListPriceMoney NULL)
GO
INSERTINTO#ProductPricesVALUES('Standard Widget',NULL, 15.95)
INSERTINTO#ProductPricesVALUES('Economy Widget', 9.95, 12.95)
INSERTINTO#ProductPricesVALUES('Deluxe Widget', 19.95, 20.95, 22.95)
INSERTINTO#ProductPricesVALUES('Super Deluxe Widget', 29.45, 32.45, 38.95)
INSERTINTO#ProductPricesVALUES('Executive Widget', 45.95, 54.95)
GO
所有的产品都有定价,有些有销售价,有些还有促销价。一项产品的当前价格是所有己有价格的最低价,或者在读取每个价格列时以列出顺序读到的第一个非空值:
SELECTProductName,COALESCE(SuperSalePrice,SalePrice,ListPrice) ASCurrentPrice
FROM#ProductPrices
这个方法比使用多行分支与判断逻辑要简洁得多,而结果也是同样简单,如下图所示:
DATALENGTH()函数
DECLARE@Valuevarchar(20)
SET@Value= 'abc'
SELECTDATALENGTH(@Value)
SELECTLEN(@Value)
这些语句的返回值都为3。因为varchar类型使用了3个单字节字符来存储三个字符的值。然而,如果使用nVarchar类型来管理相同长度的值,就要占用多一倍的字节:
DECLARE@Valuenvarchar(20)
SET@Value= 'abc'
SELECTDATALENGTH(@Value)
SELECTLEN(@Value)
DECLARE@Value1int,@Value2int
SET@Value1= 2
SET@Value2= 2000000000
SELECTDATALENGTH(@Value1)
SELECTLEN(@Value1)
SELECTDATALENGTH(@Value2)
SELECTLEN(@Value2)
在下表中的全局系统变量都将返回int类型的值。这些变量可用于存储过程和其他实现定制业务逻辑的编程对象。
系统统计变量
下表描述了用于确定数据库系统使用信息与环境信息的管理工具:
变量
说@@CONNECTIONS
返回打开连接的次数
@@cpu_BUSY 从上次启动服务器开始,sql Server一共工作的毫秒数
@@IDLE 从上次启动服务器开始,sql Server一共空闲的毫秒数
@@IO_BUSY 从上次启动服务器开始,sql Server一共处理I/0的毫秒数
@@PACK_RECEIVED sql Server一共收到的网络数据包数 @@PACK_SENT 从上次启动服务器开始,sql Server一共发送的网络数据包数
@@PACKET_ERRORS sql Server一共收到的网络数据包错误数 @@TIMETICKS 每个时钟滴答有多少毫秒
@@TOTAL_ERRORS sql Server一共收到的磁盘I/O错误数 @@TOTAL_READ @@TOTAL_WRITE sql Server一共进行的物理磁盘写入次数 小结