日期是數據處理中經常使用到的信息之一。生日、數據處理時間、計劃的預計完成時間,按年、季、月的統
計,這些都屬于日期處理的范疇。由于日期中包含了年、季、月、日等眾多信息,不同的國家對日期格式、日期文字描述及星期有不同的規定,因此產生了日期處理
的復雜性。本章主要討論在SQL Server數據庫中對日期的各種處理方法。
日期類型概述
SQL Server中的日期類型包括datetime和smalldatetime,僅能處理可以識別為1753年~9999年間的日期的值,沒有單獨的日期型或時間型。
1.datetime
datetime類型處理從1753年1月1日~9999年12月31日的日期和時間數據,精確度為百分之三秒。即:對于0.000~0.001、0.009的日期值,調整為0.000;對于0.002~0.004的日期值,調整為0.003;對于0.005~0.008的日期值,調整為0.007。
例如,下面的代碼在輸入時,其時間精確度為百分之一秒,但經數據庫保存后再顯示出來,其結果就已經做了處理。
DECLARE @t TABLE(date char(21))
INSERT @t SELECT '1900-1-1 00:00:00.000'
...
INSERT @t SELECT '1900-1-1 00:00:00.009'
SELECT date,轉換后的日期=CAST(date as datetime) FROM @t
/*--結果
date 轉換后的日期
---------------------------------- ----------------------------
1900-1-1 00:00:00.000 1900-01-01 00:00:00.000
...
1900-1-1 00:00:00.000 1900-01-01 00:00:00.010
--*/
datetime的存儲長度為8字節,日期和時間各用4個字節存儲,第一個4字節存儲自1900年1月1日之前或之后的天數(以1900年1月1日為分界點,在1900年1月1日之前的日期的天數小于0,在1900年1月1日之后的日期的天數大于0)。另外一個4字節存儲以午夜(00:00:00.000)后毫秒數所代表的每天的時間。
例如,下面的代碼演示了datetime變量中,僅包含單純的日期和單純的時間時,日期存儲的十六進制存儲表示結果。
DECLARE @dt datetime
--單純的日期
SET @dt='1900-1-2'
SELECT CAST(@dt as binary(8))
--結果: 0x0000000100000000
--單純的時間
SET @dt='00:00:01'
SELECT CAST(@dt as binary(8))
--結果: 0x000000000000012C
2.smalldatetime
smalldatetime類型處理從1900年1月1日~2079年6月6 日的日期和時間數據,精確到分鐘。29.998秒或更低的smalldatetime值向下舍入為最接近的分鐘,29.999秒或更高的smalldatetime值向上舍入為最接近的分鐘。
smalldatetime的存儲長度為4字節,第一個2字節存儲自1900年1月1日之后的天數。另外一個2字節存儲午夜(00:00:00.000)后的分鐘數。
例如,下面的代碼演示了smalldatetime變量中,僅包含單純的日期和單純的時間時,日期存儲的十六進制存儲表示結果。
DECLARE @dt smalldatetime
--單純的日期
SET @dt='1900-1-2'
SELECT CAST(@dt as binary(4))
--結果: 0x00010000
--單純的時間
SET @dt='00:10'
SELECT CAST(@dt as binary(4))
--結果: 0x0000000A
日期處理函數
日期由年、月、日、時等多個部分組成,它的處理相對復雜,因此,SQL Server提供了大量的日期處理函數,用以完成各種日期數據的處理。掌握好這些函數,對完成數據庫的各種日期處理非常必要,本節將介紹幾個常用的日期處理函數。期增減函數可以對日期指定部分的值進行增減,并返回處理后的日期值,SQL Server提供的日期增減函數為DATEADD。
DATEADD的具體語法如下:DATEADD ( datepart , number, date )
其中包括以下參數。
¡ datepart:是規定應向日期的哪一部分返回新值的參數。表2-1列出了SQL Server支持的日期部分、縮寫及含義。
DATEADD、DATEDIFF支持的日期部分、縮寫及含義
日期部分
|
縮 寫
|
含 義
|
Year
|
yy , yyyy
|
年份
|
Quarter
|
qq , q
|
季度
|
Month
|
mm , m
|
月份
|
Dayofyear
|
dy,y
|
日
|
Day
|
dd , d
|
Week
|
wk , ww
|
星期
|
Hour
|
Hh
|
小時
|
Minute
|
mi , n
|
分鐘
|
Second
|
ss , s
|
秒
|
Millisecond
|
Ms
|
毫秒
|
¡ number:是用來增加datepart的值。正數表示增加,負數表示減少,如果指定的是非整數值,則忽略此值的小數部分,不做四舍五入處理。例如,DATEADD(Day,1.7,date),表示date增加1天。
¡ date:是返回datetime或smalldatetime值或日期格式字符串的表達式。
如果date是smalldatetime,則返回smalldatetime,否則返回datetime。date為smalldatetime,Datepart為Second(ss,s)或Millisecond(ms)時,返回值將根據日期增減的結果調整到分鐘;date為datetime,Datepart為Millisecond(ms)時,返回值將根據日期增減的結果調整為百分之三秒。調整規則可以參考2.1節的相關說明。
date允許直接與number進行增減計算,即對于DATEADD(Day,number,date),等同于date+number。
日期信息獲取函數
日期信息獲取函數用于獲取日期指定部分的相關信息,常用的日期信息獲取函數如表2-2所示。
常用的日期信息獲取函數
功能說明
|
語 法
|
參數及返回值數據類型說明
|
返回代表指定日期的指定日期部分的字符串
|
DATENAME(datepart,date)
|
datepart是指定應返回的日期部分的參數,其定義如表2-3所示。date是返回datetime或smalldatetime值或日期格式字符串的表達式。DATENAME函數返回nvarchar,DATEPART函數返回int
|
返回代表指定日期的指定日期部分的整數
|
DATEPART(datepart,date)
|
返回表示指定日期中的年份的整數
|
YEAR(date)
|
返回int
|
返回表示指定日期中的月份的整數
|
MONTH(date)
|
返回int
|
返回表示指定日期中的天的整數
|
DAY(date)
|
返回int
|
DATENAME、DATEPART支持的日期部分、縮寫及含義
日期部分
|
縮 寫
|
含 義
|
Year
|
yy , yyyy
|
年份
|
Quarter
|
qq , q
|
季度
|
Month
|
mm , m
|
月份
|
Dayofyear
|
dy , y
|
日
|
Day
|
dd , d
|
Week
|
wk , ww
|
自年初開始的第幾個星期
|
Weekday
|
Dw
|
星期幾(例如星期一、星期二)
|
Hour
|
Hh
|
小時
|
Minute
|
mi , n
|
分鐘
|
Second
|
ss , s
|
秒。date為smalldatetime時,始終返回0
|
Millisecond
|
Ms
|
毫秒。date為smalldatetime時,始終返回0,為datetime時,返回百份之三秒
|
DATEPART(Week,date)返回的星期計算方式,是按照星期日為一周的第一天,這點與中國人的日期處理習慣不同,在使用時要注意這一點。DATENAME函數返回指定日期的指定日期部分的字符串,其返回的具體字符串值,與SET DATEFIRST及SET DATELANGUAGE選項的設置有關。使用DATEPART(Weekday,date)時,其返回的值與SET DATEFIRST選項的設置有關,具體的將在2.3節中說明。
日期差值計算函數
日期差值計算函數用于計算兩個給定日期指定部分的邊界數,SQL Server提供的日期差值計算函數為DATEDIFF。
DATEDIFF的具體語法如下:
DATEDIFF ( datepart , startdate , enddate )
其中包括以下參數。
¡ datepart:規定了應在日期的哪一部分計算差額,其定義如表2-1所示。
¡ startdate:規定了計算的開始日期。
¡ enddate:規定了計算的終止日期。
返回類型:integer
計算的開始日期和終止日期,可以是日期或日期格式的字符串。計算的方法是從enddate減去startdate。如果startdate比enddate晚,返回負值。當結果超出整數值范圍,DATEDIFF就產生錯誤。對于毫秒,最大數是24天20小時31分鐘23.647秒。對于秒,最大數是68年。
計算跨分鐘、秒和毫秒這些邊界的方法,使得DATEDIFF給出的結果在全部數據類型中是一致的。結果是帶正負號的整數值,其等于跨第一個和第二個日期間的datepart邊界數。例如,在2005年1月4日和2005年2月11日之間的月份數是1。
其他日期處理相關函數
其他常用的日期處理相關函數包括以下幾個。
1.GETDATE
GETDATE按照datetime值返回當前系統日期和時間。
GETDATE的語法如下:
GETDATE()
返回類型:datetime
2.ISDATE
ISDATE確定輸入的表達式是否有效日期。
在輸入日期表達式時,日期都是以日期格式的字符串提供的,由于不同的區域有不同的日期格式,所以并不能保證輸入的日期表達式能夠被SQL Server識別,這種情況下,就需要用ISDATE來判斷日期表達式能否正確地被SQL Server識別了。
ISDATE的語法如下:
ISDATE(expression)
返回類型:int
3.CONVERT
CONVERT將某種數據類型的表達式顯式轉換為另一種數據類型。
嚴格來說,CONVERT不屬于日期處理函數,只是它被經常用于日期處理中,所以這里把它列入了其他日期處理函數,下面是CONVERT的用法描述(只重點說明在日期處理中的應用)。
CONVERT的具體語法如下:
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
其中包括以下參數。
¡ expression:是要轉換數據類型的有效SQL Server表達式。
¡ data_type:是expression轉換后的數據類型,length是對于有精度定義需要的data_type的精度定義,對于沒有精度定義需要的data_type,該參數可以省略。
¡ style:定義數據類型轉換時的格式,對于日期類型的轉換,它的定義如表2-4所示。
表2-4 style在日期轉換中的說明
不帶世紀數位
|
帶世紀數位
|
標 準
|
輸入/輸出
|
—
|
0或100
|
默認值
|
mon dd yyyy hh:miAM(或 PM)
|
1
|
101
|
美國
|
mm/dd/yyyy
|
2
|
102
|
ANSI
|
yy.mm.dd
|
3
|
103
|
英國/法國
|
dd/mm/yy
|
4
|
104
|
德國
|
dd.mm.yy
|
5
|
105
|
意大利
|
dd-mm-yy
|
6
|
106
|
—
|
dd mon yy
|
7
|
107
|
—
|
mon dd, yy
|
8
|
108
|
—
|
hh:mm:ss
|
—
|
9或109
|
默認值+毫秒
|
mon dd yyyy hh:mi:ss:mmmAM(或PM)
|
10
|
110
|
美國
|
mm-dd-yy
|
11
|
111
|
日本
|
yy/mm/dd
|
12
|
112
|
ISO
|
yymmdd
|
—
|
13或113
|
歐洲默認值+毫秒
|
dd mon yyyy hh:mm:ss:mmm(24h)
|
14
|
114
|
—
|
hh:mi:ss:mmm(24h)
|
—
|
20或120
|
ODBC規范
|
yyyy-mm-dd hh:mm:ss[.fff]
|
—
|
21或121
|
ODBC規范(帶毫秒)
|
yyyy-mm-dd hh:mm:ss[.fff]
|
—
|
126
|
ISO8601
|
yyyy-mm-ddThh:mm:ss.mmm
|
—
|
130
|
Hijri
|
dd mon yyyy hh:mi:ss:mmmAM
|
—
|
131
|
Hijri
|
dd/mm/yy hh:mi:ss:mmmAM
|
說明:
① 輸入/輸出:“輸入”表示從字符串轉換為日期時字符串的日期格式,“輸出”指從日期轉換為字符串時的日期字符串格式。
② Hijri:是具有幾種變化形式的日歷系統,SQL Server使用其中的科威特算法。
當從smalldatetime轉換為字符數據時,由于smalldatetimer只保存到分鐘的數據,因此,對于包含秒或毫秒的樣式,將在秒或毫秒的位置上顯示零。當從datetime或smalldatetime值進行轉換時,可以通過使用適當的char或varchar數據類型長度來截斷不需要的日期部分。
注意:
在SQL Server中,由于直接提供的日期均是以日期格式的字符串提供,所以在使用CONVERT進行日期格式轉換時,要先把日期格式的字符串轉換為日期型,然后才能利用CONVERT進行日期格式轉換,否則就變成字符串轉換為字符串,此時的style選項是無效的。
返回類型:由參數data_type確定。
下面是利用CONVERT進行日期轉換的簡單示例:
/*== 字符轉換為日期時,Style的使用 ==*/
--1. Style=101時,表示日期字符串為:mm/dd/yyyy格式
SELECT CONVERT(datetime,'11/1/2003',101)
--結果:2003-11-01 00:00:00.000
--2. Style=101時,表示日期字符串為:dd/mm/yyyy格式
SELECT CONVERT(datetime,'11/1/2003',103)
--結果:2003-01-11 00:00:00.000
/*== 日期轉換為字符串 ==*/
DECLARE @dt datetime
SET @dt='2003-1-11'
--1. Style=101時,表示將日期轉換為:mm/dd/yyyy 格式
SELECT CONVERT(varchar,@dt,101)
--結果:01/11/2003
--2. Style=103時,表示將日期轉換為:dd/mm/yyyy 格式
SELECT CONVERT(varchar,@dt,103)
--結果:11/01/2003
/*== 這是很多人經常犯的錯誤,對非日期型轉換使用日期的style樣式 ==*/
SELECT CONVERT(varchar,'2003-1-11',101)
--結果:2003-1-11