test_expression [ NOT ] BETWEEN begin_expression AND end_expression
BETWEEN 20 AND 22 等價於 >= 20 AND <= 22。begin_expression 必須 ≤ end_expression,否則永遠不匹配 (不會自動交換)。int + datetime → datetime),可能導致隱含轉換導致索引失效。SELECT number, age FROM students WHERE age BETWEEN 20 AND 22;
SELECT number, age FROM students WHERE age NOT BETWEEN 20 AND 22;
-- 等價於 age < 20 OR age > 22 (注意:若 age 為 NULL,結果為 UNKNOWN,不會被選取)
| 陷阱 | 說明 | 解決方案 |
|---|---|---|
| 日期時間型別上界截斷 | WHERE dt BETWEEN '2023-01-01' AND '2023-01-31' 會漏掉 1/31 當天 00:00:00 之後的資料 (字串轉 datetime 預設 00:00:00) | 用 WHERE dt >= '2023-01-01' AND dt < '2023-02-01' (半開區間) |
| 字串比對排序規則影響 | BETWEEN 'A' AND 'Z' 依資料庫排序規則,可能不包含小寫或重音字元 | 明確指定 COLLATE Latin1_General_CI_AI 或用 LIKE 模式 |
| NULL 值處理 | 任何與 NULL 比較結果為 UNKNOWN,BETWEEN / NOT BETWEEN 皆不會選取 NULL 列 | 若需包含 NULL:WHERE (col BETWEEN 1 AND 10) OR col IS NULL |
| 隱含轉換導致索引掃描 | WHERE varchar_col BETWEEN 1 AND 100 → 隱含轉換 varchar_col 為 int,索引失效 | 參數/常數型別與欄位一致:BETWEEN '1' AND '100' |
| NOT BETWEEN 邏輯誤解 | 以為 NOT BETWEEN 等於 NOT (BETWEEN),但三值邏輯下 NULL 會導致不同結果 | 明確寫成 WHERE col < 1 OR col > 10 OR col IS NULL (視業務需求) |
BETWEEN 可利用索引 Seek (SARGable),前提是無隱含轉換、無函數包裹欄位。BETWEEN 欄位若非前導欄位,可能退化為 Scan。BETWEEN (如 > 10% 資料) 優化器可能選擇 Clustered Index Scan,可用 FORCESEEK 提示測試。| 平台 | BETWEEN 語意 | 備註 |
|---|---|---|
| SQL Server | 包含邊界 | 標準 SQL |
| Oracle | 包含邊界 | 同標準 |
| MySQL | 包含邊界 | 同標準 |
| PostgreSQL | 包含邊界 | 同標準 |
| Access (Jet/ACE) | 包含邊界 | 同標準 |