在 SQL Server 中正確選擇日期時間類型,關乎數據精度、存儲成本、查詢性能及業務正確性。datetime 與 smalldatetime 雖同屬日期時間家族,但精度差 1000 倍、範圍差 300 年、存儲差一倍。本文將從底層存儲、精度機制、邊界行為、選型決策四個維度深度剖析,助你做出最優架構決策。
| 特性 | datetime | smalldatetime |
|---|---|---|
| 日期範圍 | 1753-01-01 ~ 9999-12-31 | 1900-01-01 ~ 2079-06-06 |
| 時間精度 | 3.33 毫秒 (1/300 秒) | 1 分鐘 |
| 存儲大小 | 8 字節 (兩個 4 字節整數) | 4 字節 (兩個 2 字節整數) |
| 默認值 | 1900-01-01 00:00:00.000 | 1900-01-01 00:00:00 |
| 適用場景 | 金融交易、科學計算、審計日誌、高精度業務 | 一般業務、日程安排、低精度記錄、存儲敏感環境 |
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 <)更安全。
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,導致統計報表出現「未來數據」或分鐘級聚合偏差。
自 SQL Server 2008 起,微軟推出三大新類型全面優於 雙舊類,新項目嚴禁 使用 datetime/smalldatetime:
| 新類型 | 精度 | 範圍 | 存儲 | 推薦場景 |
|---|---|---|---|---|
datetime2(n) | 100 納秒 (可配置 0-7 位小數) | 0001-01-01 ~ 9999-12-31 | 6-8 字節 | 所有高精度場景,首選替代 datetime |
date | 天 | 0001-01-01 ~ 9999-12-31 | 3 字節 | 純日期業務(生日、合同日期),替代 datetime 日期部分 |
time(n) | 100 納秒 | 00:00:00 ~ 23:59:59.9999999 | 3-5 字節 | 純時間業務(班次、鬧鐘),替代 datetime 時間部分 |
datetimeoffset(n) | 100 納秒 + 時區偏移 | 0001-01-01 ~ 9999-12-31 | 8-10 字節 | 跨時區系統、全球化應用 |
datetimeoffsetdate (3 字節,極致省空間)timedatetime2(3) 或 datetime2(7) (默認 7 位,毫秒級用 3 位省空間)smalldatetimedatetime (但需接受 3.33ms 量子化)-- 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,獲得納秒精度、更大範圍、更靈活存儲與時區支援。舊系統遷移時,務必驗證四捨五入行為對業務邏輯的影響,採用並行雙寫、灰度切換、回滾預案 確保平滑過渡。選對時間類型,是數據質量的基石。