SQL IN 操作符
学习 IN 和 NOT IN · 难度:入门 · +10XP
SQL IN 操作符
当查询条件需要匹配多个离散值时,用多个 OR 连接条件不仅写法繁琐,而且可读性差。例如查询年龄为 19、20 或 21 岁的学生,需要写成 WHERE age=19 OR age=20 OR age=21。SQL 的 IN 操作符提供了一种更优雅的方式,让你可以在 WHERE 子句中指定一个值列表,只要列的值在列表中任意匹配一个即可,大大简化了多值筛选的写法。
IN 基本语法
SELECT 列名 FROM 表名 WHERE 列名 IN (值1, 值2, 值3, ...);
SELECT 列名 FROM 表名 WHERE 列名 NOT IN (值1, 值2, 值3, ...);
IN 后面的括号中可以是显式的值列表,也可以是一个子查询返回的结果集。
使用值列表
-- 查询年龄为19、20、21的学生
SELECT * FROM students WHERE age IN (19, 20, 21);
-- 查询指定姓名的学生
SELECT * FROM students WHERE name IN ('张三', '李四', '王五');
-- NOT IN:排除指定值
SELECT * FROM students WHERE name NOT IN ('张三', '李四');
-- 结合其他条件
SELECT * FROM students
WHERE age IN (19, 20) AND score > 80;
使用子查询作为值来源
这是 IN 最强大的用法——动态获取值列表:
-- 查询有选课记录的学生
SELECT * FROM students
WHERE id IN (SELECT student_id FROM courses);
-- 查询分数排名前3的学生
SELECT * FROM students
WHERE score IN (SELECT score FROM students ORDER BY score DESC LIMIT 3);
-- 查询在特定班级中的学生
SELECT * FROM students
WHERE class_id IN (SELECT id FROM classes WHERE grade = '三年级');
IN vs OR vs EXISTS
| 操作符 | 适用场景 | 性能 |
|---|---|---|
| IN (值列表) | 匹配少量离散值(静态列表) | 快 |
| IN (子查询) | 值列表来自另一个查询 | 取决于子查询 |
| OR 连接 | 少量条件,不同列 | 一般 |
| EXISTS | 检查关联表中是否存在记录 | 大批量数据时优于IN |
IN 与 NULL 的陷阱
特别注意:当 IN 子查询的结果包含 NULL 时,NOT IN 的行为可能出乎意料:
-- 如果子查询返回 (1, 2, NULL)
SELECT * FROM t WHERE id NOT IN (1, 2, NULL);
-- 结果:永远返回空!因为 NULL 不等于任何值
安全做法:在 NOT IN 子查询中加 WHERE 列 IS NOT NULL,或改用 NOT EXISTS。
实战任务
- 查询年龄为 18、20、22 岁的学生
- 使用 IN + 子查询,查询有课程记录的学生
- 使用 NOT IN 排除特定姓名的学生