SQL WHERE:用 AND、OR 与 NULL 筛选行
SQL WHERE 子句用于按条件筛选表中的行。在 SQL 查询里,WHERE 子句只有在谓词计算结果为 TRUE 时才会保留该行,FALSE 和 NULL/UNKNOWN 都会被排除。这种三值逻辑是 WHERE 在处理 NULL 时最常见的异常行为来源。
SQL WHERE 行筛选示例
输出:
输出将显示在这里...
输出:
+--------+-----------+-------+
| name | category | price |
+--------+-----------+-------+
| 键盘 | 电子产品 | 49.99 |
| 鼠标 | 电子产品 | 25.0 |
+--------+-----------+-------+
2 row(s)
这个示例如何工作
CREATE TABLE和INSERT创建了一个products表,四行数据分布在两个分类中。- SQL 查询中的 WHERE 子句
category = '电子产品' AND price < 100用AND组合两个条件,两个条件都为 TRUE 时该行才会出现。 - “显示器”属于电子产品但价格是 299.00,因此被价格条件排除。“笔记本”未通过分类条件。最终只有“键盘”和“鼠标”同时满足两个谓词。
什么是 SQL WHERE 子句?
SQL WHERE 子句是逐行应用的布尔过滤器。数据库会对每一条候选行计算表达式,只保留结果为 TRUE 的行。返回 FALSE 或 NULL 的表达式都会被丢弃。WHERE 在 GROUP BY 和聚合函数之前执行,这也是它与 HAVING 的关键区别。
SQL WHERE 子句中的常见错误
错误: 用 = 把列和 NULL 比较。
错误写法:
WHERE category = NULL
正确写法:
WHERE category IS NULL
原因:= NULL 的计算结果是 UNKNOWN,而 WHERE 会过滤掉 UNKNOWN 行。应使用 IS NULL 或 IS NOT NULL。
错误: 混用 AND 和 OR 时不加括号。
错误写法:
WHERE category = '办公用品' OR category = '电子产品' AND price < 50
正确写法:
WHERE (category = '办公用品' OR category = '电子产品') AND price < 50
原因:AND 的优先级高于 OR,要让逻辑与意图一致必须加括号。
WHERE 与 HAVING
| WHERE | HAVING |
|---|---|
| 在分组前筛选单行 | 在聚合后筛选分组 |
| 不能引用聚合函数 | 可以引用 COUNT、SUM 等聚合函数 |
减少进入 GROUP BY 的行数 | 减少最终结果中的分组 |
规则:在聚合前排除行用 WHERE,在聚合后排除分组用 HAVING。尽早在 WHERE 里过滤,能减少聚合阶段的工作量。
性能注意事项
在已建立索引的列上使用 WHERE 谓词,可以把全表扫描变成索引查找。把列包在函数里(如 LOWER(name)、DATE(created_at))会阻止优化器使用索引;应优先变换比较值而不是变换列。对于 AND 连接的条件,按谓词列顺序建立复合索引通常性能最好。OR 条件往往会触发多个索引扫描再合并,通常比同一索引上的 AND 更慢。
安全说明
构建 WHERE 条件时要使用参数化查询,绝不要把用户输入直接拼接进 SQL 字符串。动态列名必须先用严格的白名单校验。处理 IN (...) 列表时,生成占位符并逐个绑定值。执行 UPDATE 或 DELETE 前,先用完全相同的 WHERE 子句跑一条 SELECT 进行预览。
常见问题
SQL 中 WHERE 和 HAVING 的区别是什么?
WHERE 在 GROUP BY 前筛选行;HAVING 在聚合后筛选分组。WHERE 不能引用 COUNT()、SUM() 这类聚合函数。一个查询可以同时使用两者:WHERE 先缩小输入行,再由 HAVING 缩小分组后的输出。
为什么 = NULL 在 WHERE 子句里不起作用?
SQL 使用三值逻辑:TRUE、FALSE、UNKNOWN。任何与 NULL 的比较都会得到 UNKNOWN,而 WHERE 会丢弃 UNKNOWN 行。判断 NULL 应使用 IS NULL。一些数据库也支持 IS NOT DISTINCT FROM,用于 NULL 安全的相等比较。
WHERE 子句中条件的书写顺序会影响性能吗?
SQL 标准不保证表达式计算顺序,多数优化器也会在内部重排谓词。条件按可读性最佳的顺序书写即可。真正影响性能的是列是否有索引以及每个谓词的选择性,而不是书写顺序。