本節介紹一些對日期和時間數據類型進行操作的函數,包括GETDATE、CURRENT_TIMESTAP、GETUTCDATE、SYSDATETIME、SYSUTCDATETIME、SYSDATETIMEOFFSET、CAST、CONVERT、SWITCHOFFSET、TODATETIMEOFFSET、DATEADD、DATEDIFF、DATEPART、YEAR、MONTH、DAY,以及DATENAME。注意,SYSDATETIME、SYSUTCDATETIME、SYSDATETIMEOFFSET、SWITCHOFFSET,以及TODATETIMEOFFSET是SQL Server 2008中新增的,其他幾個函數在SQL Server 2008之前的版本中也可以使用。不過,SQL Server 2008對原有的幾個函數進行了改進,以支持新的日期和時間數據類型,以及新的日期和時間組成部分。
日期和時間函數
以下幾個不帶參數的函數可以返回SQL Server實例所在系統的當前日期和時間:GETDATE、CURRENT_TIMESTAMP、GETUTCDATE、SYSDATETIME、SYSUTCDATETIME,以及SYSDATETIMEOFFSET。下表列舉了這些函數的一些信息。
函數 |
返回類型 |
描述 |
是否是SQL Server 2008新加的 |
GETDATE |
DATETIME |
當前日期和時間 |
否 |
CURRENT_TIMESTAMP |
DATETIME |
與GETDATE相同,而且是ANSI SQL |
否 |
GETUTCDATE |
DATETIME |
以UTC格式表示的當前日期和時間 |
否 |
SYSDATETIME |
DATETIME2 |
當前日期和時間 |
是 |
SYSUTCDATETIME |
DATETIME2 |
以UTC格式表示的當前日期和時間 |
是 |
SYSDATETIMEOFFSET |
DATETIMEOFFSET |
當前日期和時間,包含時區偏移量 |
是 |
注意,除了ANSI函數CURRENT_TIMESTAMP以外,對於不需要參數的函數,在調用它們時都必須多加一對空的圓括號。此外,因為CURRENT_TIMESTAMP和GETDATE返回的內容相同,但前者是標准SQL,所以推薦優先選用CURRENT_TIMESTAMP。我們應該盡量遵循一條實踐原則:當完成同樣的事情有多種選擇,而且它們之間在功能和性能上都沒有區別,但只有一個是標准SQL,其他都不是時,我們應該偏向選擇使用標准SQL。
以下代碼演示了取得當前日期和時間函數的用法:
3 CURRENT_TIMESTAMP AS [ CURRENT_TIMESTAMP ] ,
4 GETUTCDATE() AS [ GETUTCDATE ] ,
5 SYSDATETIME() AS [ SYSDATETIME ] ,
6 SYSUTCDATETIME() AS [ SYSUTCDATETIME ] ,
7 SYSDATETIMEOFFSET() AS [ SYSDATETIMEOFFSET ] ;
或許你會發現,SQL Server 2008中的函數都不是只返回當前系統日期或只返回當前系統時間。不過,通過把CURRENT_TIMESTAMP或SYSDATETIME轉換為DATE或TIME,可以容易地做到這一點,如下所示:
2 CAST (SYSDATETIME() AS DATE) AS [ Current_date ] ,
3 CAST (SYSDATETIME() AS TIME) AS [ Current_time ] ;
CAST和CONVERT函數
CAST和CONVERT函數用於轉換值的數據類型。
語法
CAST(value AS datatype)
CONVERT(datatype,value [,style_number])
這兩個函數都可以將輸入的值轉換為指定的數據類型。在一些情況下,還能用CONVERT提供的第三個參數來指定轉換的樣式。例如,當把字符串轉換成日期和時間數據類型(或者進行反向轉換)時,style樣式值可以指定字符串的格式。例如,樣式值101表示'MM/DD/YYYY',而103則表示'DD/MM/YYYY'。有關樣式值和它們各自含義的完整列表,可以在SQL Server聯機叢書的“CAST和CONVERT”一節中找到相關的內容。當把字符串轉換成某些日期和時間數據類型時,一些字符串格式是依賴於語言的。這里推薦要么使用一種獨立於語言的格式,要么使用CONVERT函數,顯示地指定要用的樣式值。這樣,無論登錄時用的語言是什么,SQL Server對代碼的解釋方式都是一樣的。
注意,CAST是ANSI標准SQL,而CONVERT不是;所以,除非需要使用樣式值,否則推薦優先使用CAST函數,以保證代碼盡可能與標准兼容。
以下代碼把字符串文字'20090212'轉換成一個DATE數據類型的值,其實只能提取其當前的系統日期:
以下代碼把當前系統日期和時間值轉換成一個TIME數據類型的值,其實只能提取其當前的系統時間:
還記得DATE和TIME是SQL Server 2008新引入的數據類型吧。前面介紹過,如果在SQL Server 2008之前的版本中只想用日期或時間,就必須把DATETIME或SMALLDATETIME值中不相關的部分設置為“0”。換句話說,要只使用日期,就得把時間部分設置為午夜;要只使用時間,就得把日期設置為基礎日期1900年1月1日。稍后將會介紹把給定的日期和時間值(比如CURRENT_TIMESTAMP)中不相關的部分設置為0的技巧。
以下代碼用樣式值112('YYYYMMDD'),把當前日期和時間值轉換為CHAR(8):
例如,如果當前日期是2009年2月12日,這一代碼將返回'20090212'。記住該樣式是語言無關的,所以當用代碼把結果再轉換回DATETIME類型時,得到的當前日期的時間部分將是午夜:
類似地,要把日期部分設置為基礎日期,可以先用樣式114值('hh:mm:ss.nnn')把當前日期和時間值轉換為CHAR(12):
當用代碼把結果再轉換回DATETIME時,得到的當前的日期部分將是基礎日期:
SWITCHOFFSET函數
SWITCHOFFSET函數可以按指定的時區對輸入的DATETIMEOFFSET值進行調整。
語法
SWITCHOFFSET(datetimeoffset_value,time_zone)
例如,以下代碼將當前系統時間的datetimeoffset值按時區-05:00進行調整:
如果當前系統的datetimeoffset值是February 12,2009 10:00:00.0000000 -08:00,這段代碼將返回以下值:February 12,2009 13:00:00.0000000 -05:00。
而以下代碼則將當前的datetimeoffset值調整為UTC時間:
假設當前的datetimeoffset值為前面提到的那個值,該代碼將返回以下值:
February 12,2009 18:00:00.0000000 +00:00。
TODATETIMEOFFSET函數
語法
TODATETIMEOFFSET(date_and_time_value,time_zone)
這個函數與SWITCHOFFSET函數的區別有兩點。首先,它可以接受的輸入不限於datetimeoffset值,而是支持任何日期和時間數據類型。其次,它不是根據輸入值的原始值和指定的時區之間的差值來調整時間,而只是簡單地用指定的時區將輸入的日期和時間值作為datetimeoffset值返回。例如,如果當前系統的datetimeoffset值是February 12,2009 10:00:00.0000000 -08:00,運行以下代碼:
會得到以下值:February 12,2009 10:00:00.0000000 -05:00。還記得前面的SWITCHOFFSET函數返回值是February 12,2009 13:00:00.0000000 -05:00吧,因為它是根據輸入的時區(-08:00)和指定的時區(-05:00)之間的時區差來調整時間的。
如前所述,TODATETIMEOFFSET函數可以支持任何日期和時間數據類型作為輸入。例如,以下代碼以當前系統日期和時間值作為輸入,將其更改為時區是-05:00的datetimeoffset值:
DATEADD函數
DATEADD函數可以將指定日期的部分作為單位,為輸入的日期和時間值增加指定的數量。
語法
DATEADD(part,n,dt_val)
日期部分的有效值包括year、quarter、month、dayofyear、day、week、weekday、hour、minute、second、millisecond、microsecond,以及nanosecond。最后兩個是SQL Server 2008新增加的。也可以按縮寫格式來指定這些時間部分,例如用yy代替year。要了解相關的細節,請參考SQL Server聯機叢書。
該函數返回值的類型與輸入的日期和時間值的類型相同。如果輸入的是一個字符串文字,輸出的則是DATETIME。
例如,以下代碼為“2009年2月12日”增加1年:
DATEDIFF函數
DATEDIFF返回兩個日期和時間值之間相差的指定部分的計數。
語法
DATEDIFF(part,dt_val1,dt_val2)
例如,以下代碼返回兩個值之間相差的天數:
在SQL Server 2008之前的版本中,可以用以下代碼將當前系統日期和時間值中的時間部分設置為午夜:
這段代碼首先用DATEDIFF函數計算一個錨點(anchor)日期的午夜值(在這個例子中是'20010101')與當前日期和時間之間相差的總天數(也稱為不同的diff值)。接着,再用DATEADD函數為錨點日期增加上一步得到的diff天。這樣就可以得到當前系統日期在午夜的時間值。
有趣的是,如果在這個表達式中用month(月)取代day(天)來作為計數單位,並確保使用的錨點日期是某個月的第1天(如我們這個例子所示),最后得到的結果將是當前月份的第1天:
類似地,用year(年)作為計數單位,並用某年的第1天作為錨點日期,最后得到的將是當前年的第1天。
如果想要得到當前月或當前年的最后一天,只要簡單地把錨點日期修改為月或年的最后1天。例如,以下表達式返回當前月份的最后1天:
DATEPART函數
DATEPART函數返回一個表示給定日期和時間值的指定部分的整數。
語法
DATEPART(part,dt_val)
part參數的有效值包括year、quarter、month、dayofyear、day、week、weekday、hour、minute、second、millisecond、microsecond、nanosecond、TZoffset,以及ISO_WEEK。最后4個part參數值是SQL Server 2008中新增的。如前所述,日期和時間部分的名稱也可以使用縮寫格式,如用yy代替year、用mm代替month、用dd代替day,等等。作為例子,以下代碼返回輸入值的月份部分:
這一代碼將返回整數2.
YEAR、MONTH和DAY函數
YEAR、MONTH,以及DAY函數是DATEPART函數的簡略版本,它們分別返回一個代表輸入日期和時間值中年、月、日部分的整數。
語法
YEAR(dt_val)
MONTH(dt_val)
DAY(dt_val)
例如,以下代碼提取出輸入值的日、月、年部分:
2 MONTH ( ' 20090212 ' ) AS themonth,
3 YEAR ( ' 20090212 ' ) AS theyear;
DATENAME函數
DATENAME函數返回一個表示給定日期和時間值的指定部分的字符串。
語法
DATENAME(part,dt_val)
這個函數與DATEPART類似,它們的part輸入參數的有效值都是相同的。不過,DATENAME返回的是代表請求部分的名字,而不是數字。例如,以下代碼返回給定輸入值的月份的名稱:
回想一下,對於同樣的輸入,前面的DATEPART返回的是整數2。而DATENAME返回的是月份的名稱,該名稱是依賴於語言的。如果當前會話的語言是某種英語,函數調用的返回值將是'February'。如果請求的部分沒有名稱,只是一個數字值(比如年份),則DATENAME函數將它的數字值作為字符串而返回。例如,以下代碼返回'2009':
ISDATE函數
ISDATE接受一個字符串作為輸入,如果能把這個字符串轉換為日期和時間數據類型的值,則返回值1;如果不能,則返回值0。
語法
ISDATE(string)
例如,以下代碼返回1:
而以下代碼則返回0: