使用日期和時間資料
本主題中的下列各節會提供關於使用日期和時間資料類型與函數之範例的資訊。如需所有 Transact-SQL 日期和時間資料類型與函數的概觀,請參閱<日期和時間函數 (Transact-SQL)>。
使用運算子搭配日期和時間資料類型
使用日期和時間格式
字串常值日期和時間格式
未分隔的字串格式
ISO 8601 格式
按字母順序排列的日期格式
數值日期格式
時間格式
ODBC 日期 - 時間格式
轉換 date、time、datetime2 和 datetimeoffset
在字串常值和 time(n)、date、datetime2(n),以及 datetimeoffset(n) 之間的轉換
在日期和時間資料類型之間的轉換
使用 CAST 和 CONVERT 搭配 time、date、datetime2 和 datetimeoffset
CONVERT 函數的樣式引數
SQL Server 日期和時間限制
下層用戶端的回溯相容性
範例
使用運算子搭配日期和時間資料類型
所有日期和時間資料類型都支援關係運算子 (<、<=、>、>= 和 <>)、比較運算子 (=、<、<=、>、>=、<>、!< 和 !>) 和邏輯運算子與布林述詞 (IS NULL、IS NOT NULL、IN、BETWEEN、EXISTS、NOT EXISTS 和 LIKE)。
日期和時間算術運算子
使用日期和時間格式
字串常值格式會影響資料在應用程式中向使用者顯示的方式,但不是 SQL Server 中的基礎整數儲存格式。然而,SQL Server 可能會解譯由應用程式或使用者輸入之字串常值格式的日期值,以便用於儲存或解譯為日期函數,做為不同的日期。解譯會因為字串常值格式、資料類型以及執行階段 SET DATEFORMAT、SET LANGUAGE 和預設語言選項設定的組合而有所不同。
某些字串常值格式並不會受到這些設定的影響。除非您知道格式的設定正確,否則請考慮使用與這些設定無關的格式。ISO 8601 格式與這些設定無關,而且是國際標準。使用字串常值格式的 Transact-SQL 與系統設定有關,可攜性較差。
若要找出下層用戶端的預設字串常值格式,請參閱每個日期和時間資料類型的主題。如需所有 Transact-SQL 日期和時間資料類型與函數的概觀,請參閱<日期和時間函數 (Transact-SQL)>。
不支援 date、datetime2 和 datetimeoffset 類型的 ydm 日期格式。會引發執行階段錯誤。
字串常值日期和時間格式
下表列出各種不同的日期和時間字串格式。建議您使用與 DATEFORMAT 無關而且是多語言的日期 – 時間格式。ISO 8601 格式 '1998-02-23T14:23:05' 和 '1998-02-23T14:23:05 -08:00' 是國際標準的唯一格式。這些格式與 DATEFORMAT 或預設登入語言無關,而且是多語言的。
日期 - 時間部份 |
格式類型 |
格式範例 |
可以結合使用其他格式 |
DATEFORMAT 相依 |
多語言 |
---|---|---|---|---|---|
日期 |
未分隔的 ISO 8601 |
'19980223' |
是 |
否 |
是 |
日期 |
數值 |
'02/23/1998' |
是 |
是 |
否 (DATEFORMAT) |
日期 |
ISO 8601 數值 |
'1998-02-23' |
是 |
否 |
否 |
日期 |
字母順序 |
'23 February 1998' |
是 |
否 |
否 (月份或簡短月份) |
日期 |
ODBC 日期 |
{d '1998-02-23'} |
否 |
否 |
是 |
時間 |
ISO 8601 時間 |
'14:23:05' '10:00:00.123456' |
是 |
否 |
是 |
時間 |
ODBC 時間 |
{t '14:23:05'} |
否 |
否 |
是 |
日期 - 時間 |
ODBC 日期 – 時間 |
{ts '1998-02-23 14:23:05'} |
否 |
否 |
是 |
日期 - 時間 |
ISO 8601 |
'1998-02-23T14:23:05' '1998-02-23T14:23:05 -08:00' |
否 |
否 |
是 date、datetime2、datetimeoffset。 |
日期 - 時間 |
ANSI SQL 標準 |
'1998-02-23 14:23:05' '1998-02-23 14:23:05 -08:00' |
否 |
否 (datetime2、datetimeoffset) 是 (datetime) |
是 date、datetime2、datetimeoffset。 |
日期 - 時間 |
日期和時間的組合 |
'19980223 14:23:05' '02/23/1998 2:23:05 PM' '1998-02-23 10:00:00.123' '23 Feb 1998 14:23:05' |
否 |
是 (日期部分) |
否 |
TimeZone |
TimeZone 格式 |
'+12:00' '01:00' '-08:00' 'Z' |
是 |
否 |
是 |
下列陳述式顯示 SET LANGUAGE 和 SET DATEFORMAT 設定的效果。
DECLARE @Today date = '12/1/2003';
DECLARE @MyTime time = '12:30:22';
DECLARE @MyDatetimeoffset datetimeoffset = '12/1/2003 12:30:22 -5:00';
SET LANGUAGE Italian
-- Returns: Changed language setting to Italiano.
SELECT DATENAME(month, @Today) AS 'Month Name';
-- Returns: dicembre
SELECT CONVERT(VARCHAR(30), @MyDatetimeoffset) AS 'DATETIMEOFFSET';
-- Returns: dic 1 2003 12:30PM -05:00
SELECT DATENAME(hour, @MyTime) As 'Hour Name';
-- Returns: 12
SET LANGUAGE us_english;
-- Returns: Changed language setting to us_english.
SELECT DATENAME(month, @Today) AS 'Month Name';
-- Returns: December
SELECT CONVERT(VARCHAR(30), @MyDatetimeoffset) AS 'DATETIMEOFFSET';
-- Returns: Dec 1 2003 12:30PM -05:00
SELECT DATENAME(hour, @MyTime) As 'Hour Name';
-- Returns: 12
GO
-- Set date format to month, day, year.
SET DATEFORMAT mdy;
GO
DECLARE @datevar date = '12/31/1998';
SELECT @datevar AS DateVar;
-- Returns: 1998-12-31
GO
-- Set date format to year, day, month.
SET DATEFORMAT ydm;
GO
DECLARE @datevar datetimeoffset = '1998/31/12 12:30:22 -05:00';
SELECT @datevar AS DateVar;
-- Returns: Msg 241, Conversion failed when converting
-- date and/or time from character string.
GO
-- Set date format to year, month, day.
SET DATEFORMAT ymd;
GO
DECLARE @datevar date = '12/31/1998';
SELECT @datevar AS DateVar;
-- Returns: 1998-12-31
GO
未分隔的字串格式
您可以將日期資料指定為未分隔的字串。日期資料可以使用 4、6 或 8 位數、空白字串或沒有日期值的時間值來指定。
SET DATEFORMAT 工作階段設定不適用於全數值的日期項目,例如不含分隔符號的數值項目。6 位數或 8 位數字串一律解譯為 ymd。月和日一定是 2 位數。
以下是有效的未分隔字串格式:[19]960415
只含 4 位數的字串會解譯為年。月份和日期設為 1 月 1 日。僅指定 4 位數時,必須包括世紀。
ISO 8601 格式
包含時間格式的 ISO 8601 日期如下:
YYYY-MM-DDThh:mm:ss[.nnnnnnn][{+|-}hh:mm]
YYYY-MM-DDThh:mm:ss[.nnnnnnn]Z (UTC,Coordinated Universal Time)
T 指出日期 - 時間值之時間部份的開始。
若要使用 ISO 8601 格式,您必須在格式中指定每個元素。包括 T、冒號 (:)、+ 或 -,以及句號 (.)。括號指出小數秒或時區時差元件是選擇性的。
時間元件是使用 24 小時格式所指定。
使用 ISO 8601 格式的優點在於它是國際標準。另外,使用此格式所指定的日期和時間值是不明確的。此格式不受登入預設語言設定的 SET DATEFORMAT 和 LANGUAGE 的影響。
以下是以 ISO 8601 格式指定日期 - 時間值的兩個範例:
2004-05-23T14:25:10
2004-05-23T14:25:10.1234567+07:00
按字母順序排列的日期格式
您可以將月份指定為英文的名稱,例如,April 或是英文的縮寫 Apr。這些設定應在工作階段的 LANGUAGE 設定中指定,例如,法文為 avril 或 avr。逗號是選擇性且會忽略大小寫。
以下是使用字母日期格式的一些指導方針:
將日期和時間資料括在單引號 (') 中。
如果只指定年份的後兩位數字,這些數值小於兩位數年份的截止組態選項的後兩位數字時,就與截止年份同一世紀。數值如果大於或等於這個選項的值,就在截止年份的前一個世紀。例如,如果 two digit year cutoff 是 2050 (預設值),則 25 就會被解譯為 2025,而 50 則解譯為 1950。若要避免語意模糊,請使用四位數年份。
如果漏了日的部分,就用當月第一天。
如果以字母形式指定月份,就不適用 SET DATEFORMAT 工作階段設定。
下列格式為 SQL Server 資料類型的有效字母格式。 以括號括住的字元是選擇性的。
Apr[il] [15][,] 1996
Apr[il] 15[,] [19]96
Apr[il] 1996 [15]
[15] Apr[il][,] 1996
15 Apr[il][,][19]96
15 [19]96 apr[il]
[15] 1996 apr[il]
1996 APR[IL] [15]
1996 [15] APR[IL]
數值日期格式
您可以使用數值月份指定日期資料。例如,5/20/97 代表 1997 年 5 月 20 日。當您使用數值日期格式時,請在字串中使用斜線 (/)、連字號 (-) 或句號 (.) 做為分隔符號來指定年、月及日。此字串必須以下列形式出現:
<number>separator<number>separator<number> [<time>] [<time>]
以下為有效的數值格式:
[0]4/15/[19]96 -- (mdy)
[0]4-15-[19]96 -- (mdy)
[0]4.15.[19]96 -- (mdy)
[0]4/[19]96/15 -- (myd)
15/[0]4/[19]96 -- (dmy)
15/[19]96/[0]4 -- (dym)
[19]96/15/[0]4 -- (ydm)
[19]96/[0]4/15 -- (ymd)
工作階段的預設語言 DATEFORMAT 是由登入、SET LANGUAGE 陳述式或 SET DATEFORMAT 陳述式的預設語言所設定。預設登入或 SET LANGUAGE 陳述式將語言設成 us_english 時,日期的預設順序是 mdy。
您可以使用 SET DATEFORMAT 陳述式來變更日期順序。SET DATEFORMAT 陳述式的設定會影響日期值的解譯方式。如果順序與設定不符,就不會將值解譯為日期 (因為超出範圍),否則這些值會被誤解。例如,依 DATEFORMAT 設定而定,可以將 12/10/08 解譯為六種日期之一。四位數的年份將被解譯為年份。
時間格式
SQL Server 可辨識下列的時間資料格式。請將每種格式括在單引號 (') 中。
14:30
14:30[:20:999]
14:30[:20.9]
4am
4 PM
[0]4[:30:20:500]AM
下列陳述式顯示 CAST 函數不同輸入的傳回值。
SELECT CAST('01/01/2000 14:30' AS datetime2)
--Returns: 2000-01-01 14:30:00.0000000
SELECT CAST('01/01/2000 14:30:20:999' AS datetime2)
-- Returns: 2000-01-01 14:30:20.9990000
SELECT CAST('01/01/2000 14:30:20.9' AS datetime2)
-- Returns: 2000-01-01 14:30:20.9000000
SELECT CAST('01/01/2000 4am' AS datetime2)
-- Returns: 2000-01-01 04:00:00.0000000
SELECT CAST('01/01/2000 4 PM' AS datetime2)
-- Returns: 2000-01-01 16:00:00.0000000
SELECT CAST('01/01/2000 04:30:20:500AM' AS datetime2)
-- Returns: 2000-01-01 04:30:20.5000000
SELECT CAST('01/01/2000 04:30:20:500 AM' AS datetime2)
-- Returns: 2000-01-01 04:30:20.5000000
GO
您可以指定 AM 或 PM 後置字元,以指示時間值在中午 12 點前或 12 點後。AM 或 PM 不區分大小寫。
小時值可以採用 12 小時制或 24 小時制指定。小時值的解譯如下。
無論您是否指定 AM,只要小時的值為 00 就表示午夜之後 (AM) 的小時。小時等於 00 時,無法指定 PM。
如果沒有指定 AM 或 PM,那麼從 01 到 11 小時的值就代表正午之前的小時值。如果指定為 AM 也代表正午之前的小時值。如果指定為 PM 才代表正午之後的小時。
如果沒有指定 AM 或 PM,小時值 12 就代表從正午開始的小時值。如果指定為 AM,則代表從午夜開始的小時。如果指定為 PM,則代表從正午開始的小時。例如:12:01 就是正午之後的 1 分鐘,也就是 12:01 PM, 而 12:01 AM 則是午夜之後1 分鐘。指定為 12:01 AM 與指定為 00:01 或 00:01 AM 是相同的。
如果未指定 AM 或 PM,從 13 到 23 的小時值就代表正午之後的小時。如果指定為 PM,同樣也代表正午之後的小時。不過若小時值從 13 到 23 則無法指定為 AM。
24 這個小時值是無效的,請使用 12:00 AM 或 00:00 來表示午夜。
毫秒前可以用冒號 (:) 或句號 (.)。如果以冒號開頭,數字是指千分之一秒。如果以句號開頭,一位數代表十分之一秒、二位數代表百分之一秒、三位數代表千分之一秒。例如,12:30:20:1 表示 12:30 過 20 又千分之一秒;12:30:20.1 表示 12:30 過 20 又十分之一秒。
ODBC 日期 - 時間格式
ODBC API 會定義逸出序列來代表日期和時間值,供 ODBC 呼叫時間戳記資料。SQL Server 的 OLE DB 語言定義 (DBGUID-SQL) 和 Microsoft OLE DB 提供者也支援 ODBC 時間戳記格式。使用 ADO、OLE DB 與 ODBC 架構 API 的應用程式都可以使用這個 ODBC 時間戳記格式來代表日期和時間值。
SQL Server 永遠會將 ODBC 資料視為屬於 datetime 資料類型。
ODBC 時間戳記格式逸出序列的格式如下:
{ literal_type 'constant_value' }
literal_type
指定逸出序列的類型。下列都是 literal_type 的有效引數。d = 只有日期
t = 只有時間
ts = 時間戳記 (時間 + 日期)
'constant_value'
是逸出序列的值。constant_value 必須遵循以下每個 literal_type 的格式。literal_type
constant_value 格式
d
YYYY-MM-DD
t
hh:mm:ss[.fff]
ts
YYYY-MM-DDhh:mm:ss[.fff]
ODBC 時間與日期常數的範例如下所示:
{ ts '1998-05-02 01:23:56.123' }
{ d '1990-10-02' }
{ t '13:33:41' }
請勿將 ODBC 與 OLE DB 時間戳記資料類型名稱跟 Transact-SQLtimestamp 資料類型名稱混為一談。ODBC 與 OLE DB 時間戳記資料類型是記錄日期和時間。Transact-SQLtimestamp 資料類型是二進位資料類型,不含與時間相關的值。
轉換 date、time、datetime2 和 datetimeoffset
有兩種方式可以在不同的資料類型之間轉換:明確和隱含。隱含轉換時,不需要使用 CAST 或 CONVERT 函數。明確轉換時,需要使用 CAST 或 CONVERT 函數。
在字串常值和 time(n)、date、datetime2(n),以及 datetimeoffset(n) 之間的轉換
如果字串的所有部分都是有效的格式,則允許從字串常值轉換為日期和時間類型。否則,就會引發執行階段錯誤。
不指定樣式的隱含轉換或明確轉換 (從日期和時間類型轉換為字串常值) 都是目前工作階段的預設格式。
若是從 date、time、datetime2 和 datetimeoffset 資料類型到字元字串的明確轉換,則會套用 SQL 標準格式 YYY-MM-DD hh:mi:ss.[nnnnnnn],CONVERT 樣式 121。若是 datetime 和 smalldatetime 資料類型,則會套用 CONVERT 樣式 0 格式 mon dd yyyy hh:miAM (或 PM)。
下表顯示在 date、time、datetime2 和 datetimeoffset 類型與字串常值之間轉換的規則。
輸入字串常值 |
date |
time(n) |
datetime2(n) |
datetimeoffset(n) |
---|---|---|---|---|
ODBC DATE |
請參閱注意 1。 |
請參閱注意 1。 |
請參閱注意 1。 |
請參閱注意 1。 |
ODBC TIME |
請參閱注意 1。 |
請參閱注意 1。 |
請參閱注意 1。 |
請參閱注意 1。 |
ODBC DATETIME |
請參閱注意 1。 |
請參閱注意 1。 |
請參閱注意 1。 |
請參閱注意 1。 |
只限 DATE |
一般 |
提供預設值 |
TIME 部分預設為 00:00:00。 |
TIME 部分預設為 00:00:00。TIMEZONE 預設為 +00:00。 |
只限 TIME |
提供預設值 |
一般 |
DATE 部分預設為 1900-1-1。 |
DATE 部分預設為 1900-1-1。TIMEZONE 將預設為 +00:00。 |
只限 TIMEZONE |
提供預設值 |
提供預設值 |
提供預設值 |
提供預設值 |
DATE + TIME |
使用輸入字串的 DATE 部分。 |
使用輸入字串的 TIME 部分。 |
一般 |
TIMEZONE 預設為 +00:00。 |
DATE + TIMEZONE |
不允許 |
不允許 |
不允許 |
不允許 |
TIME + TIMEZONE |
提供預設值 |
使用輸入字串的 TIME 部分。 |
DATE 部分預設為 1900-1-1。忽略 TIMEZONE 輸入。 |
DATE 部分預設為 1900-1-1。 |
DATE + TIME + TIMEZONE |
將使用本地 DATETIME 的 DATE 部分。 |
將使用本地 DATETIME 的 TIME 部分。 |
將使用本地 DATETIME。 |
一般 |
轉換注意事項
ODBC 字串常值會對應到 datetime 資料類型。從 ODBC DATETIME 常值到 date、time、datetime2 或 datetimeoffse 類型的任何指派作業都會造成 datetime 和轉換規則所定義的這些類型之間的隱含轉換。
datetime 的毫秒有效位數精確度為三百分之一秒 (相當於 3.33 毫秒或 0.00333 秒)。這些值會進位到 .000、.003 或 .007 秒的遞增。由於 '.999' 超出有效位數,'08/22/1995 10:15:19:999' 會進位。
若是 time(3)、datetime2(3) 或 datetimeoffset(3),毫秒有效位數的精確度為一毫秒。因此,'1995-8-22 10:15:19:999 ' 將不會被進位。
輸入 TIMEZONE 時差部分的 hh 和 mm 應該永遠是兩位數。正負號 + 或 – 都是強制性的。
在日期和時間資料類型之間的轉換
本章節的表格說明要如何將下列的每一個日期和時間資料類型轉換成其他日期和時間資料類型:
date
time(n)
datetime
smalldatetime
datetimeoffset(n)
datetime2
日期資料類型
下表說明當 date 資料類型轉換成其他日期和時間資料類型時,將會發生哪些事情。
資料類型要轉換成 |
轉換詳細資料 |
---|---|
time(n) |
轉換失敗,而且引發了錯誤訊息 206:「運算元類型衝突: date 與 time 不相容」。 |
datetime |
將會複製日期。下列程式碼顯示將 date 值轉換成 datetime 值的結果。
|
smalldatetime |
當 date 值在 smalldatetime 範圍內時,將會複製日期元件,而時間元件會設定為 00:00:00.000。當 date 值在 smalldatetime 值的範圍以外時,將會引發錯誤訊息 242:「將 date 資料類型轉換成 smalldatetime 資料類型時,產生超出範圍的值」,而 smalldatetime 值會設定為 NULL。 下列程式碼顯示將 date 值轉換成 smalldatetime 值的結果。
|
datetimeoffset(n) |
將會複製日期,並將時間設定為 00:00.0000000 +00:00。 下列程式碼顯示將 date 值轉換成 datetimeoffset(3) 值的結果。
|
datetime2(n) |
將會複製日期元件,並將時間元件設定為 00:00.000000。 下列程式碼顯示將 date 值轉換成 datetime2(3) 值的結果。
|
time(n) 資料類型
下表說明當 time 資料類型轉換成其他日期和時間資料類型時,將會發生哪些事情。
資料類型要轉換成 |
轉換詳細資料 |
---|---|
time(n) |
將會複製時、分和秒。當目標有效位數小於來源有效位數時,小數秒數將會被截斷,以配合目標有效位數。 下列範例顯示將 time(4) 值轉換成 time(3) 值的結果。
|
date |
轉換失敗,而且引發了錯誤訊息 206:「運算元類型衝突: date 與 time 不相容」。 |
datetime |
將會複製時、分和秒的值,而且日期元件會設定為 '1900-01-01'。如果 time(n) 值的小數秒數有效位數大於三位數,datetime 結果將會被截斷。 下列程式碼顯示將 time(4) 值轉換成 datetime 值的結果。
|
smalldatetime |
日期會設定為 '1900-01-01',而且會複製時和分的值。秒和小數秒數會設定為 0。 下列程式碼顯示將 time(4) 值轉換成 smalldatetime 值的結果。
|
datetimeoffset(n) |
日期會設定為 '1900-01-01',而且會複製時間。時區時差會設定為 +00:00。如果 time(n) 值的小數秒數有效位數大於 datetimeoffset(n) 值的有效位數,此值會被截斷以配合其大小。 下列範例顯示將 time(4) 值轉換成 datetimeoffset(3) 類型的結果。
|
datetime2(n) |
日期會設定為 '1900-01-01' 且會複製時間元件,而時區時差會設定為 00:00。如果 datetime2(n) 值的小數秒數有效位數大於 time(n) 值,此值將會被截斷以配合其大小。 下列範例顯示將 time(4) 值轉換成 datetime2(2) 值的結果。
|
datetime 資料類型
下表說明當 datetime 資料類型轉換成其他日期和時間資料類型時,將會發生哪些事情。
資料類型要轉換成 |
轉換詳細資料 |
---|---|
date |
年、月和日都會複製。時間元件會設定為 00:00:00.000。 下列程式碼顯示將 date 值轉換成 datetime 值的結果。
|
time(n) |
時間元件會複製,而日期元件會設定為 '1900-01-01'。如果 time(n) 值的小數有效位數大於三位數,此值將會被截斷以配合其大小。 下列範例顯示將 time(4) 值轉換成 datetime 值的結果。
|
smalldatetime |
將會複製時和分。秒和小數秒數會設定為 0。 下列程式碼顯示將 smalldatetime 值轉換成 datetime 值的結果。
|
datetimeoffset(n) |
日期和時間元件都會複製。時區則會被截斷。如果 datetimeoffset(n) 值的小數有效位數大於三位數,此值將會被截斷。 下列範例顯示將 datetimeoffset(4) 值轉換成 datetime 值的結果。
|
datetime2(n) |
將會複製日期和時間。如果 datetime2(n) 值的小數有效位數大於三位數,此值將會被截斷。 下列範例顯示將 datetime2(4) 值轉換成 datetime 值的結果。
|
smalldatetime 資料類型
下表說明當 smalldatetime 資料類型轉換成其他日期和時間資料類型時,將會發生哪些事情。
資料類型要轉換成 |
轉換詳細資料 |
---|---|
date |
年、月和日都會複製。 下列程式碼顯示將 smalldatetime 值轉換成 date 值的結果。
|
time(n) |
將會複製時、分和秒。小數秒數會設定為 0。 下列程式碼顯示將 smalldatetime 值轉換成 time(4) 值的結果。
|
datetime |
smalldatetime 值會複製到 datetime 值。小數秒數會設定為 0。 下列程式碼顯示將 smalldatetime 值轉換成 datetime 值的結果。
|
datetimeoffset(n) |
smalldatetime 值會複製到 datetimeoffset(n) 值。小數秒數會設定為 0,而時區時差會設定為 +00:0。 下列程式碼顯示將 smalldatetime 值轉換成 datetimeoffset(4) 值的結果。
|
datetime2(n) |
smalldatetime 值會複製到 datetime2(n) 值。小數秒數會設定為 0。 下列程式碼顯示將 smalldatetime 值轉換成 datetime2(4) 值的結果。
|
datetimeoffset(n) 資料類型
下表說明當 datetimeoffset(n) 資料類型轉換成其他日期和時間資料類型時,將會發生哪些事情。
資料類型要轉換成 |
轉換詳細資料 |
---|---|
date |
年、月和日都會複製。 下列程式碼顯示將 datetimeoffset(4) 值轉換成 date 值的結果。
|
time(n) |
將會複製時、分、秒和小數秒數。時區值則會被截斷。如果 datetimeoffset(n) 值的有效位數大於 time(n) 值的有效位數,此值將會被截斷。 下列程式碼顯示將 datetimeoffset(4) 值轉換成 time(3) 值的結果。
|
datetime |
日期和時間值都會複製,而時區則會被截斷。如果 datetimeoffset(n) 值的小數有效位數大於三位數,此值將會被截斷。 下列程式碼顯示將 datetimeoffset(4) 值轉換成 datetime 值的結果。
|
smalldatetime |
將會複製日期、時和分。秒數會設定為 0。 下列程式碼顯示將 datetimeoffset(3) 值轉換成 smalldatetime 值的結果。
|
datetime2(n) |
日期和時間會複製到 datetime2 值,而時區則會被截斷。如果 datetime2(n) 值的有效位數大於 datetimeoffset(n) 值的有效位數,小數秒數會被截斷以配合其大小。 下列程式碼顯示將 datetimeoffset(4) 值轉換成 datetime2(3) 值的結果。
|
datetime2 資料類型
下表說明當 datetime2 資料類型轉換成其他日期和時間資料類型時,將會發生哪些事情。
資料類型要轉換成 |
轉換詳細資料 |
---|---|
date |
年、月和日都會複製。 下列程式碼顯示將 datetime2(4) 值轉換成 date 值的結果。
|
time(n) |
將會複製時、分、秒和小數秒數。 下列程式碼顯示將 datetime2(4) 值轉換成 time(3) 值的結果。
|
datetime |
日期和時間值都會複製。如果 datetimeoffset(n) 值的小數有效位數大於三位數,此值將會被截斷。 下列程式碼顯示將 datetime2 值轉換成 datetime 值的結果。
|
smalldatetime |
將會複製日期、時和分。秒數會設定為 0。 下列程式碼顯示將 datetime2 值轉換成 smalldatetime 值的結果。
|
datetimeoffset(n) |
datetime2(n) 值會複製到 datetimeoffset(n) 值。時區時差會設定為 +00:0。如果 datetime2(n) 值的有效位數大於 datetimeoffset(n) 值的有效位數,此值將會被截斷以配合其大小。 下列程式碼顯示將 datetime2(5) 值轉換成 datetimeoffset(3) 值的結果。
|
使用 CAST 和 CONVERT 搭配 time、date、datetime2 和 datetimeoffset
本節提供有關在日期和時間資料類型之間轉換的資訊。
轉換成 datetimeoffset
- 每當包含時區的 datetimeoffset 值要從沒有時區的值隱含衍生 (例如,在簡單指派作業中) 時,就會將沒有時區的值視為本地,而目前預設的時區 (00:00) 替代則會從該值減去以提供 UTC。
- 當您將非時區的資料類型轉換為 datetimeoffset 以進行下列轉換時,永遠都會附加 UTC 時區 (00:00):
date 到datetimeoffset
time 到datetimeoffset
datetime2 到datetimeoffset
datetime 或 smalldatetime 到 datetimeoffset
字串常值為有效的 date、time 或 datetime,而沒有將時區格式設定為 datetimeoffset
從 datetimeoffset 轉換
當您從 datetimeoffset 轉換為下列非時區類型時,樣式 0 (預設值) 永遠表示 date、time、datetime2、datetime 或 smalltime 傳回值為保留之時區時差的本地格式,而樣式 1 則永遠表示 UTC 格式。
每當沒有時區的日期或時間值在下列任一種轉換中隱含衍生時,會將 datetimeoffset 值視為 UTC。保留的時區替代會加入到值中以提供本地時間。結果為沒有任何時區時差的本地時間。
datetimeoffset 到date
datetimeoffset 到time
datetimeoffset 到datetime2
datetimeoffset 到 datetime 或 smalldatetime
0 和 1 樣式無法用於 datetimeoffset 到字串的轉換。因此,請先從 datetimeoffset 轉換為 datetime2 或 datetime,然後從轉換為 varchar 或 char。
如果現有的 CONVERT 樣式包含時間部分,而且是從 datetimeoffset 轉換為字串,則會包含時區時差 (樣式 127 除外)。如果您不要時區時差,您可以先轉換為 datetime2,然後再轉換為字串。
所有現有的日期和時間樣式都會將任何 datetimeoffset 套用到字串轉換,而且會保留時區時差。
輸入字串時區時差部分的 hh 和 mm 應該永遠是兩位數,而且正負號 + 或 – 都是強制性的。
轉換時遺失的資訊
當您從 datetime2 或 datetimeoffset 轉換為 date 時,沒有進位,而且會明確擷取日期部分。若是 datetimeoffset,會在本地日期和時間 (但不會在 UTC 值) 上執行擷取。
若是從 datetimeoffset 隱含轉換為 date、time、datetime2, datetime 或 smalldatetime,則會根據本地日期和時間值轉換 (為保存的時區時差)。例如,將 datetimeoffset(3) 的值 2006-10-21 12:20:20.999 -8:00 轉換為 time(3) 時,結果為 12:20:20.999 而非 20:20:20.999(UTC)。
轉換時截斷
- 允許從較高的有效位數時間值轉換為較低的有效位數值。較高的有效位數值會被截斷,以配合較低的有效位數類型。
毫秒的轉換
如果樣式包含時間格式 hh:mm:ss.mmm,time(n)、datetime2(n) 和 datetimeoffset(n) 的格式將會變成 hh:mm:ss.[nnnnnnn]。位數取決於指定的類型。如果您僅要毫秒有效位數,請先轉換為 datetime2(3),然後再轉換為字串。
若是樣式 9、109、13、113、21、121、130 和 131,轉換字串時,不支援 time、datetime2 和 datetimeoffset 類型之分隔符號前的冒號 (:) 毫秒。包含以上任何樣式的輸出字串格式都會轉換為句號 (.)。
CONVERT 函數的樣式引數
下表針對 CONVERT 函數的樣式引數,列出 date、time、datetime2 和 datetimeoffset 值。如需有關樣式的詳細資訊,請參閱<CAST 和 CONVERT (Transact-SQL)>的「引數」一節。
樣式 |
Associated standard |
Input/Output (3) format |
date |
time(n) |
datetime2(n) |
datetimeoffset(n) |
---|---|---|---|---|---|---|
0 或 100 (1,2) |
預設值 |
mon dd yyyy hh:miAM (或 PM) |
Jan 1 2001 |
12:20PM |
Jan 1 2001 12:20PM |
Jan 1 2001 12:20PM -08:00 |
101 |
美式英文 |
mm/dd/yyyy |
01/01/2001 |
- |
01/01/2001 |
01/01/2001 |
102 |
ANSI |
yy.mm.dd |
2001.01.01 |
- |
2001.01.01 |
2001.01.01 |
103 |
英式英文/法文 |
dd/mm/yy |
01/01/2001 |
- |
01/01/2001 |
01/01/2001 |
104 |
德文 |
dd.mm.yy |
01.01.2001 |
- |
01.01.2001 |
01.01.2001 |
105 |
義大利文 |
dd-mm-yy |
01-01-2001 |
- |
01-01-2001 |
01-01-2001 |
106(1) |
- |
dd mon yy |
01 Jan 2001 |
- |
01 Jan 2001 |
01 Jan 2001 |
107(1) |
- |
Mon dd, yy |
Jan 01, 2001 |
- |
Jan 01, 2001 |
Jan 01, 2001 |
108 |
- |
hh:mi:ss |
- |
12:20:20 |
12:20:20 |
12:20:20 |
9 或 109 (1,2) |
預設值 + 毫秒 |
mon dd yyyy hh:mi:ss:mmmAM (或 PM) |
Jan 1 2001 |
12:20:20.1234567AM |
Jan 1 2001 12:20:20.1234567PM |
Jan 1 2001 12:20:20:1230000PM -08:00 |
110 |
美國 |
mm-dd-yy |
01-01-2001 |
- |
01-01-2001 |
01-01-2001 |
111 |
日本 |
yy/mm/dd |
2001/01/01 |
- |
2001/01/01 |
2001/01/01 |
112 |
ISO |
yymmdd |
20010101 |
- |
20010101 |
20010101 |
13 或 113 (1,2) |
歐洲預設值 + 毫秒 |
dd mon yyyy hh:mi:ss:mmm(24h) |
01 Jan 2001 |
12:20:20.1234567 |
01 Jan 2001 12:20:20.1234567 |
01 Jan 2001 12:20:20:1230000 -08:00 |
114 |
- |
hh:mi:ss:mmm(24h) |
- |
12:20:20.1234567 |
12:20:20.1234567 |
12:20:20:1230000 -08:00 |
20 或 120 (2) |
ODBC 標準 |
yyyy-mm-dd hh:mi:ss(24h) |
2001-01-01 |
12:20:20 |
2001-01-01 12:20:20 |
2001-01-01 12:20:20 -08:00 |
21 或 121 (2) |
ODBC 標準 (含毫秒) |
yyyy-mm-dd hh:mi:ss.mmm(24h) |
2001-01-01 |
12:20:20.1234567 |
2001-01-01 12:20:20.1234567 |
2001-01-01 12:20:20.1230000 -08:00 |
126 (4) |
ISO8601 |
yyyy-mm-ddThh:mi:ss.mmm (無空格) |
2001-01-01 |
12:20:20.1234567 |
2001-01-01T 12:20:20.1234567 |
2001-01-01T 12:20:20.1234567 |
127(6, 7) |
具有時區 Z 的 ISO8601。 |
yyyy-mm-ddThh:mi:ss.mmmZ (無空格) |
2001-01-01 |
12:20:20.1234567Z |
2001-01-01T 12:20:20.1234567Z |
2001-01-01T20:20:20.1230000Z |
130 (1,2) |
回曆 (5) |
dd mon yyyy hh:mi:ss:mmmAM |
01 Jan 2001 |
12:20:20.1230000PM |
01 Jan 2001 12:20:20.1230000PM |
1 Jan 2001 12:20:20:1230000PM -08:00 |
131 (2) |
回曆 (5) |
dd/mm/yy hh:mi:ss:mmmAM |
01/01/2001 |
12:20:20.1230000PM |
01/01/2001 12:20:20.1230000PM |
01/01/2001 12:20:20.1230000PM -08:00 |
1 這些樣式值會傳回不具決定性的結果。其中包括所有 (yy) (不含世紀) 樣式和 (yyyy) (含世紀) 樣式的子集。
2 預設值 (style0 或 100、9 或 109、13 或 113、20 或 120 及 21 或 121) 一律會傳回世紀 (yyyy)。
3 當轉換成 datetime 時輸入;當轉換成字元資料時輸出。
4 專為了 XML 而設計。如果是從 datetime 或 smalldatetime 轉換成字元資料,輸出格式會符合上表的描述。
5 回曆是含有多種變體的一種日曆系統。SQL Server 使用科威特演算法。
6 只有在從字元資料轉換為 datetime 或 smalldatetime 時才支援。當只代表日期或只代表時間元件的字元資料轉換為 datetime 或 smalldatetime 資料類型時,未指定的時間元件會設定為 00:00:00.000,而未指定的日期元件則會設定為 1900-01-01。
7 選擇性的時區指標 Z 可用來輕鬆地將具有時區資訊的 XML datetime 值對應到沒有時區的 SQL Serverdatetime 值。Z 是時區 UTC - 0 的指標。
SQL Server 日期和時間限制
在下列清單中,日期和時間指的是包含日期或時間部分的任何日期 – 時間資料類型。
不支援 datetimeoffset 的伺服器端日光節約時間 (DST)。
日期不支援凱撒曆。
不支援表示午夜「24」時的時間。
不支援超過「59」之「閏秒」的時間。
不支援毫秒有效位數為「1 奈秒」以上的時間。
不支援時間的時區。
不支援 SQL 標準 INTERVAL 作業。
下層用戶端的回溯相容性
有些下層用戶端不支援在 SQL Server 2008 中新增的 time、date、datetime2 和 datetimeoffset 資料類型。下表顯示在 SQL Server 2008 的上層執行個體與下層用戶端間對應的類型。
SQL Server 2008 資料類型 |
傳遞至下層用戶端的預設字串常值格式 |
下層 ODBC |
下層 OLEDB |
下層 JDBC |
下層 SQLCLIENT |
---|---|---|---|---|---|
time |
hh:mm:ss[.nnnnnnn] |
SQL_WVARCHAR 或 SQL_VARCHAR |
DBTYPE_WSTR 或 DBTYPE_STR |
Java.sql.String |
字串或 SqString |
date |
YYYY-MM-DD |
SQL_WVARCHAR 或 SQL_VARCHAR |
DBTYPE_WSTR 或 DBTYPE_STR |
Java.sql.String |
字串或 SqString |
datetime2 |
YYYY-MM-DD hh:mm:ss[.nnnnnnn] |
SQL_WVARCHAR 或 SQL_VARCHAR |
DBTYPE_WSTR 或 DBTYPE_STR |
Java.sql.String |
字串或 SqString |
datetimeoffset |
YYYY-MM-DD hh:mm:ss[.nnnnnnn] [+|-]hh:mm |
SQL_WVARCHAR 或 SQL_VARCHAR |
DBTYPE_WSTR 或 DBTYPE_STR |
Java.sql.String |
字串或 SqString |
範例
A. 比較日期和時間資料類型
下列範例會比較將字串常值轉換成每個日期和時間資料類型的結果。嘗試 CAST 為字串常值時,如果包含的毫秒有效位數多於 smalldatetime 或 datetime 所允許的位數,將會引發錯誤。
SELECT
CAST('2007-05-08 12:35:29. 1234567 +12:15' AS time(7)) AS 'time'
,CAST('2007-05-08 12:35:29. 1234567 +12:15' AS date) AS 'date'
,CAST('2007-05-08 12:35:29.123' AS smalldatetime) AS
'smalldatetime'
,CAST('2007-05-08 12:35:29.123' AS datetime) AS 'datetime'
,CAST('2007-05-08 12:35:29. 1234567 +12:15' AS datetime2(7)) AS
'datetime2'
,CAST('2007-05-08 12:35:29.1234567 +12:15' AS datetimeoffset(7)) AS
'datetimeoffset';
資料類型 |
輸出 |
---|---|
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(7) |
2007-05-08 12:35:29.1234567 |
datetimeoffset(7) |
2007-05-08 12:35:29.1234567 +12:15 |
B. 取得目前的系統日期和時間
下列範例會示範如何使用 SQL Server 系統函數來傳回目前的日期和時間。
SELECT SYSDATETIME() AS 'SYSDATETIME'
--Results
--SYSDATETIME
--2007-10-22 14:10:41.7984554
--(1 row(s) affected)
SELECT SYSDATETIMEOFFSET() AS 'SYSDATETIMEOFFSET'
--Results
--SYSDATETIMEOFFSET
--2007-10-22 14:11:34.2607172 -0
--(1 row(s) affected)
SELECT SYSUTCDATETIME() AS 'SYSUTCDATETIME'
--Results
--SYSUTCDATETIME
--2007-10-22 21:12:11.7069470
--(1 row(s) affected)
SELECT CURRENT_TIMESTAMP AS 'CURRENT_TIMESTAMP'
--Results
--CURRENT_TIMESTAMP
-------------------------
--2007-10-22 14:12:33.320
--(1 row(s) affected)
SELECT GETDATE() AS 'GETDATE'
--Results
--GETDATE
--2007-10-22 14:13:57.943
--(1 row(s) affected)
SELECT GETUTCDATE() AS 'GETUTCDATE'
--Results
--GETUTCDATE
--2007-10-22 21:14:35.657
--(1 row(s) affected)
C. 搜尋一天中的所有 datetime2 值
- 下列範例會示範如何搜尋一天中的所有日期和時間值。
-- Create a table that contains with the following dates:
-- The last date-time in 2005-04-06, '2005-04-06 23:59:59.9999999'
-- The first date-time in 2005-04-07, '2005-04-07 00:00:00.0000000'
-- The last date-time in 2005-04-07, '2005-04-07 23:59:59.9999999'
-- The first date-time in 2005-04-08, '2005-04-08 00:00:00.0000000'
CREATE TABLE #Search
(
MyDate datetime2
);
INSERT INTO #Search(MyDate)VALUES('2005-04-06 23:59:59.9999999');
INSERT INTO #Search(MyDate)VALUES('2005-04-07 00:00:00.0000000');
INSERT INTO #Search(MyDate)VALUES('2005-04-07 23:59:59.9999999');
INSERT INTO #Search(MyDate)VALUES('2005-04-08 00:00:00.0000000');
-- The following four SELECT statements show different ways to find
-- only the two rows that contain 2005-04-07 dates.
--Use CONVERT.
SELECT MyDate
FROM #Search
WHERE CONVERT(date,MyDate) = '2005-04-07';
--Use >= and <=.
SELECT MyDate
FROM #Search
WHERE MyDate >= '2005-04-07 00:00:00.0000000'
AND MyDate <= '2005-04-07 23:59:59.9999999';
--Use > and <.
SELECT MyDate
FROM #Search
WHERE MyDate > '2005-04-06 23:59:59.9999999'
AND MyDate < '2005-04-08 00:00:00.0000000';
--Use BETWEEN AND.
SELECT MyDate
FROM #Search
WHERE MyDate BETWEEN '2005-04-07 00:00:00.0000000'
AND '2005-04-07 23:59:59.9999999';
DROP TABLE #Search
GO
D. 搜尋一天中的時間週期
下列範例會示範如何搜尋具有時間值的日期來尋找時間範圍。
-- Create a table called Search and insert
-- five different time values for the same
-- date.
CREATE TABLE #Search
(
MyDate datetime2
);
INSERT INTO #Search(MyDate)VALUES('2005-04-06 08:59:59.9999999');
INSERT INTO #Search(MyDate)VALUES('2005-04-06 09:00:00.0000000');
INSERT INTO #Search(MyDate)VALUES('2005-04-06 09:00:00.9999999');
INSERT INTO #Search(MyDate)VALUES('2005-04-06 16:59:59.9999999');
INSERT INTO #Search(MyDate)VALUES('2005-04-06 17:00:00.0000000');
-- The following SELECT statements show different ways
-- to search for dates that have time values to find a
-- time range.
--Using CONVERT with time (0) to ignore fractional seconds
SELECT MyDate
FROM #Search
WHERE CONVERT(time(0),MyDate) = '09:00:00';
--Returns two rows (ignores fractional seconds):
--2005-04-06 08:59:59.9999999
--2005-04-06 09:00:00.0000000
--Using CONVERT with time (7) to include fractional seconds
SELECT MyDate
FROM #Search
WHERE CONVERT(time(7),MyDate) = '09:00:00';
--Returns one row (matches fractional seconds):
--2005-04-06 09:00:00.0000000
--Each of the SELECT statements below use CONVERT
--to find all times in an eight-hour period.
--Use CONVERT with >= and <=.
SELECT MyDate
FROM #Search
WHERE CONVERT(time(7),MyDate) >= '09:00:00.0000000'
AND CONVERT(time(7),MyDate) <= '16:59:59.9999999'
--Use CONVERT with > and <.
SELECT MyDate
FROM #Search
WHERE CONVERT(time(7),MyDate) > '08:59:59.9999999'
AND CONVERT(time(7),MyDate) < '17:00:00.0000000';
--Use CONVERT with BETWEEN AND
SELECT MyDate
FROM #Search
WHERE CONVERT(time(7),MyDate) BETWEEN '09:00:00.0000000'
AND '16:59:59.9999999';
DROP TABLE #Search
GO
E. 使用 DATEPART 和 DATEADD 來尋找日期部分的第一天和最後一天
下列範例會示範如何傳回 datepart 的第一天或最後一天。
-- When several months, quarters, or years are added to the base
-- year,1900-01-01, the returned day is the first day of a month.
-- To calculate the last day of the current month, you need to
--
-- 1. Find the difference in months between today and the base
-- year (0 ='1900-01-01'). This is accomplished by
--
-- DATEDIFF(month, 0, SYSDATETIME())
-- 2. Add that number of months plus 1 to the base year (0)
-- to obtain the first day of the next month.
-- DATEADD(month, DATEDIFF(month, 0, SYSDATETIME()) + 1, 0)
-- 3. Subtract 1 day.
--
--Find the first day of the current month.
SELECT DATEADD(month, DATEDIFF(month, 0, SYSDATETIME()), 0);
--Find the last day of the current month.
SELECT DATEADD(month, DATEDIFF(month, 0, SYSDATETIME()) + 1, 0) - 1;
-- Find the first day of the current quarter.
SELECT DATEADD(quarter, DATEDIFF(quarter, 0, SYSDATETIME()), 0);
-- Find the last day of the current quarter.
SELECT DATEADD(quarter, DATEDIFF(quarter, -1, SYSDATETIME()), -1);
-- Find the first day of the current year.
SELECT DATEADD(year, DATEDIFF(year, 0, SYSDATETIME()), 0);
-- Find the last day of the current year.
SELECT DATEADD(year, DATEDIFF(year, -1, SYSDATETIME()), -1);
F. 使用使用者定義的日期部分引數代表 DATEADD、DATEDIFF、DATENAME 及 DATEPART
下列範例會建立一個使用者定義的純量函數,它可將常數加入 datetime2 值的任何部分。
USE tempdb
GO
CREATE FUNCTION UserDateadd
(
@datepart nvarchar(11)
,@number int
,@date datetime2
)
RETURNS datetime2
AS
BEGIN
DECLARE @Return datetime2
SELECT @Return = CASE @datepart
WHEN 'year' THEN DATEADD(year,@number,@date)
WHEN 'yy' THEN DATEADD(year,@number,@date)
WHEN 'yyyy' THEN DATEADD(year,@number,@date)
WHEN 'quarter' THEN DATEADD(quarter,@number,@date)
WHEN 'qq' THEN DATEADD(quarter,@number,@date)
WHEN 'month' THEN DATEADD(month,@number,@date)
WHEN 'mm' THEN DATEADD(month,@number,@date)
WHEN 'm' THEN DATEADD(month,@number,@date)
WHEN 'dayofyear' THEN DATEADD(dayofyear,@number,@date)
WHEN 'dy' THEN DATEADD(dayofyear,@number,@date)
WHEN 'y' THEN DATEADD(dayofyear,@number,@date)
WHEN 'day' THEN DATEADD(day,@number,@date)
WHEN 'dd' THEN DATEADD(day,@number,@date)
WHEN 'd' THEN DATEADD(day,@number,@date)
WHEN 'week' THEN DATEADD(week,@number,@date)
WHEN 'wk' THEN DATEADD(week,@number,@date)
WHEN 'ww' THEN DATEADD(week,@number,@date)
WHEN 'weekday' THEN DATEADD(weekday,@number,@date)
WHEN 'wk' THEN DATEADD(weekday,@number,@date)
WHEN 'w' THEN DATEADD(weekday,@number,@date)
WHEN 'hour' THEN DATEADD(hour,@number,@date)
WHEN 'hh' THEN DATEADD(hour,@number,@date)
WHEN 'minute' THEN DATEADD(minute,@number,@date)
WHEN 'mi' THEN DATEADD(minute,@number,@date)
WHEN 'n' THEN DATEADD(minute,@number,@date)
WHEN 'second' THEN DATEADD(second,@number,@date)
WHEN 'ss' THEN DATEADD(second,@number,@date)
WHEN 's' THEN DATEADD(second,@number,@date)
WHEN 'millisecond' THEN DATEADD(millisecond,@number,@date)
WHEN 'ms' THEN DATEADD(millisecond,@number,@date)
WHEN 'microsecond' THEN DATEADD(microsecond,@number,@date)
WHEN 'mcs' THEN DATEADD(microsecond,@number,@date)
WHEN 'nanosecond' THEN DATEADD(nanosecond,@number,@date)
WHEN 'ns' THEN DATEADD(nanosecond,@number,@date)
END
return @Return
END
GO
SELECT GetDate()
SELECT dbo.UserDateadd('year', 1, GetDate())
GO
G. 使用 DATEPART 依據日期部分分組
下列範例會使用 AdventureWorks2008R2 範例資料庫。DATEPART 用於分組總銷售量 (依據工作日、月、年及年/月/工作日)。
USE AdventureWorks2008R2;
GO
SELECT SUM(TotalDue) AS 'Total Sales'
,DATEPART(year,OrderDate)AS 'By Year'
,DATEPART(month,OrderDate) AS 'By Month'
,DATEPART(weekday,OrderDate) AS 'By Weekday'
FROM Sales.SalesOrderHeader
WHERE YEAR(OrderDate) IN('2007','2008')
GROUP BY GROUPING SETS
(
(DATEPART(year,OrderDate))
,(DATEPART(month,OrderDate))
,(DATEPART(weekday,OrderDate))
,(
DATEPART(year,OrderDate)
,DATEPART(month,OrderDate)
,DATEPART(weekday,OrderDate))
)
ORDER BY DATEPART(year,OrderDate)
,DATEPART(month,OrderDate)
,DATEPART(weekday,OrderDate);