默认选 UNION ALL,除非明确需要去重;列数、顺序、类型必须严格一致,字段按位置匹配而非名称,别名仅以首查询为准,ORDER BY/LIMIT 必须置于末尾,类型不兼容时应显式 CAST。

默认选 UNION ALL,除非你明确需要去重;漏掉字段对齐、类型兼容或末尾排序控制中的任意一项,结果可能错得毫无征兆。
列数和顺序必须严格一致,MySQL只认位置不认名字
MySQL 合并时完全按 SELECT 列的**位置顺序**匹配,第一个 SELECT 的列名决定最终字段名,后面所有别名都会被忽略。一旦顺序错位,数据就直接写进错误字段里。
- 正确写法:
SELECT id, name, created_at FROM t1 UNION ALL SELECT id, name, created_at FROM t2 - 危险反例:
SELECT name, id, created_at FROM t1 UNION ALL SELECT id, name, created_at FROM t2→ 第二个查询的id值会塞进结果集的name列 - 缺字段必须占位:
SELECT id, name, NULL AS city FROM t1 UNION ALL SELECT id, name, city FROM t2,不能省略或换序
对应列的数据类型要兼容,别依赖隐式转换
MySQL 会尝试隐式转换,但边界模糊时容易出错:比如 TINYINT 和 DATETIME 强行合并可能返回 0 或报错;CHAR(10) 和 TEXT 虽能兼容,但长度截断风险高。
- 安全组合:
INT/BIGINT、VARCHAR(50)/VARCHAR(200)、DECIMAL(10,2)/INT - 建议显式转换统一类型:
CAST(updated_at AS DATE)、COALESCE(status, 'unknown') - 避免混用:
BIT和JSON、不同精度浮点(FLOATvsDOUBLE)
ORDER BY 和 LIMIT 只能加在最后,中间加会报错
UNION ALL 是集合操作,不是嵌套结构。每个子查询单独加 ORDER BY 或 LIMIT 会触发语法错误,除非你把它包成子查询。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 整体排序(合法):
(SELECT id, name FROM t1) UNION ALL (SELECT id, name FROM t2) ORDER BY name DESC - 整体限制条数(合法):
... UNION ALL ... LIMIT 100 - 某一边取最新 5 条(必须子查询):
(SELECT * FROM logs WHERE type='error' ORDER BY id DESC LIMIT 5) UNION ALL SELECT * FROM logs WHERE type='warn' - 错误写法:
SELECT id FROM t1 ORDER BY id LIMIT 10 UNION ALL SELECT id FROM t2→ 报错
别用 UNION ALL 替代 JOIN,语义和性能都错配
它只是纵向拼接,不建立行与行之间的逻辑关联。想按主键、外键或条件匹配数据,该用 JOIN 就用 JOIN;想合并明细、拼接分区表、汇总多来源统计,才是它的主场。
- 典型误用:
SELECT order_id, user_id FROM orders UNION ALL SELECT order_id, product_id FROM order_items→ 字段语义错乱,user_id和product_id强行挤进同一列 - 典型正用:
SELECT * FROM orders_2024 UNION ALL SELECT * FROM orders_2025(分年表合并) - 带来源标识更清晰:
SELECT 'online' AS source, user_id, amount FROM payments_online UNION ALL SELECT 'offline', user_id, amount FROM payments_offline
最常被忽略的是「字段顺序」和「类型显式转换」——它们不出错则已,一出就是静默错位,查起来极费时间。宁可多写几个 CAST,也不要赌 MySQL 的隐式转换靠谱。










