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

SQL Server 日期時間函數完全手冊:特定日期計算、格式轉換、部分抽取、範圍查詢與比較運算

     編輯:關於SqlServer

一、常用特定日期快速取得

核心公式:DATEADD(單位, DATEDIFF(單位, 0, 參考日期), 0) —— 先算「距基準日 1900-01-01 有多少個單位」,再加回去,得到該單位的「起始點」。

需求T-SQL 表達式說明
本月第一天 00:00DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)月份邊界
本週一 00:00DATEADD(week, DATEDIFF(week, 0, GETDATE()), 0)以週一為週首(依 @@DATEFIRST)
今年第一天 00:00DATEADD(year, DATEDIFF(year, 0, GETDATE()), 0)年份邊界
本季第一天 00:00DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()), 0)季度邊界
今天 00:00DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)日期邊界
上月最後一天 23:59:59.997DATEADD(ms, -3, DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0))減 3 ms 避開午夜
去年最後一天 23:59:59.997DATEADD(ms, -3, DATEADD(year, DATEDIFF(year, 0, GETDATE()), 0))同上
本月最後一天 23:59:59.997DATEADD(ms, -3, DATEADD(month, DATEDIFF(month, 0, GETDATE())+1, 0))下月首日減 3 ms
今年最後一天 23:59:59.997DATEADD(ms, -3, DATEADD(year, DATEDIFF(year, 0, GETDATE())+1, 0))明年首日減 3 ms
本月第一個週一DATEADD(week, DATEDIFF(week, 0, DATEADD(day, 6-DATEPART(day, GETDATE()), GETDATE())), 0)先算本月 1 號屬第幾週

二、取得目前日期時間

  • GETDATE():傳回 datetime,精度 3.33 ms,預設值常用於 DEFAULT (GETDATE())。
  • SYSDATETIME():datetime2(7),100 ns 精度(SQL 2008+)。
  • SYSUTCDATETIME():UTC 高精度時間。

三、格式轉換:CONVERT / FORMAT

-- CONVERT 風格代碼(常用)
SELECT CONVERT(VARCHAR(30), GETDATE(), 120);  -- 2024-01-15 14:30:45 (ODBC 標準)
SELECT CONVERT(VARCHAR(30), GETDATE(), 111);  -- 2024/01/15 (日本/ISO 短日期)
SELECT CONVERT(VARCHAR(30), GETDATE(), 106);  -- 15 Jan 2024 (歐洲風格)
SELECT CONVERT(VARCHAR(30), GETDATE(), 9);    -- Jan 15 2024  2:30:45:123PM (含毫秒)

-- FORMAT (SQL 2012+,.NET 格式字串,效能較慢但極靈活)
SELECT FORMAT(GETDATE(), 'yyyy-MM-dd HH:mm:ss.fff', 'zh-TW');  -- 2024-01-15 14:30:45.123
SELECT FORMAT(GETDATE(), 'D', 'zh-TW');  -- 2024年1月15日

四、日期部分抽取:DATEPART / DATENAME

日期部分縮寫範圍範例
年year, yy, yyyy1753-9999DATEPART(year, GETDATE()) → 2024
季quarter, qq, q1-4DATEPART(qq, GETDATE()) → 1
月month, mm, m1-12DATENAME(month, GETDATE()) → 一月
日day, dd, d1-31DATEPART(dd, GETDATE()) → 15
年內天數dayofyear, dy, y1-366
週week, wk, ww1-53
星期幾weekday, dw, w1-7 (週日-週六)DATENAME(dw, GETDATE()) → 星期一
時hour, hh0-23
分minute, mi, n0-59
秒second, ss, s0-59
毫秒millisecond, ms0-999

DATEPART 回傳 int,適合比較/運算;DATENAME 回傳 nvarchar,適合顯示。

五、日期範圍查詢:正確過濾單日資料

錯誤寫法: WHERE EntryDate = '2024-01-15' → 只會比中 2024-01-15 00:00:00.000。

正確寫法 1(範圍):

WHERE EntryDate >= '2024-01-15' AND EntryDate < '2024-01-16'

正確寫法 2(LIKE 配合字串轉換):

WHERE CONVERT(VARCHAR(10), EntryDate, 120) = '2024-01-15'
-- 或
WHERE EntryDate LIKE '2024-01-15%'

建議採用「範圍法」,可利用索引 Seek,LIKE 會導致掃描。

六、日期比較與運算:DATEDIFF / DATEADD

-- 計算某筆記錄距今幾個小時
SELECT DATEDIFF(hour, EntryDate, GETDATE()) AS HoursAgo FROM WebLog;

-- 計算會員註冊一個月後到期日
SELECT DATEADD(month, 1, FirstVisitDate) AS ExpireDate FROM Members;
-- 注意:DATEADD(month,1) 只是月份 +1,不保證 30 天(1/31 → 2/28/29)

七、進階技巧與避坑

  • 語言/日期格式安全: 字串轉日期請用 CONVERT(datetime, '2024-01-15', 120) 或 PARSE('15/01/2024' AS datetime USING 'zh-TW'),避免隱性轉換受 SET DATEFORMAT/SET LANGUAGE 影響。
  • 閏秒/夏令時間: datetimeoffset + AT TIME ZONE(SQL 2016+)處理時區轉換。
  • 效能: 避免在 WHERE 條件欄位上套用函數(WHERE YEAR(CreateDate) = 2024),改寫為範圍查詢以利索引。
  • 基準日 0 = 1900-01-01,所有 DATEADD/DATEDIFF 以此為原點,負數代表 1900 年前(不支援)。

速查卡:常用日期邊界一鍵生成

DECLARE @Now DATETIME = GETDATE();
SELECT
    DATEADD(month, DATEDIFF(month, 0, @Now), 0)         AS MonthStart,
    DATEADD(month, DATEDIFF(month, 0, @Now)+1, 0)       AS NextMonthStart,
    DATEADD(day, DATEDIFF(day, 0, @Now), 0)             AS DayStart,
    DATEADD(day, DATEDIFF(day, 0, @Now)+1, 0)           AS NextDayStart,
    DATEADD(year, DATEDIFF(year, 0, @Now), 0)           AS YearStart;

掌握這套日期時間工具箱,即能輕鬆應對報表統計、排程觸發、資料歸檔等各類時間維度業務需求。

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