在编写SQL查询时,AND和OR是最常用的两个逻辑运算符,但不少人在把它们组合到同一个WHERE子句里时,会发现查询结果和自己预想的完全不一样。例如想查询“北京的客户或者所有VIP客户”,结果却只得到了北京地区的VIP客户。这背后的根源就是SQL对逻辑运算符定义了明确的优先级规则:AND的优先级高于OR,如果不用括号显式分组,条件会被按默认规则切分,最终筛选出的数据自然与预期不符。本文将从优先级原理、括号用法、实际案例和性能影响几个方面,系统地讲清AND与OR的组合使用方法。

一、AND和OR的优先级规则详解
SQL标准中规定,逻辑运算符的优先级从高到低依次是:NOT、AND、OR。也就是说,在一个没有括号的WHERE子句中,所有的AND条件会先被计算,然后再用OR把各个AND分组连接起来。这个规则和数学里“先乘除后加减”非常类似,理解了这一点,很多“奇怪”的查询结果就能解释清楚了。
举个简单例子,假设有一条查询语句:
SELECT * FROM employees WHERE dept = '销售部' AND salary > 8000 OR dept = '技术部';
由于AND先计算,这条语句实际等价于(dept = '销售部' AND salary > 8000) OR dept = '技术部',也就是“销售部中工资高于8000的人,加上技术部的所有人”。如果开发者的本意是“销售部和技术部中工资都高于8000的人”,那么写法就错了,正确应该加括号:WHERE (dept = '销售部' OR dept = '技术部') AND salary > 8000。
需要特别注意的还有NOT运算符。NOT的优先级最高,它会先作用于紧随其后的条件。例如WHERE NOT a = 1 AND b = 2等价于WHERE (NOT a = 1) AND b = 2,而不是NOT (a = 1 AND b = 2)。当条件表达式变得复杂时,强烈建议始终使用括号明确表达意图,即使默认优先级恰好符合需求,加上括号也能提升SQL的可读性,方便后期维护。
二、用括号精确控制条件组合的实战案例
括号是控制逻辑运算顺序最直接、最可靠的手段。下面通过一个员工表的完整案例来演示不同写法带来的结果差异。先创建测试数据:
-- 创建员工表并插入测试数据
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50),
dept VARCHAR(30),
salary DECIMAL(10, 2),
city VARCHAR(30)
);
INSERT INTO employees VALUES
(1, '张三', '销售部', 9000, '北京'),
(2, '李四', '销售部', 6000, '上海'),
(3, '王五', '技术部', 12000, '北京'),
(4, '赵六', '技术部', 7000, '深圳'),
(5, '孙七', '人事部', 6500, '北京');需求一:查询北京的技术部员工,或者上海的销售部员工。这类“成对条件二选一”的场景,必须用括号把每一对条件包起来:
SELECT * FROM employees WHERE (city = '北京' AND dept = '技术部') OR (city = '上海' AND dept = '销售部');
这条查询会正确返回王五和李四两条记录。如果去掉括号写成WHERE city = '北京' AND dept = '技术部' OR city = '上海' AND dept = '销售部',虽然本例结果恰好相同(因为AND优先级正好符合意图),但一旦需求变成“北京的员工,或者技术部且工资高于一万的人”,不加括号就必然出错。养成加括号的习惯可以彻底杜绝这类隐患。
需求二:查询工资低于7000或者高于11000,并且部门不是人事部的员工。这类混合了范围条件和排除条件的查询,写法如下:
SELECT name, dept, salary FROM employees WHERE (salary < 7000 OR salary > 11000) AND dept <> '人事部';
如果忘记给OR部分加括号,SQL会先计算salary > 11000 AND dept <> '人事部',导致工资低于7000的员工中人事部的孙七也被错误地包含进来。可见括号不仅是风格问题,更是查询正确性的保障。
三、AND与OR组合对索引和性能的影响
除了逻辑正确性,AND与OR的写法还会影响数据库对索引的利用。多个AND条件连接时,数据库优化器通常能高效地使用复合索引或多个单列索引做交集运算,性能一般较好。而OR条件的处理相对复杂:如果OR两边的条件分别命中不同的索引,MySQL等数据库可以通过index merge(索引合并)优化;但如果OR条件中有一列没有索引,往往会导致全表扫描。
一种常见的优化手段是把OR改写为UNION。例如下面这条查询:
-- 原始写法:OR可能导致索引失效 SELECT * FROM employees WHERE dept = '技术部' OR salary > 10000; -- 优化写法:拆分为UNION,两个分支都可走索引 SELECT * FROM employees WHERE dept = '技术部' UNION SELECT * FROM employees WHERE salary > 10000;
UNION会自动去重,如果确定没有重复数据或不需要去重,可以使用UNION ALL减少排序去重的开销。不过在改写时要注意一个细节:AND的优先级高于OR,但UNION各分支之间是并列关系,拆分时必须把原来括号内的完整条件组搬到对应分支中,否则会改变查询语义。此外,当OR条件针对的是同一列时,例如city = '北京' OR city = '上海',更推荐改写为IN写法city IN ('北京', '上海'),语义清晰且优化器处理效率更高。
最后提醒一点,无论条件多复杂,都建议在写完WHERE子句后手动梳理一遍逻辑分组:先找OR,把OR两侧的AND组用括号框出来,再验证每一组条件是否符合业务意图。配合EXPLAIN查看执行计划,就能同时保证查询结果的正确性和执行效率。掌握这些规则后,AND和OR的组合使用就再也不会成为查询语句中的隐形炸弹了。
SQL AND OR优先级WHERE子句逻辑运算符修改时间:2026-09-01 09:58:27