使用 IN 和 NOT IN 处理集合
使用 IN 和 NOT IN 根据值列表进行过滤,了解 NOT IN 中 NULL 带来的陷阱,并转换为 EXISTS 以获得安全语义。
使用 IN 和 NOT IN 处理集合 是 CoddyKit 上的免费 SQL Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Academy 课程共包含 4 节课。
IN:与列表匹配
IN 是多个 OR 条件的简写:
SELECT * FROM users WHERE country IN ('US', 'CA', 'GB');
-- Equivalent to:
SELECT * FROM users
WHERE country = 'US' OR country = 'CA' OR country = 'GB';带子查询的 IN
您可以在右侧使用子查询:
SELECT * FROM orders
WHERE user_id IN (
SELECT id FROM users WHERE country = 'US'
);NOT IN:排除列表
过滤掉匹配的行:
SELECT * FROM users WHERE status NOT IN ('banned', 'deleted');NOT IN 的 NULL 陷阱
如果右侧包含 NULL,NOT IN 会返回 NULL,而谓词为 NULL 的行会被丢弃。结果是零行。
-- Suppose blocked_names contains NULL:
SELECT name FROM users
WHERE name NOT IN (SELECT excluded_name FROM blocked_names);
-- → 0 rows, silently
-- Safer: filter out NULLs explicitly, or use NOT EXISTS:
SELECT name FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM blocked_names b WHERE b.excluded_name = u.name
);为什么 NOT EXISTS 更安全
NOT EXISTS 使用标准的相关子查询语义,并且能够安全处理 NULL。大多数规划器会将其优化为与格式正确的 NOT IN 完全相同的方式。
IN 与 OR:可读性
相比冗长的 OR 链,IN 更清晰,而且规划器通常会以相同方式进行优化:
-- Hard to read:
WHERE country = 'US' OR country = 'CA' OR country = 'GB' OR ...
-- Clear:
WHERE country IN ('US', 'CA', 'GB', ...)带元组的 IN(行构造器)
匹配多列组成的列对:
SELECT * FROM order_items
WHERE (order_id, product_id) IN (
(1, 42), (2, 99), (3, 17)
);索引使用
针对已建立索引的列使用 IN 列表时,可以执行多次索引查找(位图索引扫描)。通常速度很快。
-- Plan: Bitmap Index Scan + Bitmap Heap Scan
SELECT * FROM products WHERE id IN (1, 5, 99, 121, 4421);很大的 IN 列表
包含数千个值的列表可能会变慢。建议使用:
- 与实际表或临时表进行 JOIN
- 使用
= ANY(array)传递数组参数
SELECT * FROM products WHERE id = ANY(ARRAY[1,2,3,...]);空 IN 列表
标准 SQL 不允许空的 IN 列表。一些客户端会传递占位值;更安全的做法是有条件地生成 SQL 条件。
-- Use empty array trick in PostgreSQL:
SELECT * FROM products WHERE id = ANY($1::bigint[]);
-- Pass {} to get zero matches without rewriting the SQL.IN 与 JOIN
有时,使用 JOIN 比使用 IN 子查询更清晰:
-- With IN:
SELECT * FROM orders
WHERE user_id IN (SELECT id FROM users WHERE pro);
-- With JOIN:
SELECT o.*
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE u.pro;回顾
IN 是表示集合成员关系的简便形式。
- 为了可读性,优先使用 IN 而不是 OR
- NOT IN 遇到 NULL 时很危险,优先使用 NOT EXISTS
- 对于大型集合,使用 JOIN 或传递数组
快速检查
当子查询可能包含 NULL 时,NOT IN (subquery) 最安全的替代方式是什么?
常见问题解答
「使用 IN 和 NOT IN 处理集合」课时是免费的吗?
是的 — 「使用 IN 和 NOT IN 处理集合」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Academy 课程的其余内容,请升级到 CoddyKit PRO。 SQL Academy 课程共包含 4 节课。
「使用 IN 和 NOT IN 处理集合」这节课中我会学到什么?
使用 IN 和 NOT IN 根据值列表进行过滤,了解 NOT IN 中 NULL 带来的陷阱,并转换为 EXISTS 以获得安全语义。 你通过在浏览器中直接运行的动手代码来练习 SQL Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 IN 和 NOT IN 处理集合」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Academy 课中编写并运行代码吗?
能。每节 SQL Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- LIKE 模式与通配符
- 使用 IN 和 NOT IN 处理集合
- 使用 BETWEEN 处理范围
- IS NULL、IS NOT NULL 与 COALESCE