[英]DateTime2 vs DateTime in SQL Server
DATETIME2
的日期范圍為“0001 / 01 / 01”到“9999 / 12 / 31”,而DATETIME
類型僅支持 1753-9999 年。
此外,如果需要, DATETIME2
可以在時間方面更精確; DATETIME 被限制為 3 1/3 毫秒,而DATETIME2
可以精確到 100ns。
兩種類型都映射到 .NET 中的System.DateTime
- 沒有區別。
如果您有選擇,我建議您盡可能使用DATETIME2
。 我沒有看到使用DATETIME
任何好處(除了向后兼容性) - 你會遇到更少的麻煩(日期超出范圍和麻煩)。
另外:如果您只需要日期(沒有時間部分),請使用 DATE - 它與DATETIME2
一樣好,也可以節省空間! :-) 同樣適用於時間 - 使用TIME
。 這就是這些類型的用途!
datetime2在大多數方面都勝出(舊應用程序兼容性)
請注意以下幾點
圖片來源: MCTS 自定進度培訓套件(考試 70-432):Microsoft® SQL Server® 2008 - 實施和維護第 3 章:表 -> 第 1 課:創建表 -> 第 66 頁
我同意@marc_s 和@Adam_Poward——DateTime2 是前進的首選方法。 它的日期范圍更廣,精度更高,並且使用相等或更少的存儲空間(取決於精度)。
然而,討論遺漏了一件事......
@Marc_s 聲明: Both types map to System.DateTime in .NET - no difference there
。 這是正確的,然而,反之則不正確……這在進行日期范圍搜索時很重要(例如“找到我在 2010 年 5 月 5 日修改的所有記錄”)。
.NET 的Datetime
版本具有與DateTime2
相似的范圍和精度。 將 .net Datetime
向下映射到舊的 SQL DateTime
Datetime
時,會發生隱式舍入。 舊的 SQL DateTime
精確到 3 毫秒。 這意味着11:59:59.997
盡可能接近一天的結束。 任何更高的值都會向上舍入到第二天。
嘗試這個 :
declare @d1 datetime = '5/5/2010 23:59:59.999'
declare @d2 datetime2 = '5/5/2010 23:59:59.999'
declare @d3 datetime = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'
避免這種隱式舍入是轉移到 DateTime2 的重要原因。 日期的隱式四舍五入顯然會導致混淆:
幾乎所有的答案和評論都強調了優點,而強調了缺點。 這是迄今為止所有優點和缺點的回顧,以及一些關鍵的缺點(在下面的 #2 中)我只見過一次或根本沒有提到。
1.1. 更符合 ISO (ISO 8601)(雖然我不知道這在實踐中是如何發揮作用的)。
1.2. 更多的范圍(1/1/0001 到 12/31/9999 vs. 1/1/1753-12/31/9999)(盡管額外的范圍,都在 1753 年之前,可能不會被使用,除了例如,在歷史、天文、地質等應用程序中)。
1.3. 完全匹配 .NET 的DateTime
類型的范圍(盡管如果值在目標類型的范圍和精度內,則兩者都沒有特殊編碼來回轉換,除了下面的 Con # 2.1 否則會發生錯誤/舍入)。
1.4. 更高的精度(100 納秒又名 0.000,000,1 秒 vs. 3.33 毫秒,又名 0.003,33 秒)(盡管可能不會使用額外的精度,除非在工程/科學應用中除外)。
1.5. 當配置為類似(如 Iman Abidi 聲稱的 1 毫秒不“相同”(如 3.33 毫秒))精度為DateTime
,使用更少的空間(7 對 8 字節),但當然,你會失去精度好處可能是最受吹捧的兩個(另一個是范圍)之一,盡管可能是不需要的好處)。
2.1. 將參數傳遞給 .NET SqlCommand
,如果您傳遞的值可能超出 SQL Server DateTime
的范圍和/或精度,則必須指定System.Data.SqlDbType.DateTime2
,因為它默認為System.Data.SqlDbType.DateTime
。
2.2. 不能隱式/輕松轉換為浮點數字(自最小日期時間以來的天數)值,以便在使用數字值和運算符的 SQL Server 表達式中對其執行以下操作:
2.2.1. 添加或減去天數或部分天數。 注意:當您需要考慮日期時間的多個部分(如果不是全部)時,使用DateAdd
函數作為解決方法並DateAdd
。
2.2.2. 出於“年齡”計算的目的,取兩個日期時間之間的差異。 注意:您不能簡單地使用 SQL Server 的DateDiff
函數,因為它不會像大多數人所期望的那樣計算age
,因為如果兩個日期時間恰好跨越指定單位的日歷/時鍾日期時間邊界,即使對於一個該單位的一小部分,它將返回該單位的 1 與 0 的差異。例如,如果兩個日期時間相隔僅 1 毫秒, Day
的DateDiff
將返回 1 與 0(天),如果這些日期時間在不同的日歷日(即“1999-12-31 23:59:59.9999999”和“2000-01-01 00:00:00.0000000”)。 如果移動相同的 1 毫秒差異日期時間,以便它們不會跨越日歷日,則將在Day
's of 0(天)中返回“DateDiff”。
2.2.3. 通過簡單地首先轉換為“Float”然后再轉換回DateTime
來獲取日期時間的Avg
(在聚合查詢中)。
注意:要將DateTime2
轉換為數字,您必須執行類似於以下公式的操作,該公式仍然假定您的值不小於 1970 年(這意味着您將失去所有額外范圍加上另外 217 年。注意:您可能無法簡單地調整公式以允許額外的范圍,因為您可能會遇到數字溢出問題。
25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0
– 來源:“ https://siderite.dev/blog /how-to-translate-t-sql-datetime2-to.html “
當然,你也可以Cast
以DateTime
第一(如果必要,再次回到DateTime2
),但你會失去精度和范圍(全年開放前1753)的好處DateTime2
與DateTime
這是prolly 2最大,也同時prolly 2個最不可能需要的問題,當您丟失隱式/簡單轉換為浮點數字(天數)以進行加法/減法/“年齡”(與DateDiff
)/ Avg
時,為什么要使用它calcs 的好處在我的經驗中是一個很大的好處。
順便說一句,日期時間的Avg
是(或至少應該是)一個重要的用例。 a) 除了在日期時間(因為一個共同的基准日期時間)用於表示持續時間(一種常見做法)時用於獲取平均持續時間,b)獲取關於平均日期的儀表板類型統計數據也很有用 -時間在一個范圍/一組行的日期時間列中。 c) 一個標准(或至少應該是標准的)臨時查詢來監視/排除列中可能永遠/不再有效和/或可能需要棄用的值是為每個值列出出現計數以及(如果可用)與該值關聯的Min
、 Avg
和Max
日期時間戳。
下面是一個示例,它將向您展示 smalldatetime、datetime、datetime2(0) 和 datetime2(7) 在存儲大小(字節)和精度方面的差異:
DECLARE @temp TABLE (
sdt smalldatetime,
dt datetime,
dt20 datetime2(0),
dt27 datetime2(7)
)
INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()
SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
dt,DATALENGTH(dt) as dt_bytes,
dt20,DATALENGTH(dt20) as dt20_bytes,
dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp
返回
sdt sdt_bytes dt dt_bytes dt20 dt20_bytes dt27 dt27_bytes
------------------- --------- ----------------------- -------- ------------------- ---------- --------------------------- ----------
2015-09-11 11:26:00 4 2015-09-11 11:25:42.417 8 2015-09-11 11:25:42 6 2015-09-11 11:25:42.4170000 8
因此,如果我想將信息存儲到秒 - 但不是毫秒 - 如果我使用 datetime2(0) 而不是 datetime 或 datetime2(7),我可以節省 2 個字節。
如果您是嘗試將 Now() 寫入相關字段的 Access 開發人員,則 DateTime2 會造成嚴重破壞。 剛剛做了一個 Access -> SQL 2008 R2 遷移,它把所有的日期時間字段作為 DateTime2。 使用 Now() 附加一條記錄作為值被炸毀。 2012 年 1 月 1 日下午 2:53:04 沒問題,但 2012 年 1 月 10 日下午 2:53:04 不行。
一旦性格有所不同。 希望它可以幫助某人。
老問題……但我想補充一些這里沒有人說過的東西……(注:這是我自己的觀察,所以不要要求任何參考)
Datetime2 在過濾條件中使用時更快。
域名注冊地址:
在 SQL 2016 中,我有一個包含十萬行和一個日期時間列 ENTRY_TIME 的表,因為它需要存儲精確到秒的時間。 在執行具有許多連接和子查詢的復雜查詢時,當我使用 where 子句時:
WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'
當有數百行時,查詢最初很好,但是當行數增加時,查詢開始出現此錯誤:
Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.
我刪除了 where 子句,出乎意料的是,查詢在 1 秒內運行,盡管現在獲取了所有日期的所有行。 我使用 where 子句運行內部查詢,耗時 85 秒,沒有 where 子句則耗時 0.01 秒。
我在這里遇到了許多線程作為日期時間過濾性能
我稍微優化了查詢。 但是我獲得的真正速度是將日期時間列更改為 datetime2。
現在,之前超時的相同查詢只需不到一秒鍾。
干杯
當使用非美國DATEFORMAT
設置時,將日期字符串解釋為datetime
和datetime2
也可能不同。 例如
set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2
這將返回2013-05-06
(即 5 月 6 日)的datetime
和2013-06-05
(即 6 月 5 日)的datetime2
。 然而, dateformat
設置為mdy
,既@d
和@d2
回報2013-06-05
。
datetime
行為似乎與SET DATEFORMAT
的MSDN 文檔不一致,該文檔指出:某些字符串格式,例如 ISO 8601,獨立於 DATEFORMAT 設置進行解釋。 顯然不是真的!
直到我被這個咬到之前,我一直認為yyyy-mm-dd
日期會被正確處理,無論語言/區域設置如何。
根據這篇文章,如果您想使用 DateTime2 獲得與 DateTime 相同的精度,您只需使用 DateTime2(3)。 這應該給你相同的精度,少占用一個字節,並提供一個擴展的范圍。
我只是偶然發現了DATETIME2
另一個優勢:它避免了 Python adodbapi
模塊中的錯誤,如果傳遞標准庫datetime
值,該值會adodbapi
,該值對於DATETIME
列具有非零微秒,但如果該列定義為DATETIME2
。
由於其他答案顯示datetime2
由於較小的尺寸和更高的精度而被推薦,但這里有一些關於為什么不使用 Nikola Ilic 的 datetime2 的想法:
GETDATE()+1
DATEADD
或DATEDIFF
進行比較時,您都將完成隱式數據轉換為datetime
我認為DATETIME2
是存儲date
的更好方法,因為它比DATETIME
更有效率。 在SQL Server 2008
您可以使用DATETIME2
,它存儲日期和時間,需要 6-8 bytes
來存儲,精度為100 nanoseconds
。 所以任何需要更高時間精度的人都會想要DATETIME2
。
接受的答案很好,只要知道如果您向前端發送 DateTime2 - 它就會四舍五入為正常的 DateTime 等效值。
這給我帶來了一個問題,因為在我的解決方案中,我必須將重新提交時發送的內容與數據庫中的內容進行比較,而我的簡單比較“==”不允許四舍五入。 所以必須加上。
Select ValidUntil + 1
from Documents
上述 SQL 不適用於 DateTime2 字段。 它返回錯誤“操作數類型沖突:datetime2 與 int 不兼容”
添加 1 以獲得第二天是開發人員多年來一直在做的事情。 現在微軟有一個超級新的 datetime2 字段,它無法處理這個簡單的功能。
“讓我們使用這種比舊的更糟糕的新類型”,我不這么認為!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.