navicat 16 不支持自动识别分表并合并导入,必须用 union all 显式拼接分表数据、人工控制字段对齐、去重及主键冲突策略,并通过 insert ignore 或 on duplicate key update 处理重复。

Navicat 16 不支持“自动识别分表并合并导入”
你不能右键选中 orders_202401、orders_202402、orders_202403 然后点“导入向导”就指望它自动拼成一张 orders。Navicat 对“分表”没有语义理解能力——它只把每个文件/表当作独立实体处理,不会推断字段映射、时间分区逻辑或主键去重规则。
真正能落地的方式是:先用 SQL 显式合并数据,再导出结果,最后导入目标单表。中间必须人工控制三件事:字段对齐、时间范围去重、主键冲突策略。
用 UNION ALL + INSERT INTO 合并分表数据到临时表
这是最可控、可验证、可中断重试的路径。别依赖 Navicat 的“批量导入”,它无法跨表做字段类型校验和 NULL 填充。
- 在 Navicat 查询窗口中执行建表语句,确保字段名、类型、长度与目标单表完全一致(注意:
orders_202401.id和orders_202402.id是否都为BIGINT UNSIGNED?不一致会截断) - 用
UNION ALL拼接所有分表,显式列出字段(禁用*),对缺失字段补NULL或默认值:SELECT id, order_no, amount, created_at, '202401' AS source_month FROM orders_202401 UNION ALL SELECT id, order_no, amount, created_at, '202402' AS source_month FROM orders_202402 UNION ALL SELECT id, order_no, amount, created_at, '202403' AS source_month FROM orders_202403;
- 若目标单表有自增主键且分表中已含真实 ID,插入前需确认
SET FOREIGN_KEY_CHECKS=0和SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'已生效
导入时主键冲突/重复数据怎么处理
直接 INSERT INTO orders SELECT ... 很容易报 Duplicate entry '12345' for key 'PRIMARY'——因为多张分表可能都含同一批历史 ID(比如按业务线拆分而非时间拆分)。
- 优先用
INSERT IGNORE INTO orders:跳过冲突行,适合“以最早写入为准”的场景 - 需要“以最新分表为准”?改用
ON DUPLICATE KEY UPDATE,例如:amount = VALUES(amount), updated_at = VALUES(updated_at) - 想严格去重并保留完整上下文?先
CREATE TEMPORARY TABLE deduped AS SELECT ..., ROW_NUMBER() OVER (PARTITION BY id ORDER BY created_at DESC) rn FROM (...) t,再INSERT INTO orders SELECT ... WHERE rn = 1 - 切忌勾选导入向导里的“清空目标表”——除非你确认分表已覆盖全量数据;否则会误删存量记录
大数据量下避免 Navicat 内存溢出或超时
当分表总行数超 200 万,Navicat 默认加载全部结果集再执行 INSERT,极易卡死或生成损坏文件。
- 在查询开头加
SELECT SQL_BUFFER_RESULT ...强制 MySQL 服务端暂存结果,减轻客户端压力 - 分批执行:用
LIMIT+OFFSET(注意深分页性能),或按时间字段切片:WHERE created_at BETWEEN '2024-01-01' AND '2024-01-31' - 导出为
.sql文件再用命令行导入(避开 Navicat GUI 内存限制):mysql -u root -p target_db - 如果目标库是 PostgreSQL,注意 Navicat 导出的 MySQL 语法(如
INT(11)、反引号)需手动替换,否则psql直接报错
最容易被忽略的是字段默认值继承问题:分表中某列为 NOT NULL DEFAULT 'N/A',但合并查询里没显式提供该字段,MySQL 会报错;必须在 SELECT 列表中补上 'N/A' AS status 这类占位。











