首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server datetime 與 smalldatetime 深度解析:精度、範圍、存儲與選型指南

     編輯:關於SqlServer

在 SQL Server 中正確選擇日期時間類型,關乎數據精度、存儲成本、查詢性能及業務正確性。datetime 與 smalldatetime 雖同屬日期時間家族,但精度差 1000 倍、範圍差 300 年、存儲差一倍。本文將從底層存儲、精度機制、邊界行為、選型決策四個維度深度剖析,助你做出最優架構決策。

核心差異總覽

特性datetimesmalldatetime
日期範圍1753-01-01 ~ 9999-12-311900-01-01 ~ 2079-06-06
時間精度3.33 毫秒 (1/300 秒)1 分鐘
存儲大小8 字節 (兩個 4 字節整數)4 字節 (兩個 2 字節整數)
默認值1900-01-01 00:00:00.0001900-01-01 00:00:00
適用場景金融交易、科學計算、審計日誌、高精度業務一般業務、日程安排、低精度記錄、存儲敏感環境

datetime:高精度的代價與機制

精度機制:3.33 毫秒的「量子化」

datetime 的時間部分以「滴答」為單位存儲,1 滴答 = 3.33... 毫秒。SQL Server 會將輸入的毫秒值四捨五入到最近的滴答,導致可見的「跳躍」:

輸入毫秒調整後值說明
999, 998, 997.997向上調整
996, 995, 994.997向上調整
993, 992, 991.993向下調整
990.990精確匹配

警示: WHERE CreateTime = '2023-01-01 12:00:00.000' 可能匹配不到 12:00:00.001 實際存儲的數據,範圍查詢(BETWEEN / >= AND <)更安全。

內部存儲結構

  • 前 4 字節: 距基準日 (1900-01-01) 的天數(負數表示 1753-1899 年)。
  • 後 4 字節: 午夜後的毫秒數(0 ~ 25,919,999,對應 23:59:59.997)。

smalldatetime:分鐘級的「捨入陷阱」

精度機制:秒級四捨五入到分鐘

smalldatetime 僅存儲到分鐘,秒部分遵循 四捨五入規則:

  • 00.000 ~ 29.999 秒 → 向下捨入 到當前分鐘
  • 30.000 ~ 59.999 秒 → 向上進位 到下一分鐘
-- 返回 12:35 (29.998 秒向下捨入)
SELECT CAST('2000-05-08 12:35:29.998' AS smalldatetime);

-- 返回 12:36 (29.999 秒向上進位)
SELECT CAST('2000-05-08 12:35:29.999' AS smalldatetime);

業務風險: 12:35:30 會被存為 12:36,導致統計報表出現「未來數據」或分鐘級聚合偏差。

內部存儲結構

  • 前 2 字節: 距 1900-01-01 的天數 (0 ~ 65535,覆蓋至 2079-06-06)。
  • 後 2 字節: 午夜後的分鐘數 (0 ~ 1439)。

版本演進建議:棄用雙舊類,擁抱新三類

自 SQL Server 2008 起,微軟推出三大新類型全面優於 雙舊類,新項目嚴禁 使用 datetime/smalldatetime:

新類型精度範圍存儲推薦場景
datetime2(n)100 納秒 (可配置 0-7 位小數)0001-01-01 ~ 9999-12-316-8 字節所有高精度場景,首選替代 datetime
date天0001-01-01 ~ 9999-12-313 字節純日期業務(生日、合同日期),替代 datetime 日期部分
time(n)100 納秒00:00:00 ~ 23:59:59.99999993-5 字節純時間業務(班次、鬧鐘),替代 datetime 時間部分
datetimeoffset(n)100 納秒 + 時區偏移0001-01-01 ~ 9999-12-318-10 字節跨時區系統、全球化應用

選型決策樹

  1. 需時區感知? → datetimeoffset
  2. 僅需日期? → date (3 字節,極致省空間)
  3. 僅需時間? → time
  4. 需日期時間且精度要求高? → datetime2(3) 或 datetime2(7) (默認 7 位,毫秒級用 3 位省空間)
  5. 維護舊系統必須用舊類型?
    • 精度要求分鐘級、範圍在 1900-2079、極度在意存儲 → smalldatetime
    • 其他 → datetime (但需接受 3.33ms 量子化)

遷移實戰:datetime → datetime2

-- 1. 新增列
ALTER TABLE Orders ADD OrderDate2 datetime2(3) NULL;

-- 2. 回填數據 (隱式轉換安全)
UPDATE Orders SET OrderDate2 = OrderDate;

-- 3. 驗證數據一致性
SELECT COUNT(*) FROM Orders WHERE CAST(OrderDate AS datetime2(3)) <> OrderDate2; -- 應為 0

-- 4. 切換應用代碼指向新列,舊列標記棄用

-- 5. 重建索引、統計信息
-- 6. 確認無風險後 DROP 舊列

總結

datetime 的 3.33ms 量子化與 smalldatetime 的秒級四捨五入,都是歷史遺留的精度陷阱。新架構請無條件選擇 datetime2/date/time/datetimeoffset,獲得納秒精度、更大範圍、更靈活存儲與時區支援。舊系統遷移時,務必驗證四捨五入行為對業務邏輯的影響,採用並行雙寫、灰度切換、回滾預案 確保平滑過渡。選對時間類型,是數據質量的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved