where 是 sql 查询中控制数据范围的强制开关,必须位于 from 之后、group by 之前,仅过滤原始行级数据,不可引用聚合函数;分组后条件须用 having;日期需用 # 包裹或 datevalue();文本比较应 trim 并注意通配符差异;多表联接必须显式 join 避免笛卡尔积。

WHERE 子句不是“可选技巧”,而是 SQL 查询中控制数据范围的强制开关——漏写、错写或放错位置,结果不是全表扫就是查不到记录。
WHERE 必须写在 FROM 之后,且不能直接引用聚合函数
Access 和多数 SQL 引擎要求 WHERE 执行在聚合(COUNT、SUM 等)之前,所以它看不到分组后的值。
- 错误写法:
SELECT Category, COUNT(*) FROM Products GROUP BY Category WHERE COUNT(*) > 5→ 报错Invalid use of an aggregate function - 正确做法:用
HAVING处理分组后条件,WHERE只管原始行级过滤,例如:SELECT Category, COUNT(*) FROM Products WHERE Discontinued = False GROUP BY Category HAVING COUNT(*) > 5 -
HAVING必须紧跟GROUP BY,且不能脱离分组单独存在
日期条件必须用 # 包裹,别信 '2026-04-15'
Access 对日期字面量格式极其敏感,不认 ISO 格式或带前导零的年份。直接写 '2026-04-15' 或 '15/04/2026' 很可能静默匹配失败。
- 安全写法:
WHERE OrderDate = #4/15/26#(年份缩写两位更稳,避免解析歧义) - 国际兼容写法:
WHERE OrderDate = DateValue('15-Apr-2026')(DateValue()按系统区域设置解析) - 别用
Format([OrderDate], "yyyy-mm-dd") = '2026-04-15'—— 返回文本,索引失效,还触发隐式转换
文本字段比较要防空格和通配符陷阱
Access 默认不区分大小写,但会严格比对前后空格;模糊匹配也和 MySQL/PostgreSQL 不同。
-
[LastName] = 'Bagel '(末尾有空格)永远不等于存储为'Bagel'的记录 - 去空格再比:
WHERE Trim([ContactName]) = 'John Smith' - 前缀匹配用
LIKE:WHERE [CompanyName] LIKE 'Micro*'(Access 用星号*,不是百分号%) - 含某词模糊查:
WHERE [Notes] LIKE '*shipping*'
多表查询别靠 WHERE 做联接,显式 JOIN 更安全
旧式写法 FROM Orders, Customers WHERE Orders.CustomerID = Customers.ID 是隐式联接,漏一个等值条件就触发笛卡尔积。
- 1000 行 × 1000 行 = 百万级无意义结果,轻则卡死,重则爆内存
- 推荐写法:
SELECT * FROM Orders INNER JOIN Customers ON Orders.CustomerID = Customers.ID - 若真要用 WHERE 联接,必须确保每个表至少有一个等值关联条件,且所有关联字段都参与判断
最常被忽略的是执行顺序:WHERE 在聚合前、在 JOIN 后(显式时)、在 ORDER BY 前——它只看见原始行和 JOIN 后的中间结果,看不见 COUNT,也看不见排序后的序号。这点一旦错位,调试成本远高于重写整条语句。











