日期時間函數是 T-SQL 查詢、ETL、排程的基石。本文透過實例詳解四大核心函數 GETDATE、DATEADD、DATEDIFF、DATEPART 的語法、行為差異與常見陷阱,並提供實戰查詢模式。
SELECT GETDATE() -- 當前日期時間,精確到毫秒(約 3.33ms)
SELECT SYSDATETIME() -- 高精度 datetime2,100ns 精度
SELECT SYSUTCDATETIME() -- UTC 高精度時間
注意: GETDATE() 回傳 datetime,新專案建議改用 SYSDATETIME() 回傳 datetime2。
SELECT DATENAME(YEAR, GETDATE()) -- '2024'
SELECT DATENAME(MONTH, GETDATE()) -- '一月' (視語言而定)
SELECT DATENAME(WEEKDAY,GETDATE()) -- '星期一'
SELECT DATENAME(DAY, GETDATE()) -- '15'
回傳 nvarchar,適合報表顯示、動態 SQL 拼接。
SELECT DATEADD(MONTH, 2, '2008-08-08') -- 2008-10-08 00:00:00.000
SELECT DATEADD(DAY, 2, '2008-08-08') -- 2008-08-10 00:00:00.000
SELECT DATEADD(HOUR, -1, GETDATE()) -- 1 小時前
SELECT DATEADD(MINUTE, 30, GETDATE()) -- 30 分鐘後
SELECT DATEADD(SECOND, -10, GETDATE()) -- 10 秒前
間隔單位速查: year/yy/yyyy, quarter/qq/q, month/mm/m, dayofyear/dy/y, day/dd/d, week/ww/wk, weekday/dw, hour/hh, minute/mi/n, second/ss/s, millisecond/ms, microsecond/mcs, nanosecond/ns。
SELECT DATEDIFF(HOUR, '04:00', '05:50') -- 1 (僅計算時鐘跨越次數)
SELECT DATEDIFF(MONTH, '1987-05-02', '1995-11-15')-- 102
SELECT DATEDIFF(DAY, '00:00', '23:59') -- 0 (同一天)
SELECT DATEDIFF(DAY, '1999-07-19 00:00', '1999-07-23 23:59') -- 4
SELECT DATEDIFF(MONTH, '1999-07-19', '1999-07-23')-- 0
SELECT DATEDIFF(MONTH, '1999-07-19', '1999-08-23')-- 1
核心行為: 計算「邊界跨越次數」,非連續時間長度。例如 DATEDIFF(DAY, '23:59', '00:01') 回傳 1(跨越午夜),而實際僅 2 分鐘。
-- 寫法 1:DATEDIFF(會掃描全表,無法用索引)
SELECT * FROM Orders WHERE DATEDIFF(DAY, OrderDate, GETDATE()) = 0
-- 寫法 2:範圍查詢(SARGable,可用索引)—— 強烈推薦
DECLARE @TodayStart DATETIME = DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
DECLARE @TomorrowStart DATETIME = DATEADD(DAY, 1, @TodayStart)
SELECT * FROM Orders WHERE OrderDate >= @TodayStart AND OrderDate < @TomorrowStart
SELECT DATEPART(YEAR, GETDATE()) -- 2024
SELECT DATEPART(MONTH, GETDATE()) -- 1
SELECT DATEPART(WEEKDAY,GETDATE()) -- 2 (週一=1...視 SET DATEFIRST)
SELECT DATEPART(DAY, GETDATE()) -- 15
SELECT DAY(GETDATE()) -- 同 DATEPART(DAY,...)
SELECT MONTH(GETDATE()) -- 同 DATEPART(MONTH,...)
SELECT YEAR(GETDATE()) -- 同 DATEPART(YEAR,...)
| 間隔 | 縮寫 | 說明 |
|---|---|---|
| year | yy, yyyy | 年 |
| quarter | qq, q | 季度 |
| month | mm, m | 月 |
| dayofyear | dy, y | 年間第幾天 |
| day | dd, d | 日 |
| week | ww, wk | 年間第幾週 |
| weekday | dw | 星期幾 |
| hour | hh | 時 |
| minute | mi, n | 分 |
| second | ss, s | 秒 |
| millisecond | ms | 毫秒 |
DATENAME(WEEKDAY,...) 或顯式 SET DATEFIRST 7。DATEDIFF(SECOND, start, end) 或 DATEDIFF(MILLISECOND, ...)。'YYYYMMDD' 或 'YYYY-MM-DDTHH:MM:SS',避免語言/日期格式設定導致解析錯誤。datetime 精度 3.33ms,末位只能是 0/3/7;datetime2 可達 100ns。比較、排序時注意精度截斷問題。
-- 近 30 天
DECLARE @End DATETIME2 = SYSUTCDATETIME()
DECLARE @Start DATETIME2 = DATEADD(DAY, -30, @End)
-- 本月迄今 (MTD)
DECLARE @MonthStart DATETIME2 = DATEADD(MONTH, DATEDIFF(MONTH, 0, @End), 0)
-- 上月完整區間
DECLARE @LastMonthStart DATETIME2 = DATEADD(MONTH, -1, @MonthStart)
DECLARE @LastMonthEnd DATETIME2 = @MonthStart
熟練掌握這四大函數與其組合模式,是寫出高效能、可維護 T-SQL 日期邏輯的關鍵。