SQL中STR()函数功能哪个函数可比较

SQL WHERE 子句
SQL WHERE 子句
WHERE 子句用于规定选择的标准。
WHERE 子句
如需有条件地从表中选取数据,可将 WHERE 子句添加到 SELECT 语句。
SELECT 列名称 FROM 表名称 WHERE 列 运算符 值
下面的运算符可在 WHERE 子句中使用:
在某个范围内
搜索某种模式
注释:在某些版本的 SQL 中,操作符 && 可以写为 !=。
使用 WHERE 子句
如果只希望选取居住在城市 &Beijing& 中的人,我们需要向 SELECT 语句添加 WHERE 子句:
SELECT * FROM Persons WHERE City='Beijing'
&Persons& 表
Oxford Street
Fifth Avenue
Changan Street
Xuanwumen 10
Changan Street
Xuanwumen 10
引号的使用
请注意,我们在例子中的条件值周围使用的是单引号。
SQL 使用单引号来环绕文本值(大部分数据库系统也接受双引号)。如果是数值,请不要使用引号。
这是正确的:
SELECT * FROM Persons WHERE FirstName='Bush'
这是错误的:
SELECT * FROM Persons WHERE FirstName=Bush
这是正确的:
SELECT * FROM Persons WHERE Year&1965
这是错误的:
SELECT * FROM Persons WHERE Year&'1965'SQL中有哪些函数?越详细越好!!!-CSDN论坛
SQL中有哪些函数?越详细越好!!!
SQL中有哪些函数?越详细越好!!!
例如&datediff(week,时间字段,getdate())&,newId()等~
谢谢大家了~~
到联机丛书中找吧
--聚合函数
select&avg(distinct&price)&&--算平均数
from&titles
where&type='business'
select&max(ytd_sales)&&--最大数
from&titles
select&min(ytd_sales)&--最小数
from&titles
select&type,sum(price),sum(advance)&&--求和
from&titles
group&by&type
order&by&type
select&count(distinct&city)&&--求个数
from&authors
select&stdev(royalty)&--返回给定表达式中所有值的统计标准偏差
from&titles
select&stdevp(royalty)&--返回表达式中所有制的填充统计标准偏差
from&titles
select&var(royalty)&--返回所有值的统计方差
from&titles
select&varp(royalty)&--返回所有值的填充的统计方差
from&titles
--数学函数&
select&sin(23.45),atan(1.234),rand(),PI(),sign(-2.34)&--其中rand是获得一个随机数
--配置函数
SELECT&@@VERSION&--获取当前数据库版本
SELECT&@@LANGUAGE&--当前语言
--时间函数
select&getdate()&as&'wawa_getdate'&--当前时间
select&getutcdate()&as&'wawa_getutcdate'&--获取utc时间
select&day(getdate())&as&'wawa_day'&--取出天
select&month(getdate())&as&'wawa_month'&--取出月
select&year(getdate())&as&'wawa_year'&--取出年
select&dateadd(d,3,getdate())&as&wawa_dateadd&--加三天,注意'd'表示天,'m'表示月,'yy'表示年,下面一样
select&datediff(d,'','')&as&wawa_datediff&--计算两个时间的差
select&datename(d,'')&as&wawa_datename&--取出时间的某一部分
select&datepart(d,getdate())&as&wawa_datepart&&--取出时间的某一部分,和上面的那个差不多
--字符串函数
select&ascii(123)&as&'123',ascii('123')&as&'"123"',ascii('abc')&as&'"abc"'&--转换成ascii码
select&char(123),char(321),char(-123)&--根据ascii转换成字符
select&lower('ABC'),lower('Abc'),upper('Abc'),upper('abc')&--转换大小写
select&str(123.45,6,1),&str(123.45,2,2)&--把数值转换成字符串
select&ltrim('&&&&"左边没有空格"')&&--去空格
select&rtrim('"右边没有空格"&&&&&')&--去空格
select&ltrim(rtrim('&&&"左右都没有空格"&&&&'))&--去空格
select&left('sql&server',3),right('sql&server',6)&--取左或者取右&
select&au_lname,substring(au_fname,1,1)&--取子串
from&authors
order&by&au_lname&
select&charindex('123','abc123def',2)&--返回字符串中指定表达式的起始位置
select&patindex('123','abc123def'),patindex('%123%','abc123def')&--返回表达式中某模式第一次出现的起始位置
select&quotename('abc','{'),quotename('abc')&--返回由指定字符扩住的字符串
select&reverse('abc'),reverse('上海')&--颠倒字符串顺序
select&replace('abcdefghicde','cde','xxxx')&--返回呗替换了指定子串的字符串
select&space(5),space(-2)&
--系统函数
select&host_name()&as&'host_name',host_id()&as&'host_id',user_name()&as&'user_name',user_id()&as&'user_id',db_name()&as&'db_name'
--变量的定义使用
--声明局部变量
declare&@mycounter&int
declare&@last_name&varchar(30),@fname&varchar(20),@state&varchar(2)&--一下声明多个变量
--给变量赋值
use&northwind
declare&@firstnamevariable&varchar(20),
&@regionvariable&varchar(30)
set&@firstnamevariable='anne'&--可以用set,也可以用select给变量赋值,微软推荐用set,但select在选择一个值直接赋值时很有用
set&@regionvariable&='wa'&
select&lastname,firstname,title&&--用声明并赋值过的变量构建一个Select语句并查询
from&employees
where&firstname=&@firstnamevariable&or&region=@regionvariable
--全局变量
select&@@version&&--返回数据库版本
select&@@error&&--返回最后的一次脚本错误
select&@@identity&&--返回最后的一个自动增长列的id&
--while,break,continue的使用
--首先计算所有数的平均价格,如果低于30的话进入循环让所有的price翻倍,
--里面又有个if来判断如果最大的单价还大于50的话,退出循环,否则继续循环,知道最大单价大于50就break出循环,呵呵,
--我分析的应该对吧.
while&(select&avg(price)&from&titles)&&$30&
&update&titles
&&set&price=price*2
&&select&max(price)&from&titles
&&if(select&max(price)&from&titles)&&$50
&&continue
print&'too&much&for&the&marker&to&bear'&
--事务编程经典例子
--begin&transaction是开始事务,commit&transaction是提交事务,rollback&transaction是回滚事务
--这个例子是先插入一条记录,如果出现错误的话就回滚事务,也就是取消,并直接return(返回),如果没错的话就commit&提交这个事务了哦
--上面的那个return返回可以返回一个整数值,如果这个值是0的话就是执行的时候没出错,如果出错了就是一个负数,
--这个return也可以用在存储过程中,可用用&exec&@return_status=&pro_name来获取这个值
begin&tran&mytran
&insert&into&stores(stor_id,stor_name)
&&values('333','my&books')
&insert&into&discounts(discounttype,stor_id,discount)
&&values('清仓甩卖',')
&if&@@error&&0
&&&rollback&tran&mytran
&&&print&'插入打折记录出错'
commit&tran&mytran&
--事务处理的保存点示例
--做了事务保存点后可以rollback(回滚)到指定的保存点,不至于所有的操作都不能用
select&*&from&stores
begin&transaction&testsavetran
&insert&into&stores(stor_id,stor_name)
&&values('1234','W.Z.D&Book')
&save&transaction&before_insert_data2
&insert&into&stores(stor_id,stor_name)
&&values('5678','foreat&Books')
rollback&transaction&before_insert_data2
select&*&from&stores&
--存储存储过程
if&exists(select&name&from&sysobjects&where&name=&'proc_calculate_taxes'&and&type='P')
&drop&procedure&proc_calculate_taxes
create&procedure&proc_calculate_taxes&(@p1&smallint=42,@p2&char(1),@p3&varchar(8)='char')
from&titles
--执行过程
EXECUTE&PROC_CALCULATE_TAXES&@P2='A'
引文来源&&SQL函数大全&-&苏格兰风笛&-&CSDNBlog&
1:replace&函数
第一个参数你的字符串,第二个参数你想替换的部分,第三个参数你要替换成什么
select&replace('lihan','a','b')
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-----------------------------
(所影响的行数为&1&行)
=========================================================
2:substring函数
第一个参数你的字符串,第二个是开始替换位置,第三个结束替换位置
select&substring('lihan',0,3);
(所影响的行数为&1&行)
=========================================================
3:charindex函数
第一个参数你要查找的char,第二个参数你被查找的字符串&返回参数一在参数二的位置
select&&charindex('a','lihan')
-----------&
(所影响的行数为&1&行)
===========================================================
4:ASCII函数
返回字符表达式中最左侧的字符的&ASCII&代码值。
select&ASCII('lihan')
-----------&
(所影响的行数为&1&行)
================================================================
5:nchar函数
根据&Unicode&标准的定义,返回具有指定的整数代码的&Unicode&字符。
参数是介于&0&与&65535&之间的正整数。如果指定了超出此范围的值,将返回&NULL。
select&nchar(3213)
unicode字符
(所影响的行数为&1&行)
=========================================================
6:soundex
返回一个由四个字符组成的代码&(SOUNDEX),用于评估两个字符串的相似性。
SELECT&SOUNDEX&('lihan'),&SOUNDEX&('lihon');
-----&-----&
L546&&L542
(所影响的行数为&1&行)
=========================================================
参数为介于&0&和&255&之间的整数。如果该整数表达式不在此范围内,将返回&NULL&值。
SELECT&char(125)
(所影响的行数为&1&行)
==========================================================
8:str函数
第一个参数必须为数字,第二个参数表示转化成char型占的位置,小于参数一位置返回*,大于右对齐
SELECT&str(12345,3)
(所影响的行数为&1&行)
SELECT&str(12345,12)
------------&
&&&&&&&12345
(所影响的行数为&1&行)
===========================================================
9:difference函数
返回一个整数值,指示两个字符表达式的&SOUNDEX&值之间的差异。
返回的整数是&SOUNDEX&值中相同字符的个数。返回的值从&0&到&4&不等:0&表示几乎不同或完全不同,4&表示几乎相同或完全相同。
SELECT&difference('lihan','liha')
-----------&
(所影响的行数为&1&行)
==================================================================
10:stuff函数(四个参数)
函数将字符串插入另一字符串。它在第一个字符串中从开始位置删除指定长度的字符;然后将第二个字符串插入第一个字符串的开始位置。
SELECT&stuff('lihan',2,3,'lihan')
(所影响的行数为&1&行)
===============================================================
11:left函数
返回最左边N个字符,由参数决定
select&left('lihan',4)
(所影响的行数为&1&行)
================================================================
12&right函数
返回最右边N个字符,由参数决定
select&right('lihan',4)
(所影响的行数为&1&行)
================================================================
13:replicate函数
我的认为是把参数一复制参数二次
select&replicate('lihan',4)
--------------------&
lihanlihanlihanlihan
(所影响的行数为&1&行)
================================================================
14:len函数
返回参数长度
select&len('lihan')
-----------&
(所影响的行数为&1&行)
================================================================
15:reverse函数
反转字符串
select&reverse('lihan')
(所影响的行数为&1&行)
=================================================================
16:lower和upper函数
参数大小写转化
select&lower(upper('lihan'))
--------------------&
(所影响的行数为&1&行)
====================================================================
17:ltrim和rtrim函数
删除左边空格和右面空格
select&ltrim('&&&&lihan&&&&&&&&&&&&&&&&&')
--------------------------&
lihan&&&&&&&&&&&&&&&&&
(所影响的行数为&1&行)
select&rtrim('&&&&lihan')
---------&
(所影响的行数为&1&行)
楼主去下一个《SQL语言参考资料》
这里很多的
谢谢大家了~~
回复什么SQL函数,作用有哪些_百度知道
什么SQL函数,作用有哪些
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
为你推荐:
其他类似问题
您可能关注的内容
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。SQL Server 中有包含函数吗_百度知道
SQL Server 中有包含函数吗
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
IT类认证行家
采纳数:33400
获赞数:21874
从事多年系统运维,喜欢编写各种小程序和脚本。
有的。CHARINDEX返回字符串中指定表达式的起始位置。 语法CHARINDEX ( expression1 , expression2 [ , start_location ] ) 参数expression1一个表达式,其中包含要寻找的字符的次序。expression1 是一个短字符数据类型分类的表达式。expression2一个表达式,通常是一个用于搜索指定序列的列。expression2 属于字符串数据类型分类。start_location在 expression2 中搜索 expression1 时的起始字符位置。如果没有给定 start_location,而是一个负数或零,则将从 expression2 的起始位置开始搜索。返回类型int注释如果 expression1 或 expression2 之一属于 Unicode 数据类型(nvarchar 或 nchar)而另一个不属于,则将另一个转换为 Unicode 数据类型。如果 expression1 或 expression2 之一为 NULL 值,则当数据库兼容级别为 70 或更大时,CHARINDEX 返回 NULL 值。当数据库兼容级别为 65 或更小时,CHARINDEX 仅在 expression1 和 expression2 都为 NULL 时返回 NULL 值。 如果在 expression2 内没有找到 expression1,则 CHARINDEX 返回 0。示例第一个代码示例返回序列&wonderful&在 titles 表的 notes 列中开始的位置。第二个示例使用可选的 start_location 参数从 notes 列的第五个字符开始寻找&wonderful&。第三个示例显示了当 expression2 内找不到 expression1 时的结果集。USE pubsGOSELECT CHARINDEX('wonderful', notes)FROM titlesWHERE title_id = 'TC3218'GO-- Use the optional start_location parameter to start searching -- for wonderful starting with the fifth character in the notes-- column.USE pubsGOSELECT CHARINDEX('wonderful', notes, 5)FROM titlesWHERE title_id = 'TC3218'GO下面是第一个查询和第二个查询的结果集:----------- 46
(1 row(s) affected)USE pubsGOSELECT CHARINDEX('wondrous', notes)FROM titlesWHERE title_id='TC3218'GO下面是结果集。----------- 0
(1 row(s) affected)PATINDEX返回指定表达式中某模式第一次出现的起始位置;如果在全部有效的文本和字符数据类型中没有找到该模式,则返回零。语法PATINDEX ( '%pattern%' , expression ) 参数pattern一个字符串。可以使用通配符,但 pattern 之前和之后必须有 % 字符(搜索第一个和最后一个字符时除外)。pattern 是短字符数据类型类别的表达式。expression一个表达式,通常为要在其中搜索指定模式的列,expression 为字符串数据类型类别。返回类型int注释PATINDEX 对 text 数据类型很有用;除 IS NULL、IS NOT NULL 和 LIKE(这些是 WHERE 子句中对 text 类型有效的仅有的其它比较运算)外,PATINDEX 也可用于 WHERE 子句中。如果 pattern 或 expression 为 NULL,则当数据库的兼容级别为 70 时 PATINDEX 返回 NULL;如果数据库兼容级别为 65 或更靠前,则仅当 pattern 和 expression 同时为 NULL 时,PATINDEX 返回 NULL。示例A. 在 PATINDEX 中使用模式本示例查找模式&wonderful&在 titles 表中 notes 列的某一特定行中的开始位置。USE pubsGOSELECT PATINDEX('%wonderful%', notes)FROM titlesWHERE title_id = 'TC3218'GO下面是结果集:----------- 46
(1 row(s) affected)如果未通过 WHERE 子句限制要搜索的行,查询将返回表中的所有行,对在其中找到该模式的所有行报告非零值,对在其中未找到该模式的所有行报告零值。B. 在 PATINDEX 中使用通配符本示例使用通配符查找模式&won_erful&在 titles 表中 notes 列的某一特定行中的开始位置,其中下划线为代表任何字符的通配符。USE pubsGOSELECT PATINDEX('%won_erful%', notes)FROM titlesWHERE title_id = 'TC3218'GO下面是结果集:------------46(1 row(s) affected)如果没有限制要搜索的行,查询将返回表中的所有行,对在其中找到该模式的所有行报告非零值。
为你推荐:
其他类似问题
您可能关注的内容
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果。这些要求包括:执行计算与数学运算、转换数据、解析数值、组合值和聚合一个范围内的值等。
下表给出了T-SQL函数的类别和描述。
执行的操作是将多个值合并为一个值。例如&COUNT、SUM、MIN&和&MAX。
是一种标量函数,可返回有关配置设置的信息。
将值从一种数据类型转换为另一种。
支持加密、解密、数字签名和数字签名验证。
返回有关游标状态的信息。
日期和时间函数
可以更改日期和时间的值。
执行三角、几何和其他数字运算。
元数据函数
返回数据库和数据库对象的属性信息。
是一种非确定性函数,可以返回分区中每一行的排名值。
返回可在&Transact-SQL&语句中表引用所在位置使用的行集。
返回有关用户和角色的信息。
字符串函数
可更改&char、varchar、nchar、nvarchar、binary&和&varbinary&的值。
对系统级的各种选项和对象进行操作或报告。
系统统计函数
返回有关&SQL&Server&性能的信息。
文本和图像函数
可更改&text&和&image&的值。
函数的组成
函数的目标是返回一个值。大多数函数都返回一个标量值(scalar&value),标量值代表一个数据单元或一个简单值。实际上,函数可以返回任何数据类型,包括表、游标等可返回完整的多行结果集的类型。本章不准备讨论到这个深度,第12章将讲解如何创建和使用用户自定义函数,以返回更复杂的数据。
函数己经存在很长时间了,它的历史比SQL还要长。在几乎所有的编程语言中,函数调用的方式都是相同的:
Result=Function()
在T-SQL中,一般用SELECT语句来返回值。如果需要从查询中返回一个值,就可以把SELECT当成输出运算符,而不用使用等号:
SELECT&Function()
对于SQL函数而言,参数表示输入变量或者值的占位符。函数可以有任意个参数,有些参数是必须的,而有些参数是可选的。可选参数通常被置于以逗号隔开的参数表的末尾,以便于在函数调用中去除不需要的参数。
在SQL&Server在线图书或者在线帮助系统中,函数的可选参数用方括号表示。在下列的CONVERT()函数例子中,数据类型的length和style参数是可选的:
CONVERT&(data-type&[(length)],&expression[,style])
可将它简化为如下形式,因为现在不讨论如何使用数据类型:
CONVERT(date_type,&expression[,style])
根据上面的定义,CONVERT()函数可接受2个或3个参数。因此,下列两个例子都是正确的:
SELECT&CONVERT(Varchar(20),&GETDATE())
SELECT&CONVERT(Varchar(20),&GETDATE(),&101)
这个函数的第一个参数是数据类型Varchar(20),第2个参数是另一个函数GETDATE()。GETDATE()函数用datetime数据类型将返回当前的系统日期和时间。第2条语句中的第3个参数决定了日期的样式。这个例子中的101指以mm/dd/yyyy格式返回日期。本章后面将详细介绍GETDATE()函数。即使函数不带参数或者不需要参数,调用这个函数时也需要写上一对括号,例如GETDATE()函数。注意在书中使用函数名引用函数时,一定要包含括号,因为这是一种标准形式。
确定性函数
由于数据库引擎的内部工作机制,SQL&Server必须根据所谓的确定性,将函数分成两个不同的组。这不是一种新时代的信仰,只和能否根据其输入参数或执行对函数输出结果进行预测有关。如果函数的输出只与输入参数的值相关,而与其他外部因素无关,这个函数就是确定性函数。如果函数的输出基于环境条件,或者产生随机或者依赖结果的算法,这个函数就是非确定性的。例如,GETDATE()函数是非确定性函数,因为它不会两次返回相同的值。为什么要把看起来简单的事弄得如此复杂呢?主要原因是非确定性函数与全局变量不能在一些数据库编程对象中使用(如用户自定义函数)。部分原因是SQL&Server缓存与预编译可执行对象的方式。例如,即席查询可以使用任何函数,不过如果打算构建先进的、可重用的编程对象,理解这种区别很重要。
以下这些函数是确定性的:
l&AVG()(所有的聚合函数都是确定性的)
l&CONVERT()
l&DATEADD()
l&DATEDIFF()
l&SUBSTRING()
以下这些函数与变量是非确定性的:
l&GETDATE()
l&@@SERVICENAME
l&CURSORSTATUS()
在函数中使用用户变量
变量既可用于输入,也可用于输出。在T-SQL中,用户变量以@符号开头,用于声明为特定的数据类型。可以使用SET或者SELECT语句给变量赋值。以下的例子用于将一个int类型的变量@MyNumber传递给SQRT()函数:
DECLARE&@MyNumber&int
SET&@MyNumber=144&
SELECT&SQRT(@MyNumber)
结果是12,即144的平方根。
用SET给变量赋值
以下例子使用另一个int型的变量@MyResult,来捕获该函数的返回值。这个技术类似于过程式编程语言中的函数调用样式,即把SET语句和一个表达式结合起来,给参数赋值:
DECLARE&@MyNumber&int,&@MyResult&int
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&@MyNumber1&int,&@MyNumber2&int,
@MyResult1&int,&@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
&上面的例子首先声明了4个变量,然后用两个SELECT语句给这些变量赋值,而不是用4个SELECT语句给变量赋值。虽然这些技术在功能上是相同的,但是在服务器的资源耗费上,用一个SELECT语句给多个变量赋值一般比用多个SET命令的效率要高。将一个甚至多个值选进参数的限制是,对变量的赋值不能和数据检索操作同时进行。这就是上面的例子使用SELECT语句来填充变量,而用另外一个SELECT语句来检索变量中数据的原因。例如,下面的脚本就不能工作:
DECLARE&@RestockName&varchar(50)&
SELECT&ProductId&
&&&&&&,@RestockName&=&Name&+&':'&+&ProductNumber&
FROM&Production.Product
&这个脚本会产生如下错误:
消息141,级别15,状态1,第2&行
向变量赋值的SELECT&语句不能与数据检索操作结合使用。
在查询中使用函数
函数经常和查询表达式结合使用来修改列值。这只需将列名作为参数传递给函数即可,随后函数将引用插入到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()函数用于返回一组数值中所有非空数值的平均值。例如,表6-2包含了体操成绩。
体操运动员
对这些数据执行以下查询:
SELECT&AVG(Score)
结果是8.965。
如果有三个女孩没有完成一些项目,在表中没有记录成绩,则可用NULL来表示(见表6-3)。
体操运动员
create&table&#GymEvent(Player&varchar(10),[Subject]&nvarchar(5),Scoredecimal(4,2))
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)
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所示。
IntegerColumn(int类型)
VarCharColumn(varChar类型)
create&table&#Temp(IntegerColumn&int,VarCharColumn&varchar(10))
insert&into&#Temp&values(2,'2')
insert&into&#Temp&values(4,'4')
insert&into&#Temp&values(12,'12')
insert&into&#Temp&values(19,'19')
drop&table&#Temp
如果分别调用MIN()与MAX()函数将会返回什么值呢?
select&MIN(IntegerColumn),MAX(IntegerColumn)&from&#Temp
select&MIN(VarCharColumn),MAX(VarCharColumn)&from&#Temp
因为VarCharColumn中值的存储类型为字符类型,而不是数字,所以结果以每个字符的ASCII值为顺序从左到右排序。这就是12比其他值小、而4比其他值大的原因。
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
SELECT&@@ERROR
&在成功检索@@ERROR的值后,@@ERROR的值将返回0,因为@@ERROR只保存了上次执行的语句的错误代码。如果希望检索更多的错误信息,可以使用如下脚本从sysmessages视图中得到:
SELECT&5&/&0
SELECT&*&FROM&master.dbo.sysmessages&WHERE&error&=&@@ERROR
&本节的后面部分内容将说明如何通过使用错误函数来更高效地返回错误数据。
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.
Обнаружена&ошибка:&деление&на&ноль.
Erro&de&divis?o&por&zero.
發現除以零的錯誤。
0으?&???&???&??????.
遇到以零作除数错误。
除了美国英语之外,SQL&Server还默认安装了其他语言。每种语言专用的错误消息都有一个语言标识符(mslangid),对应于syslanguages表中的一种语言,如下图所示。
属性名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变量
这个变量用于记录从打开当前连接开始发生的总错误次数。和@@ERROR变量一样,它对每个用户会话是唯一的,并将在连接关闭时被重置。
@@TOTAL_READ变量
这个变量记录从打开当前连接时开始计算的磁盘读取总数。DBA使用这个变量查看磁盘读取活动的情况。
@@VERSION变量
这个变量包含当前SQL&Server实例的完整版本信息。
SELECT&@@VERSION&
比如,对于运行在Windows&7上的SQL&Server&2008开发版实例,以上脚本能够返回如下信息:
Microsoft&SQL&Server&2008&(RTM)&-&10.0.1600.22&(Intel&X86)&&&Jul&9&:34&&&Copyright&(c)&&Microsoft&Corporation&Enterprise&Edition&on&Windows&NT&6.1&&X86&&(Build&7600:&)
实际的版本号是一个简单的整型值,它在微软公司内部使用。而发行的产品可能有其他的商标名。在本例中,SQL&Server&2005的版本是9,SQL&Server&2008的版本是10。Windows&XP&Professional显示为Windows&NT&5.l版,而Vista显示为6.0版。构建号用于内部控制,反映beta版和预览版以及正式发行后的补丁包的变化。
前面学习了如何使用@@ERROR全局变量来检索错误信息。而返回所有错误数据的更好方法是使用错误函数。这些函数返回的信息可以存储在错误跟踪表中,以供错误审核。错误函数嵌套在错误处理例程中。第11章将详细讨论错误处理,其实通过使用嵌套在TRY和END&TRY语句中的代码块,后跟一个放在CATCH和END&CATCH语句中的代码块就可以实现错误处理。
--Try&to&do&something&
BEGIN&TRY&
&&&SELECT&5&/&0&
--If&it&causes&an&error,&do&this&
BEGIN&CATCH&
&&&PRINT&ERROR_MESSAGE()&
所谓的错误捕获,其实就是这个意思。如果运行上面的示例,将不会出现可识别的错误,因为错误将被捕获并在CATCH语句块中进行处理。在编写错误处理代码时,SQL程序员必须把这些代码放在会引发系统错误的catch代码块中。
下列几个错误函数用于返回错误的特定信息:
ERROR_MESSAGE()
返回错误的描述。
ERROR_NUMBER()
返回错误号。
ERROR_SEVERITY()
返回错误的严重级别。错误的严重级别是一个从0到25的整数。
ERROR_STATE()
返回错误的状态号。错误状态是一个整数,可以唯一地表示系统错误的原因。
ERROR_LINE()
返回例程中导致出错的行号。
ERROR_PROCEDURE()
返回发生错误的存储过程名或触发器名。
下表简要描述了严重级别。
严&重&级&别
信息性消息。不会引发系统错误
用户可以更正的错误,例如违反了外键或主键规则
非致命的、不重要的资源错误
非致命的内部错误
致命的、不重要的资源错误
当前进程中的致命错误
所有进程中的致命数据库错误
致命的表完整性错误
致命的数据库完整性错误
致命的硬件错误
致命的系统错误
下面脚本使用T-SQL的内置错误处理功能,来捕获和输出遇到除0错误时返回的错误数据。SELECT命令的结果将显示在Management&Studio的消息选项卡中。
--Try&to&do&something&
BEGIN&TRY&
&&&&SELECT&5&/&0&
--If&it&causes&an&error,&do&this&
BEGIN&CATCH&
&&&&SELECT&ERROR_MESSAGE(),ERROR_NUMBER(),ERROR_SEVERITY(),
&&&&&&&ERROR_STATE(),ERROR_LINE(),ERROR_PROCEDURE()
可以看出,执行这个脚本会在消息选项卡中返回有关错误的更多详细信息,而不仅仅是错误号本身。
ERROR_PROCEDURE()函数不能返回过程名,因为错误是在ad-hoc查询中生成的。
数据类型转换可以通过CAST()和CONVERT()函数来实现。大多数情况下,这两个函数是重叠的,它们反映了SQL语言的演化历史。这两个函数的功能相似,不过它们的语法不同。虽然并非所有类型的值都能转变为其他数据类型,但总的来说,任何可以转换的值都可以用简单的函数实现转换。
CAST()函数
CAST()函数的参数是一个表达式,它包括用AS关键字分隔的源值和目标数据类型。以下例子用于将文本字符串'123'转换为整型:
SELECT&CAST('123'&AS&int)
返回值是整型&#。如果试图将一个代表小数的字符串转换为整型值,又会出现什么情况呢?
SELECT&CAST('123.4'&AS&int)
CAST()函数和CONVERT()函数都不能执行四舍五入或截断操作。由于123.4不能用int数据类型来表示,所以对这个函数调用将产生一个错误:
Server:&Msg&245,&Level&16,&State&1,&Line&1&
Syntax&error&converting&the&varchar&value
'123.4'&to&a&column&of&data&type&int.
在将varchar&&#2'&转换成数据类型int&时失败。
要返回一个合法的数值,就必须使用能处理这个值的数据类型。对于这个例子,存在多个可用的数据类型。如果通过CAST()函数将这个值转换为decimal类型,需要首先定义decimal值的精度与小数位数。在本例中,精度与小数位数分别为9与2。精度是总的数字位数,包括小数点左边和右边位数的总和。而小数位数是小数点右边的位数。这表示本例能够支持的最大的整数值是9999999,而最小的小数是0.01。
SELECT&CAST('123.4'&AS&decimal(9,2))&
decimal数据类型在结果网格中将显示有效小数位:123.40
精度和小数位数的默认值分别是18与0。如果在decimal类型中不提供这两个值,SQL&Server将截断数字的小数部分,而不会产生错误。
SELECT&CAST('123.4'&AS&decimal)&
结果是一个整数值:123
在表的数据中转换数据类型是很简单的。下面的例子使用Product表,首先执行如下查询:
SELECT&ProductNumber,&ProductLine,&ProductModelID
FROM&Production.Product
WHERE&ProductSubcategoryID&&&4
假定产品经理已经创建了一个系统,用于唯一地标识生产出来的每辆自行车,以便跟踪其型号、类型和类别。他决定合并产品号、产品生产线标识符、产品型号标识符和一个顺序号,为生产出来的每辆自行车创建一个唯一的序列号。在这个过程的第一步,他要求提供包括除顺序号之外的所有属性的所有可能产品的根标识符。
如果使用下面的表达式,就不能得到希望的结果,如图6-2所示。
SELECT&ProductNumber
&&&&&&&+&'-'&&
&&&&&&&+&ProductLine
&&&&&&&+&'-'&&
&&&&&&&+&ProductModelID&AS&BikeSerialNum
FROM&Production.Product
WHERE&ProductSubcategoryID&&&4
消息245,级别16,状态1,第1&行
在将nvarchar&值'BK-R93R-62-R&-'&转换成数据类型int&时失败。
我们没有得到希望的结果,而得到了有点奇怪的错误消息:请把nvarchar值转换为int。因为之前我们没有要求进行任何转换,所以这个错误很奇怪。这个查询的问题在于我们试图利用第一个连接符来连接字符值ProductNumber,利用第二个连接符连接另一个字符值ProductLine,最后连接的是ProductModelID字符值(它是一个整数)。
查询引擎会把连接符当成一个数学运算符,而不是一个字符。不管结果是什么,都需要更正这个表达式,以确保使用正确的数据类型。以下表达式执行了必要的类型转换,返回如图6-3所示的结果:
SELECT&ProductNumber&&
&&&&&&&+&'-'&&
&&&&&&&+&ProductLine&&
&&&&&&&+&'-'&&
&&&&&&&+&CAST(ProductModelID&AS&char(4))&AS&BikeSerialNum&
FROM&Production.Product&
WHERE&ProductSubcategoryID&&&4
如果把整型值转换为字符类型就不会增加多余的空格了。查询引擎将把这些值用加号和连接符组合在一起,进行字符串连接运算,而不是和前面的数值进行加法或者减法运算了。
CONVERT()函数
对于简单类型转换,CONVERT()函数和CAST()函数的功能相同,只是语法不同。CAST()函数一般更容易使用,其功能也更简单。CONVERT()函数的优点是可以格式化日期和数值,它需要两个参数:第1个是目标数据类型,第2个是源数据。以下的两个例子和上一节的例子类似:
SELECT&CONVERT(int,&'123')&
SELECT&CONVERT(decimal(9,2),&'123.4')
CONVERT()函数还具有一些改进的功能,它可以返回经过格式化的字符串值,且可以把日期值格式化成很多形式。有28种预定义的符合各种国际和特殊要求的日期与时间输出格式。下表列出了这些日期格式。
如果&expression&为&date&或&time&数据类型,则&style&可以为下表中显示的值之一。其他值作为&0&进行处理。SQL&Server&使用科威特算法来支持阿拉伯样式的日期格式。
输入/输出&(3)
0&或&100&(1,&2)
mon&dd&yyyy&hh:miAM(或&PM)
mm/dd/yyyy
dd/mm/yyyy
mon&dd,&yy
9&或&109&(1,&2)
默认设置&+&毫秒
mon&dd&yyyy&hh:mi:ss:mmmAM(或&PM)
13&或&113&(1,&2)
欧洲默认设置&+&毫秒
dd&mon&yyyy&hh:mi:ss:mmm(24h)
hh:mi:ss:mmm(24h)
20&或&120&(2)
yyyy-mm-dd&hh:mi:ss(24h)
21&或&121&(2)
ODBC&规范(带毫秒)
yyyy-mm-dd&hh:mi:ss.mmm(24h)
yyyy-mm-ddThh:mi:ss.mmm(无空格)
带时区&Z&的&ISO8601。
yyyy-mm-ddThh:mi:ss.mmmZ
(无空格)
130&(1,&2)
dd&mon&yyyy&hh:mi:ss:mmmAM
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&时输入;转换为字符数据时输出。
4.&&&&&&&&&为用于&XML&而设计。对于从&datetime&或&smalldatetime&到字符数据的转换,其输出格式如上一个表所述。
5.&&&&&&&&&回历是有多种变体的日历系统。SQL&Server&使用科威特算法。
a)&&&&&&&&&默认情况下,SQL&Server&基于截止年份&2049&年来解释两位数的年份。换言之,就是将两位数的年份&49&解释为&2049,将两位数的年份&50&解释为&1950。许多客户端应用程序(如基于自动化对象的应用程序)都使用截止年份&2030&年。SQL&Server&提供了“两位数年份截止”配置选项,可通过此选项更改&SQL&Server&使用的截止年份,从而对日期进行一致处理。建议您指定四位数年份。
6.&&&&&&&&&仅支持从字符数据转换为&datetime&或&smalldatetime。仅表示日期或时间成分的字符数据转换为&datetime&或&smalldatetime&数据类型时,未指定的时间成分设置为00:00:00.000,未指定的日期成分设置为&。
7.&&&&&&&&&使用可选的时间区域指示符&(Z)&更便于将具有时区信息的&XML&datetime&值映射到没有时区的&SQL&Server&datetime&值。Z&是时区&UTC-0&的指示符。其他时区则以&+&或&-&方向的&HH:MM&偏移量来指示。例如:T23:45:12-08:00。
从&smalldatetime&转换为字符数据时,包含秒或毫秒的样式将在这些位置上显示零。使用相应的&char&或&varchar&数据类型长度从&datetime&或&smalldatetime&值转换时,可截断不需要的日期部分。
从样式包含时间的字符数据转换为&datetimeoffset&时,将在结果末尾追加时区偏移量。
这个函数的第三个参数是可选的,该参数用于接收格式代码整型值。表中的例子用于对DateTime数据类型进行转换。在转换SmallDateTime数据类型时,格式不变,但一些元素会显示为0,因为该数据类型不支持毫秒。以下的脚本例子将输出格式化的日期:
SELECT&'Default&Date:'&+&CONVERT(Varchar(50),&GETDATE(),&100)&
Default&Date:&Apr&25&PM&
SELECT&'US&Date:'&+&CONVERT(Varchar(50),&GETDATE(),&101)&
US&Date:&04/25/2005&
SELECT&'ANSI&Date:'&+&CONVERT(Varchar(50),&GETDATE(),&103)&
ANSI&Date:&&
SELECT&'UK/French&Date:'&+CONVERT&(Varchar(50),&GETDATE(),&103)&
UK/French&Date:&25/04/2OO5&
SELECT&'German&Date:'&+&CONVERT(Varchar(50),&GETDATE(),&104)&
German&Date:&25.04.2005
格式代码0,1和2也可用于数字类型,它们对小数与千位分隔符格式产生影响。而不同的数据类型所受的影响是不一样的。一般来说,使用格式代码0(或者不指定这个参数的值),将返回该数据类型最惯用的格式。使用1或者2通常显示更为详细或者更精确的值。以下例子使用格式代码0:
DECLARE&@Num&Money&
SET&@Num&=&1234.56&
SELECT&CONVERT(varchar(50),&@Num,&0)
返回结果如下:
使用值1则返回如下结果:
使用值2则返回如下结果:
以下例子和上例相同,但是使用Float类型:
DECLARE&@Num&float
SET&@Num&=&1234.56&
SELECT&CONVERT(varchar(50),&@Num,&2)
使用值0不会改变所提供的格式,但是使用&#将返回以科学计数法表示的数字,后者使用了15位小数:
1.00e+003
这是一个将数字转换为字符串的快捷函数。这个函数有3个参数:数值、总长度和小数位数。如果数字的整数位数和小数位数(要加上小数点占用的一个字符)的总和小于总长度,对结果中左边的字符将用空格填充。在下面第1个例子中,包括小数点在内一共是5个字符。结果显示在网格中,显然左边的空格被填充了。这个调用指定,总长度为8个字符,小数位为4位:
SELECT&STR(123.4,&8,&4)&
结果值的右边以0填充:123.4000。
下面给函数传递了一个10字符的值,并指定结果包含8个字符,有4个小数位:
SELECT&STR(123.456789,&8,&4)&
只有将这个结果截断才能符合要求。STR()函数对最后一位进行四舍五入:123.4568。现在,如果为函数传递数字1,并指定结果包含6个字符,有4个小数位,STR()函数将用0补足右边的空位:
SELECT&STR(1,&6,&4)&
然而,如果指定的总长度大于整数位数、小数点和小数位数之和,结果值的左边将用空格补齐:
SELECT&STR(1,&6,&4)&
SELECT&STR(1,&12,&4)&
----------&&&1.0000
游标函数与变量
游标可以处理多行数据,在过程循环中一次访问一行。和基于集合的高效操作相比,这个功能对系统资源的消耗更大。可以用一个函数和两个全局变量来管理游标操作。
CURSOR_STATUS()函数
这个函数返回一个整型值,表示传递给这个函数的游标类型变量的状态。有很多不同类型的游标会影响这个函数的操作。为简单起见,下表列出了这个函数的常见返回值。
返&回&值
游标包含一行或多行(动态游标包含0行或者多行)
游标不包含行
游标已关闭
游标未分配
游标不存在
@@CURSOR_ROWS全局变量
这个变量是一个整型值,表示在当前连接中打开的游标中的行数。根据游标类型,这个值也能不代表结果集中的实际行数。
@@FETCH_STATUS全局变量
这个变量是一个标记,用于表示当前游标指针的状态。这个变量主要用来判断某行是否存在,以及在执行了FETCH&NEXT语句后,是否已执行到结果集的尾部。打开游标时,@@FETCH_STATUS变量值为-1。一旦把第一个值放在游标中,@@FETCH_STATUS变量值就变成0。当不再把更多的行放在游标中时,该变量的值将变回-1。
这些函数可以操作DateTime与SmallDateTime类型的值。有些函数可用于解析日期值的日期与时间部分,有些函数可用于比较、操纵日期/时间值。日期数据类型的区别如下表所示。
12:35:29.&1234567
smalldatetime
&12:35:29.123
&12:35:29.&1234567
datetimeoffset
&12:35:29.1234567&+12:15
DATEADD()函数
DATEADD()函数用于在日期/时间值上加上日期单位间隔。比如,要得到日起90天后的日期,可以使用下列语句:
SELECT&DATEADD(DAY,&90,&'4-29-2007')
结果:&&00:00:00.000
可以把下表的值作为时间间隔参数传递给DATEADD()函数。
millisecond
microsecond
nanosecond
在下面列出的例子中,我们使用和上一个例子一样的日期,并且在这些例子中还包含了时间数据。每个操作的结果将显示在查询的下一行中。
SELECT&DATEADD(YEAR,&18,&'4-29-&AM')&
&10:30:00.000
SELECT&DATEADD(YY,&-18,&'4-29-&AM')&
&10:30:00.000
9000秒后:
SELECT&DATEADD(SECOND,&9000,&'4-29-&AM')&
&13:00:00.000
9000000毫秒前:
SELECT&DATEADD(MS,&-9000000,&'4-29-&AM')&
&08:00:00.000
可以将CONVERT()函数和DATEADD()函数组合在一起,来对日9个月前的日期值进行格式化。
SELECT&CONVERT(varchar(20),&DATEADD(M,&-9,&'9-8-1989'),&101)&
12/08/1988
这将返回一个可变长度的字符值,比前面例子结果中的默认日期更易容易理解。这是一个函数嵌套调用,DATEADD()函数的返回值(一个DateTime类型的值)被作为值参数传递给CONVERT()函数。
DATEDIFF()函数
DATEADD()和DATEDIFF()函数可以看作一对表兄弟,有点像乘法与除法。在等式的两端有4个元素:起始日期、时间间隔(datepart)、差值和最终日期。如果已知其中的三个值,就可以求出第4个值。如果在DATEADD()函数中使用起始日期、一个整型值和一个时间间隔,就可返回与起始日期相关的最终日期值。如果提供了起始日期、时间间隔和最终日期,DATEDIFF()函数就可以返回差值。
为了说明这一点,我们选择任意两个日期与一个时间间隔作为参数。这个函数将以所提供的时间间隔为单位返回两个日期之间的差值。要知道日和日之间差了几个月,可编写如下查询代码:
SELECT&DATEDIFF(MONTH,&'9-8-1989',&'10-17-1991')&
结果是25个月。如果以日期为单位呢?
SELECT&DATEDIFF(DAY,&'9-8-1989',&'10-17-1991')&
结果是769天。
日和日之间差几个星期?
SELECT&DATEDIFF(WEEK,&'7-2-1996',&'8-4-1997')&
57星期。甚至可以算出自己的年龄是多少秒:
DECLARE&@MyBirthDate&datetime&
SET&@MyBirthDate&=&'7-16-1962'
SELECT&DATEDIFF(SS,&@MyBirthDate,&GETDATE())
结果显示有些人已经活了15亿秒了!
可以将列名作为参数,把这个函数用在查询中。首先建立一个简单的表,其中包含一些人的姓名和生日:
SELECT&c.FirstName
&&&&,c.LastName
&&&&,e.BirthDate
&&&&,DATEDIFF(YEAR,&e.BirthDate,&GETDATE())&AS&ApproximateAge
FROM&HumanResources.Employee&as&e&inner&join
&&&&Person.Contact&as&c&on&e.ContactID&=&c.ContactID
order&by&c.LastName
下图显示了结果:
初看起来结果是对的,但存在的问题是年龄值没有精确到日。比如,根据表中的数据,Nancy的生日是12月21日,他今年将庆祝第32个生日(这个查询在2010年8月运行)。如果依据上述计算结果来确定他的年龄何时变化,就应在一月份的某天给他发生日卡片,这比实际日期提前了11个月。
除非用更小的时间单位来计算这些日期的差,否则结果只在雇员实际生日的一年以内是精确的。以下例子将用差值除以一年(包括闰年)的天数,并将结果值转换为int类型,进行取整运算,而不是四舍五入。
SELECT&c.FirstName
&&&&,c.LastName
&&&&,e.BirthDate
&&&&,DATEDIFF(YEAR,&e.BirthDate,&GETDATE())&AS&ApproximateAge
&&&&&,CONVERT(int,&DATEDIFF(DAY,&e.BirthDate,&GETDATE())/365)&AS&Age
FROM&HumanResources.Employee&as&e&inner&join
&&&&Person.Contact&as&c&on&e.ContactID&=&c.ContactID
order&by&c.LastName
比较这次的结果和上一个例子的结果,看看有什么不同。
可以看到,Nancy是31岁,其他雇员的年龄也精确到了天。表中的BirthDate列存储雇员的生日,并以午夜(00:00:00AM)为界,这是一天中的第一秒。GETDATE()函数返回当前的时间与日期。当前两个日期相差约8小时(写这段文字时是上午8点)。如果希望这个计算更精确,就需要在当前日期的午夜把GETDATE()函数的结果转换为datetime类型。
DATEPART()与DATENAME()函数
这两个函数用于返回datetime或者shortdatetime值的日期部分。DATEPART()函数返回一个整型值;DATENAME()函数返回一个包含描述性文字的字符串。比如,将日期4-29-1988传递给DATEPART()函数,如指定返回月份值,则返回数字4:
SELECT&DATEPART(MONTH,&'4-29-1988')&
而使用相同的参数,DATENAME()函数返回04(这取决于你的机器的本地语言,如果是英文版,那么将返回April):
&SELECT&DATENAME(MONTH,&'4-29-1988')
这两个函数都接收和DATEADD()函数一样的时间间隔参数常量。
GETDATE()与GETUTCDATE()函数
这两个函数都用于返回datetime类型的当前日期与时间。GETUTCDATE()函数使用服务器上的时区设置来求出UTC时间,这和格林威治标准时间或飞行员所说的&祖鲁时&(Zulu&Time)是一样的。两个函数都能精确到3.33毫秒。
SELECT&GETDATE()&
SELECT&GETUTCDATE()
执行这两个函数,都将返回未经格式化的结果,见下图:
我在北京,和UTC时间相差8个小时,和标准时间相差9个小时。可以使用如下DATEDIFF()函数来验证这个时间差值:
&SELECT&DATEDIFF(HOUR,&GETDATE(),&GETUTCDATE())
SYSDATETIME()和SYSUTCDATETIME()函数
这两个SQL&Server&2008函数等价于GETDATE()和GETUTCDATE()函数,但不是返回datetime数据类型的结果,而是返回SQL&Server&2008新的datetime2数据类型的结果,该数据类型可以精确到100纳秒,当然这取决于服务器安装的硬件。
SELECT&SYSDATETIME()&
SELECT&SYSUTCDATETIME()
DAY()、MONTH()和YEAR()函数
这三个函数分别返回以整数表示的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
下一节将讨论字符串操纵函数,并使用相似的技术来构建一个紧凑的定制时间戳。
字符串操纵函数
字符串函数可以解析、替换、操纵字符型值。在处理原始字符数据时,最大的挑战之一是如何可靠地提取出有意义的信息。有很多字符串解析函数可用于标识和解析子字符串(一个大字符型值的一部分)。我们一直在做这种事,在我们阅读文件、发票或者书面材料时,就会本能地标识、分离出有意义的信息片段。这个过程的自动化非常困难,即使是处理不太复杂的文本,也很困难。这些函数包含几乎所有必需的工具,而挑战在于如何找出最简单、最高效的方法。
ASCII()、CHAR()、UNICODE()和NCHAR()函数
这四个函数是相似的,它们都可以在字符和字符的标准数字表示之间转换。美国标准信息交换码(American&Standard&Code&for&Information&Interchange,ASCII)标准字符集包含128个字母、数字和标点符号。这个字符集是IBM&PC体系结构的基础,虽然有些字符现在看来已经很古老了,但还是被保留了下来,且仍是现代计算机技术的核心。如果在计算机上使用英语,则键盘上的每个字符都是用ASCII码表示的。这对说英语(至少以英语打字)的计算机用户来说是有利的,但是其他人又该怎么办呢?
在计算机的发展过程中,&ASCII字符集发布没多长时间便过时了。人们很快将它扩展成为256个字符的ANSI字符集,一个字符用一个字节来保存。这个扩展的字符列表满足了许多其他用户的需求,可以支持主要的欧洲语言字符,不过仍是美国标准(由美国国家标准学会持有),仍建立在最初的英语字符集的基础上。为了支持所有可印刷的语言,人们制订了Unicode标准,它支持多种语言特定的字符集。每个Unicode字符需要2个字节的存储空间,是ASCII与ANSI字符的两倍。但是使用2个字就可以表示超过65&000个不同的字符,完全能够支持东欧和亚洲字符。SQL&Server同时支持ASCII与Unicode两种标准。
ASCII()和CHAR()是两个基于ASCII的函数,这两个函数可将计算机上应用的每个字符表示为数字。要确定代表一个字符的数字是什么,就应给ASCII()函数传送只包含一个字符的字符串,如下:
SELECT&ASCII('A')&
结果是65。
如要将一个已知数字转换为字符,又该怎么办?使用CHAR()函数即可:
SELECT&CHAR(65)&
结果是字母A。
要得到完整的ASCII字符值列表,可以对一个临时表填充从0到127的数字,然后调用CHAR()函数返回相应的字符。为了节省空间,我们对以下这个脚本进行了删节,但包含整个结果集,并以多栏格式给出。
--&创建一个临时表来保存ASCII码:&
Create&Table&#ASCIIVals&(ASCIIValue&smallint)&
--&插入数字0&-&127&到临时表中:
declare&@Number&int
set&@Number&=&0
while(@Number&&&128)
&&&&&&&Insert&Into&#ASCIIVals&(ASCIIValue)&Select&@Number
&&&&&&&set&@Number&=&@Number&+&1
--&查询所有的整型数字与其对应的ASCII码:&
SELECT&ASCIIValue,&CHAR(ASCIIValue)&AS&Character&FROM&#ASCIIVals
drop&table&#ASCIIVals
表6-12是以多栏网格重新格式化的结果集。需要注意的是这里将不可印刷的控制字符以方括号表示。由于许多因素限制,如所安装的字体或语言不同,下表的显示可能会有稍许差异。
UNICODE()函数是ASCII()的Unicode等价函数,NCHAR()函数和CHAR()函数的功能相同,只不过NCHAR()是用于Unicode字符的。SQL&Server的nchar与nvarchar类型能存储任何Unicode字符,可以和这两个函数一起使用。对于特别大的值,ntext类型和nvarchar(max)类型也支持Unicode字符。
要返回扩展字符编码集中的字符,可以将字符编码传递给NCHAR()函数:
SELECT&NCHAR(220)&
返回字母ü。
SELECT&NCHAR(233)&
返回带重音符号的小写e:é。
SELECT&NCHAR(241)&
返回西班牙语的&enya&,或者带有发音符号的n:。
当然,ASCII标准也支持所有的欧洲字符,所以使用CHAR()函数也可以返回这些扩展字符。如果对256~65536之间的值使用CHAR()函数,返回值就很有趣了。例如,下面的查询返回希腊字符Ω:
SELECT&NCHAR(433)&
下面的查询返回西里尔字母Ya(Я)。
SELECT&NCHAR(1071)
CHARINDEX()和PATINDEX()函数
CHARINDEX()是原始的SQL函数,用于寻找在一个字符串中某子字符串第一次出现的位置。如函数名所示,这个函数返回一个整型值,表示某子字符串的第一个字符在整个字符串中的位置索引。以下脚本用于在字符串Washington中寻找子字符串sh的出现位置:
SELECT&CHARINDEX('sh',&'Washington')&
返回的结果是3,表明s是字符串Washington中的第3个字符。这说明CHARINDEX函数匹配字符的索引是从1开始的。如果没有匹配到任何结果,函数将返回0。在这个例子中使用两个字符作为子字符串并没有特别意义,但是如果字符串包含多个s字符,就有意义了。
PATINDEX()函数和CHARINDEXO函数类似,它执行相同的操作,但方法稍许不同,该函数增加了对通配符(即Like运算符中使用的字符)的支持。顾名思义,它将返回一个字符模式的索引。这个函数也可以和ntext、nchar(max)和nvarchar(max)等大字符类型一起使用。注意,如果和这些大字符类型一起使用,PATINDEX()函数将返回bigint类型的值,而不是int类型的值。以下是一个例子:
SELECT&PATINDEX('%M_rs%',&'The&stars&near&Mars&are&far&from&ours')
注意,如果想找到一个字符串,在所比较的字符串的前后各有0个或者多个字符,则两个百分符都是必须的。下划线表明这个位置上的字符不必匹配,它可以是任意字符。
和使用相同字符串的CHARINDEX()函数作一下比较:
SELECT&CHARINDEX('Mars',&'The&stars&near&Mars&are&far&from&ours')&
这两个函数都返回索引值16。请注意这些函数的执行过程。下一节将把这两个函数和SUBSTRING()函数组合在一起,演示如何使用界定符解析字符串。
LEN()函数用于返回一个代表字符串长度的整型值。这是一个简单、有用的函数,经常与其他函数一起使用,来应用业务规则。以下例子将月份和日期转换为字符类型,然后测试它们的长度。如果月份日期只有一个字符,就填充字符0,然后组合成一个8字符的美国格式的日期字符串(MMDDYYYY)。
DECLARE&@MonthChar&varchar(2),&@DayChar&varchar(2),&@DateOut&char(8)&
SET&@MonthChar&=&CAST(MONTH(GETDATE())&AS&varchar(2))&
SET&@DayChar&=&CAST(DAY(GETDATE())&AS&varchar(2))&
--&Make&sure&month&and&day&are&two&char&long:&
IF&LEN(@MonthChar)&=&1&
&SET&@MonthChar&=&'0'&+&@MonthChar&
IF&LEN(@DayChar)&=&1&
&SET&@DayChar&=&'0'&+&@DayChar&
--&Build&date&string:&
SET&@DateOut&=&@MonthChar&+&@DayChar&+&CAST(YEAR(GETDATE())&ASchar(4))&
SELECT&@DateOut&AS&OutputDate
这个脚本将返回代表日期的8个字符:
LEFT()和RIGHT()函数
LEFT()与RIGHT()函数是相似的,它们都返回一定长度的子字符串。这两个函数的区别是,它们返回的分别是字符串的不同部分。LEFT()函数返回字符串最左边的字符,顺序从左数到右。RIGHT()函数正好相反,它从最右边的字符开始,以从右到左的顺序返回特定数量的字符。看一看使用这两个函数返回&GeorgeWashington&这个字符串的子字符串的例子。
如果使用LEFT()函数返回一个5字符的子字符串,则函数先定位最左边的字符,向右数5个字符,然后返回这个子字符串,如下所示。
DECLARE&@FullName&varchar(25)&
SET&@FullName&=&'George&Washington'
SELECT&LEFT(@FullName,&5)
&结果为:Georg
如果使用RIGHT()函数返回一个5字符的子字符串,则函数先定位最右边的字符,向左数5个字符,然后返回这个子字符串,如下所示。
DECLARE&@FullName&varchar(25)&
SET&@FullName&=&'George&Washington'
SELECT&RIGHT&(@FullName,&5)
&结果为:ngton
要想返回字符串中有意义的部分,这两个函数都不是特别有用。如果想返回全名中的姓氏或者名字,该怎么办?这需要多做一点工作。如果能确定每个姓名中空格的位置,就可以使用LEFT()函数在全名中读取名字。在这种情况下,可以使用CHARINDEX()或者PATINDEX()函数来定位空格,然后使用LEFT()函数返回空格前的字符。下面是第一个用过程方法编写的例子,它将处理过程分解成以下步骤:
DECLARE&@FullName&varchar(25),&@SpaceIndex&tinyint&
SET&@FullName&=&'George&Washington'
--&Get&index&of&the&delimiting&space:&
SET&@SpaceIndex&=&CHARINDEX('&'&,&@FullName)&
--&Return&all&characters&to&the&left&of&the&space:&
SELECT&LEFT(@FullName,&@SpaceIndex&-&1)
&结果为:George
如果不想在结果中包含空格,就需要从@SpaceIndex值中减去1,这样结果中就只有名字了。
SUBSTRING()函数
SUBSTRING()函数能够从字符串的一个位置开始,往右数若干字符,返回一个特定长度的子字符串。和LEFT()函数不同之处是,该函数可以指定从哪个位置开始计数,这样就可以在字符串的任何位置摘取子字符串了。这个函数需要三个参数:要解析的字符串、起始位置索引、要返回的子字符串长度。如果要返回到所输入字符串尾部的所有字符,可以使用比所需长度更大的长度值。SUBSTRING()函数将返回最大可能长度的字符数,而不会将多出的长度以空格填充。
只要指定字符串最左边的字符(1)为起始索引,就可以用SUBSTRING()函数替代LEFT()函数。
继续上一节的例子。可以设置起始位置与长度,返回姓名字符串中间的值。在这个例子中,从位置4开始,返回一个6字符的子字符串&rge&Wa&。
DECLARE&@FullName&varchar(25)&
SET&@FullName&=&'George&Washington'
SELECT&SUBSTRING(@FullName,&4,&6)
现在将上述各函数组合在一起,即可从名字+空格+姓氏格式的全名字符串中解析出名字和姓氏。使用先前的逻辑,通过函数嵌套来减少脚本的行数,并去掉@SpaceIndex变量。下面用SUBSTRING()函数替代LEFT()函数:
DECLARE&@FullName&varchar(25)&
SET&@FullName&=&'George&Washington'
--&Return&first&name:&
SELECT&SUBSTRING(@FullName,&1,&CHARINDEX('&',&@FullName)&-&1)
&类似的逻辑可以用于解析姓氏,但是必须将起始位置更改为空格后的那个字符。如果空格在第7个位置上,那么姓氏将从第8个位置开始。这就意味着起始位置是CHARINDEX()的返回结果加上1。
DECLARE&@FullName&varchar(25)&
SET&@FullName&=&'George&Washington'
--Return&last&name:&
SELECT&SUBSTRING(@FullName,&CHARINDEX('&',&@FullName)&+&1,
LEN(@FullName))
把上述步骤组合在一起,就可以运行下面的查询,从全名变量中提取出名字和姓氏:
DECLARE&@FullName&varchar(25)
SET&@FullName&=&'George&Washington'
--&Return&first&name:
SELECT&SUBSTRING(@FullName,&1,&CHARINDEX('&',@FullName)&-&1)&ASFirstName,
&&&&&&&SUBSTRING(@FullName,&CHARINDEX('&',@FullName)&+&1,LEN(@FullName))
&&&&&&&AS&LastName
传递给SUBSTRING()函数的值是空格所在位置加上1,并将该值作为起始位置,这将是姓氏的第1个字母。由于不可能总是知道名字的长度,所以将LEN()函数的结果作为子字符串长度参数传递进来,当SUBSTRING()函数到达这个位置时,就到达了字符串的末尾,这样就可以将字符串中从空格后面开始的所有字符都包含进来了。
为了举例方便,先创建并填充一个临时表:
CREATE&TABLE&#MyNames&(FullName&varchar(50))&
INSERT&INTO&#MyNames&(FullName)&SELECT&'Fred&Flintstone'
INSERT&INTO&#MyNames&(FullName)&SELECT&'Wilma&Flintstone'
INSERT&INTO&#MyNames&(FullName)&SELECT&'Barney&Rubble'
INSERT&INTO&#MyNames&(FullName)&SELECT&'Betty&Rubble'
INSERT&INTO&#MyNames&(FullName)&SELECT&'George&Jetson'
INSERT&INTO&#MyNames&(FullName)&SELECT&'Jane&Jetson'
--drop&table&#MyNames
下面执行一个使用函数调用来解析名字和姓氏值的单行查询表达式。这里对@FullName变量的引用被表中的FullName列所替代:
&&&&SUBSTRING(FullName,&1,&CHARINDEX('&',&FullName)&-&1)&AS&FirstName&
&&&&,SUBSTRING(FullName,&CHARINDEX('&',&FullName)&+&1,&LEN(FullName))AS&LastName
FROM&#MyNames
&在下图所示的结果中,显示了两个不同的列,分别是名字和姓氏。
LOWER()和UPPER()函数
这两个函数很容易理解,它们用于将字符串中所有字符分别都转换为小写和大写,这在比较用户输入或者存储用于比较的字符串时是非常有用的。字符串比较通常是区分大小写的,这取决于SQL&Server安装时的设置。如果和其他的字符串操纵函数一起使用,就可以将字符串转换为合适的大小写,以便存储或显示。以下例子说明混合大小写的名字,假设名字中的第2个大写子字符串前只包含一个空格,但在特殊情况下也有一些名字是没有空格的。这个例子很容易通过扩展来处理包含其他类型的混合大小写名字(如以MC开头的名字,带连接号的名字等)。
DECLARE&@LastName&varchar(25),&@SpaceIndex&tinyint&
SET&@LastName&=&'mc&donald'&&&&&&&&&&&&&--&Test&value&
--&Find&space&in&name:&
SET&@SpaceIndex&=&CHARINDEX('&'&,&@LastName)&
IF&@SpaceIndex&&&0&&&&&&&&&&&&&&&&&&&&&&&--&Space:&Capitalize&first&&&substring&
&&&&SELECT&UPPER(LEFT(@LastName,&1))&&
&+&LOWER(SUBSTRING(@LastName,&2,&@SpaceIndex&-&1))&&
&+&UPPER(SUBSTRING(@LastName,&@SpaceIndex&+&1,&1))&&
&+&LOWER(SUBSTRING(@LastName,&@SpaceIndex&+&2,&LEN(@LastName)))&
ELSE&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&--&No&space:&Cap&only&first&char.&
&&&&SELECT&UPPER(LEFT(@LastName,&1))&&&
&+&LOWER(SUBSTRING(@LastName,&2,&LEN(@LastName)))
&这个脚本将返回MC&Donald。还可以对这个例子进行扩展,以处理姓氏包含撇号的情况。在这个例子的业务规则中,空格是不考虑的。如果找到了撇号,就将后面的字符全部转为大写。请注意如果要在脚本中测试撇号,就必须输入两次撇号('&'),以表明这是一个文字,而不是一对单引号。姓氏中只存储一个撇号。
DECLARE&@LastName&varchar(25),&@SpaceIndex&tinyint,&@AposIndex&tinyint&
SET&@LastName&=&'o''malley'&&&&&&&&&&&&&&--&Test&value&
--&Find&space&in&name:&
SET&@SpaceIndex&=&CHARINDEX('&',&@LastName)&
--&Find&literal&'&in&name:&
SET&@AposIndex&=&CHARINDEX('''',&@LastName)&
IF&@SpaceIndex&&&0&&&&&&&&&&&&&&&&&&&&&&&--&Space:&Capitalize&first&&&substring&
&&&&SELECT&UPPER(LEFT(@LastName,&1))&&
&+&LOWER(SUBSTRING(@LastName,&2,&@SpaceIndex&-&1))&&
&+&UPPER(SUBSTRING(@LastName,&@SpaceIndex&+&1,&1))&&
&+&LOWER(SUBSTRING(@LastName,&@SpaceIndex&+&2,&LEN(@LastName)))&
ELSE&IF&@AposIndex&&&0&&&&&&&&&&&&&&&&&&&--&Apostrophe:&Cap&first&&&substring&
&&&&SELECT&UPPER(LEFT(@LastName,&1))&&
&+&LOWER(SUBSTRING(@LastName,&2,&@AposIndex&-&1))&&
&+&UPPER(SUBSTRING(@LastName,&@AposIndex&+&1,&1))&&
&+&LOWER(SUBSTRING(@LastName,&@AposIndex&+&2,&LEN(@LastName)))&
ELSE&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&--&Nospace:&Cap&only&first&char.&
&&&&SELECT&UPPER(LEFT(@LastName,&1))&&&
&+&LOWER(SUBSTRING(@LastName,&2,&LEN(@LastName)))
&这个脚本返回O'Malley。
LTRIM()和RTRIM()函数
这两个函数分别返回将字符串的左边和右边的空白修剪掉之后的字符串:
DECLARE&@Value1&char(10),&@Value2&char(10)&
SET&@Value1&=&'One'
SET&@Value2&=&'Two'
SELECT&@Value1&+&@Value2&
SELECT&CONVERT(varchar(5),&LEN(@Value1&+&@Value2))
+&'&characters&long.&'
SELECT&RTRIM(@Value1)&+&RTRIM(@Value2)&&
SELECT&CONVERT(varchar(5),&LEN(RTRIM(@Value1)&+&RTRIM(@Value2)))&&
&&&&&&&+&'&characters&long&trimmed.&'
结果如下:
REPLACE()函数
REPLACE()函数可以把字符串中的某个字符或某个子字符串替换为另一个字符或者子字符串,该函数可以用于全局查找和替换工具中。
DECLARE&@Phrase&varchar(1000)&
SET&@Phrase&=&'I&aint&gunna&use&poorgrammar&when&commenting&script&and&&
I&aint&gunna&complain&about&it.&'&
SELECT&REPLACE(@Phrase,&'aint',&'am&not')
REPLICATE()和SPACE()函数
在需要将一些字符重复填充进一个字符串时,这两个函数是非常有用的。这里也使用SUBSTRING()例子中的临时表为每个名字填满20个字符,然后将20减去各个字符串的长度,以便将正确的值传递给REPLICATE()函数:
SELECT&FullName&+&REPLICATE('*',&20&-&LEN(FullName))
FROM&#MyNames
&结果是每个名字后面都填满了星号,各个名字的总长度都是20个字符:
Fred&Flintstorle*****&
Wilrna&Flintstone****&
Barney&Rubble*******&
Betty&Rubble********&
George&Jetson********&
Jane&Jetson**********
SPACE()函数与上述函数类似,区别在于该函数使用空格进行填充。它返回一个由空格组成的字符串,空格的个数由参数定义。
SELECT&FullName&+&SPACE(20&-&LEN(FullName))&
FROM&#MyNames
&如果返回&#MyNames表不存在&的错误,只需再次运行本文前面&SUBSTRING()函数&一节的CREATE&TABLE脚本即可。
REVERSE()函数
顾名思义,这个函数用于将字符串中的字符颠倒过来。这在处理连接列表中的单个字符值时将会被用到。
SELECT&REVERSE('The&stars&near&Mars&are&far&from&ours.&')
结果为:.sruo&morf&raf&era&sraM&raen&srats&ehT
STUFF()函数
这个函数可将字符串中的一部分替换为另一个字符串。它本质上是将一个字符串以特定的长度插入另一个字符串中的特定位置上。这对于源值与目的值的长度不一样的字符串替换是很有用的。下列代码用于将字符串中的价格替换为109.95:
Please&submit&your&payment&for&99.95&immediately.
价格值是从第32个字符开始的,有5个字符长。在这个位置上插入的子字符串有多长并不重要,只需要知道需要删除多少个字符就可以了。
&SELECT&STUFF('Please&submit&your&payment&for&99.95&immediately.&',&32,&5,&'109.95')
结果为:Please&submit&your&payment&for&109.95&immediately.
QUOTENAME()函数
这个函数和SQL&Server对象名组合使用,以将结果传递给表达式。它只用于给输入的字符串加一对方括号,并返回新形成的字符串。如果参数包含保留的分隔符或者封装字符(比如引号或括号),这个函数将修改字符串,以便SQL&Server能将结果字符串中的这类字符当成文本字符。如下面的例子所示,查询的结果如图6-10所示。
SELECT&QUOTENAME(COLUMN_NAME)&AS&ColumnName&
FROM&INFORMATION_SCHEMA.&COLUMNS
返回一个数的绝对值
计算一个角的反余弦值,以弧度表示
计算一个角的反正弦值,以弧度表示
计算一个角的反正切值,以弧度表示
计算两个值的反正切,以弧度表示
返回大于或等于一个数的最小整数
计算一个角的正弦值,以弧度表示
计算一个角的余切值,以弧度表示
将一个角从弧度转换为角度
返回小于或等于一个数的最大整数
计算以2为底的自然对数
计算以10为底的自然对数
返回以浮点数表示的圆周率
将一个角从角度转换为弧度
返回以随机数算法算出的一个小数,
可以接收一个可选的种子值
对一个小数进行四舍五入运算,
使其具备特定的精度
根据参数是正还是负,返回–1或者1
计算一个角的正弦值,以弧度表示
返回一个数的平方根
返回一个数的平方
计算一个角正切的值,以弧度表示
下表中列出的函数用于执行多种普通与特殊的数学运算,可以执行代数、三角、统计、估算与财政运算等运算。
元数据函数
这是一些工具函数,它们返回SQL&Server配置细节、服务器与数据库设置细节的信息,包括一组用于返回不同对象的属性状态的通用以及专用函数,这些函数把对Master数据库中系统表以及用户数据库的查询封装在函数中。建议读者使用这些函数以及其他的系统函数,而不是自己创建对系统表的查询,以防今后SQL&Server版本对模式进行更改。
这些函数被用于以与结果集顺序无关的特定顺序,枚举已排序的或排在前面的结果集。
ROW_NUMBER()函数
ROW_NUMBER()函数根据作为参数传递给这个函数的ORDER&BY子句的值,返回一个不断递增的整数值。如果ROW_NUMBER的ORDER&BY的值和结果集中的顺序相匹配,返回值将是递增的,以升序排列。如果ROW_NUMBER的ORDER&BY子句的值和结果集中的顺序不同,这些值将不会按顺序列出,但它们表示ROW_NUMBER函数的ORDER&BY子句的顺序。如下面的例子和结果所示:
SELECT&ProductCategoryID&
&&&&,ROW_NUMBER()&OVER&(ORDER&BY&Name)&AS&RowNum
FROM&Production.ProductCategory
ORDER&BY&Name
&由于ROW_NUMBER()调用中的ORDERBY子句和查询结果的顺序匹配,所以对这些结果按顺序列出,如下图所示:
不过,在函数调用中使用另一个ORDER&BY子句时,这些值就是无序的了。
SELECT&ProductCategoryID&
&&&&,ROW_NUMBER()&OVER&(ORDER&BY&Name)&AS&RowNum
FROM&Production.ProductCategory
ORDER&BY&ProductCategoryID
这是了解如何使用ORDER&BY子句对结果进行排序的有效方法。如下图所示:
RANK()与DENSE_RANK()函数
这两个函数与ROW_NUMBER()函数类似,因为它们都返回一个基于ORDER&BY子句的值。不过这些值不一定永远是唯一的。排列值对于所提供的ORDER&BY子句中的重复结果而言也是重复的,而且唯一性是仅仅基于ORDER&BY列表中的唯一值的。这些函数用不同的方法来处理重复的值。RANK()函数保留列表中行的位置序号,对于每个重复的值,该函数会跳过下面与其相邻的值,于是就可以将下一个不重复的值保留在正确的位置上。
&其行为类似于短跑比赛中的并列成绩。例如刘翔与Dayron&Robles(古巴)在110栏的比赛中都跑出了12’92的成绩,那他们就是并列第一,而其后的一名选手将会获得第三名的成绩。
SELECT&ProductID&
&&&&,ListPrice
&&&&,RANK()&OVER&(ORDER&BY&ListPrice&DESC)&AS&[Rank]
FROM&Production.Product
ORDER&BY&[Rank]
注意在下图的结果列表中,重复的价格值所对应的结果是相同的,而每个连接之后的值都被跳过了。比如,产品&Road-150&Red,&52&和&Road-150&Red,&56&都排在第1,而接下来的行&Mountain-100&Silver,38&就排在第6了。
DENSE_RANK()函数的工作方式与RANK()函数相同,不过它不会跳过每个连接后的值,这样就不会有值被跳过了,但是在连接处排列序号位置将会丢失。
SELECT&ProductID&
&&&&,ListPrice
&&&&,DENSE_RANK()&OVER&(ORDER&BY&ListPrice&DESC)&AS&[Rank]
FROM&Production.Product
ORDER&BY&[Rank]
下图的结果重复了排列值,但是不会跳过列中的任何数字。
NTILE(n)函数
这个函数也用于对结果进行排列,并返回一个整型的排列值,但是它不会对结果以唯一的排列顺序进行枚举,而是将结果切分为有限数量的排列组。比如,一个表有10&000行,使用1000为参数值调用NTILE()函数,即NTILE(1000),并将结果分成以10为单位的1000个组,每个组赋予相同的排列值。和本节讨论的其他排列函数一样,NTILE()函数也支持OVER(ORDER&BY…)语法。下面的例子根据产品价格,按照从高到低的顺序把Product表分为50组产品:
SELECT&ProductID&
&&&&,ListPrice
&&&&,NTILE(50)&OVER&(ORDER&BY&ListPrice&DESC)&AS&GroupedProducts
FROM&Production.Product
ORDER&BY&GroupedProducts
与安全相关的函数返回SQL&Server用户的角色成员和权限信息。这类函数也包括一组管理事件与跟踪的函数。下表显示了这些函数:
fn_trace_geteventinfo()
为指定的跟踪ID返回一个填充事件信息的表类型值
fn_trace_getfilterinfo()
为指定的跟踪ID返回一个填充与过滤器有关的信息的表类型值
fn_trace_getinfo()
为指定的跟踪ID返回一个填充跟踪信息的表类型值
fn_trace_getable()
为指定的跟踪ID返回一个填充文件信息的表类型值
HAS_DBACCESS()
返回一个表明当前用户是否有访问指定数据库权限的标志
IS_MEMBER()
返回一个表明当前用户是Windows组用户还是SQL&Server用户的标志
IS_SRVROLEMEMBER()
返回一个表明当前用户是否是数据库服务器角色成员的标志
SUSER_SID()
返回指定用户的登录名的安全ID,或者(如果参数被忽略)返回当前用户的安全ID。返回指定用户的用户ID,或者(如果参数被忽略的话)返回当前用户的用户ID
SUSER_SNAME()
返回指定安全ID的登录名。如果不提供任何安全ID,则返回当前用户的登录名
返回指定用户名的用户ID,或者(如果参数被忽略的话)返回当前用户的用户ID
USER_NAME()
返回指定用户ID的用户名
系统函数与系统变量
本节讨论具有多种用途的工具函数,包括值比较、值类型测试等功能。这个类别的函数也包罗了其他函数:
APP_NAME()
返回与当前连接相关联的应用程序的名字
COALESCE()
从以逗号分隔的表达式列表中返回第一个非空值
COLLATIONPROPERTY()
返回一个特定字符集排序规则的特定属性的值。这些属性包括CodePage、LCID、ComparisonStyle
CURRENT_TIMESTAMP()
返回当前日期与时间。和GETDATE()函数是同义的。这个函数的存在只是为了与ANSI-SQL兼容
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数据库设置返回数据库的可空性设置
返回当前会话的工作站ID
HOST_NAME()
返回当前会话的工作站名
IDENT_CURRENT()
返回最后一个为指定的表生成的标识(ID)值。与会话、范围无关
IDENT_INCR()
返回最后一次创建的标识(ID)列中定义的增量值
IDENT_SEED()
返回最后一次创建的标识(ID)列中定义的种子值
IDENTITY()
用在SELECT…INTO语句中,在一个列中插入自动生成的标识值
返回一个表明指定的值是否可被转换为日期值的标志
判断指定的值是否是空值,然后返回一个事先提供的替代值
ISNUMERIC()
返回一个表明指定的值是否可被转换为数字值的标志
返回一个新生成的UniqueIdentifier类型的值。这是一个128位的整型、全球唯一的值,通常以字母或数字十六进制来表示(如89DE6247·C2E242DB-8CE8·A787E505D7EA)。这个类型经常被用作复制的和半连接系统中的主键.
两个特定的参数的值如果是相同的,则返回NULL
PARSENAME()
返回一个具有4部分对象名的特定部分
PERMISSIONS()
返回一个整型值,该值是一个表示当前用户在指定的数据库对象上权限或者权限组合的位映像
ROWCOUNT_BIG()
与@@RowCount变量一样,这个函数返回被最后一条语句修改或返回的行数量。返回值类型是bigint
SCOPE_IDENTITY()
与@@IDENTIY变量一样,这个函数返回限制在当前会话与范围内的最后一次生成的标识值
SERVERPROPERTY()
返回一个表示服务器属性状态的标记。属性包括Collation、Edition、EngineEdition、InstanceName、IsClustered、IsFullTextIn

我要回帖

更多关于 SQL中的函数 的文章

 

随机推荐