http://5dblog.me
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,未指定的日期成分设置为 1900-01-01。
7. 使用可选的时间区域指示符 (Z) 更便于将具有时区信息的 XML datetime 值映射到没有时区的 SQL Server
datetime 值。Z 是时区 UTC-0 的指示符。其他时区则以 + 或 - 方向的 HH:MM 偏移量来指示。例如:2006-12-12T23: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 2005 1:05PM
SELECT 'US Date:' + CONVERT(Varchar(50), GETDATE(), 101)
US Date: 04/25/2005
SELECT 'ANSI Date:' + CONVERT(Varchar(50), GETDATE(), 103)
ANSI Date: 2005.04.25
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)
返回结果如下: 1234.56
使用值1则返回如下结果: 1,234.56
使用值2则返回如下结果:
http://5dblog.me
1234.5600
以下例子和上例相同,但是使用Float类型:
DECLARE @Num float SET @Num = 1234.56 SELECT CONVERT(varchar(50), @Num, 2)
使用值0不会改变所提供的格式,但是使用值1或2将返回以科学计数法表示的数字,后者使用了15位小数: 1.23456000000000e+003 STR()函数
这是一个将数字转换为字符串的快捷函数。这个函数有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)
1.0000
然而,如果指定的总长度大于整数位数、小数点和小数位数之和,结果值的左边将用空格补齐:
SELECT STR(1, 6, 4)
1.0000
SELECT STR(1, 12, 4)
---------- 1.0000
游标函数与变量
游标可以处理多行数据,在过程循环中一次访问一行。和基于集合的高效操作相比,这个功能对系统资源的消耗更大。可以用一个函数和两个全局变量来管理游标操作。 CURSOR_STATUS()函数
这个函数返回一个整型值,表示传递给这个函数的游标类型变量的状态。有很多不同类型的游标会影响这个函数的操作。为简单起见,下表列出了这个函数的常见返回值。 返 回 值 1 0 -1 说 明 游标包含一行或多行(动态游标包含0行或者多行) 游标不包含行 游标已关闭 http://5dblog.me
-2 -3
游标未分配 游标不存在 @@CURSOR_ROWS全局变量
这个变量是一个整型值,表示在当前连接中打开的游标中的行数。根据游标类型,这个值也能不代表结果集中的实际行数。 @@FETCH_STATUS全局变量
这个变量是一个标记,用于表示当前游标指针的状态。这个变量主要用来判断某行是否存在,以及在执行了FETCH NEXT语句后,是否已执行到结果集的尾部。打开游标时,@@FETCH_STATUS变量值为-1。一旦把第一个值放在游标中,@@FETCH_STATUS变量值就变成0。当不再把更多的行放在游标中时,该变量的值将变回-1。
日期函数
这些函数可以操作DateTime与SmallDateTime类型的值。有些函数可用于解析日期值的日期与时间部分,有些函数可用于比较、操纵日期/时间值。日期数据类型的区别如下表所示。 数据类型 time date smalldatetime datetime datetime2 datetimeoffset
DATEADD()函数
12:35:29. 1234567 2007-05-08 2007-05-08 12:35:00 2007-05-08 12:35:29.123 2007-05-08 12:35:29. 1234567 2007-05-08 12:35:29.1234567 +12:15 输出 DATEADD()函数用于在日期/时间值上加上日期单位间隔。比如,要得到2007年4月29日起90天后的日期,可以使用下列语句:
SELECT DATEADD(DAY, 90, '4-29-2007')
结果:2007-07-28 00:00:00.000
可以把下表的值作为时间间隔参数传递给DATEADD()函数。
datepart year quarter month dayofyear day yy, yyyy qq, q mm, m dy, y dd, d 缩写 http://5dblog.me
week weekday hour minute second millisecond microsecond nanosecond
wk, ww dw, w hh mi, n ss, s ms mcs ns 在下面列出的例子中,我们使用和上一个例子一样的日期,并且在这些例子中还包含了时间数据。每个操作的结果将显示在查询的下一行中。
18年后:
SELECT DATEADD(YEAR, 18, '4-29-1988 10:30 AM')
2006-04-29 10:30:00.000 18年前:
SELECT DATEADD(YY, -18, '4-29-1988 10:30 AM')
1970-04-29 10:30:00.000 9000秒后:
SELECT DATEADD(SECOND, 9000, '4-29-1988 10:30 AM')
1988-04-29 13:00:00.000 9000000毫秒前:
SELECT DATEADD(MS, -9000000, '4-29-1988 10:30 AM')
1988-04-29 08:00:00.000
可以将CONVERT()函数和DATEADD()函数组合在一起,来对1989年9月8日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()函数就可以返回差值。
为了说明这一点,我们选择任意两个日期与一个时间间隔作为参数。这个函数将以所提供的时间间隔为单位返回两个日期之间的差值。要知道1989年9月8日和1991年10月17日之间差了几个月,可编写如下查询代码:
http://5dblog.me
SELECT DATEDIFF(MONTH, '9-8-1989', '10-17-1991')
结果是25个月。如果以日期为单位呢?
SELECT DATEDIFF(DAY, '9-8-1989', '10-17-1991')
结果是769天。
1996年7月2日和1997年8月4日之间差几个星期?
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