MySQL中WHERE子句不能用于LOAD DATA INFILE语句进行行级过滤,必须通过“临时表+INSERT...SELECT...WHERE”两步实现条件加载。
WHERE 子句不能直接用在 INSERT 或 LOAD DATA INFILE 语句里做行级过滤,这是 MySQL 的硬性限制 —— 想“只导入满足条件的数据”,必须换思路。
很多人尝试写类似这样的语句:
LOAD DATA INFILE '/tmp/data.csv' INTO TABLE orders WHERE status = 'pending';
这会直接报错 ERROR 1064 (42000):MySQL 语法不支持在 LOAD DATA 后加 WHERE。原因很实在:LOAD 是“批量灌数据”的底层操作,WHERE 是“查数据时做判断”的逻辑层,二者执行阶段和引擎路径完全不同。
SELECT、UPDATE、DELETE 走的是查询优化器路径,WHERE 在执行计划中可下推、可索引加速LOAD DATA 走的是存储引擎直写路径,跳过 SQL 解析的大部分环节,性能优先,不支持条件过滤INSERT ... SELECT ... WHERE 筛选落库这是生产环境最常用、最可控的做法。核心是把“过滤”从加载阶段移到插入阶段。
CREATE TEMPORARY TABLE orders_staging LIKE orders;
LOAD DATA 全量导入到临时表:LOAD DATA INFILE '/tmp/data.csv' INTO TABLE orders_staging;
WHERE 的 INSERT ... SELECT 精准迁移:INSERT INTO orders SELECT * FROM orders_staging WHERE status = 'pending' AND created_at >= '2025-01-01';
优势明显:WHERE 条件可任意组合(AND/OR/IN/BETWEEN 都行),还能配合索引加速;缺点是多一次 I/O 和内存拷贝,但对百万级以下数据几乎无感。
WHERE 表达式看着简单,实际踩坑最多的是类型和语义陷阱:

WHERE name = 'Alice',写成 WHERE name = Alice 会被当列名或变量报错NULL 不能用 = 判断:WHERE price = NULL 永远返回空结果,必须写 WHERE price IS NULL
'abc' = 'ABC' 为 true),要严格匹配加 BINARY:WHERE BINARY username = 'Admin'
LIKE 中的 % 和 _ 是通配符,真想查字面量下划线?得转义:WHERE comment LIKE '%\_error%' ESCAPE '\'
AND 和 OR 时,优先级容易出错 —— WHERE a=1 OR b=2 AND c=3 实际等价于 a=1 OR (b=2 AND c=3),不确定就加括号WHERE 写得再准,如果让索引失效,查十万行也像查百万行一样慢。
WHERE user_id = 123(等值查主键/索引列)、WHERE create_time BETWEEN '2025-01-01' AND '2025-12-31'(范围查有索引的时间字段)WHERE YEAR(create_time) = 2025(函数作用于索引列 → 全表扫描)、WHERE remark LIKE '%bug%'(前导 % → 无法用 B+Tree 索引)EXPLAIN 一下:EXPLAIN SELECT * FROM logs WHERE level = 'ERROR' AND created_at > '2025-12-01';看
type 是不是 ref 或 range,key 是否显示用了哪个索引真正难的从来不是写对 WHERE,而是写出让优化器愿意用索引的 WHERE —— 它不看你逻辑多漂亮,只认字段是否裸露、顺序是否匹配、函数有没有套壳。