必须分步干预:先逆向表到模型并转换为mysql 8.0,手动修正类型映射与sql语法,再导出并运行sql文件;直接数据传输会丢主键、错类型、失精度。

不能靠“数据传输”一键完成——SQL Server 到 MySQL 的迁移在 Navicat 中必须分步干预,否则必然丢数据、错类型、报语法错误。
用「逆向表到模型」+「转换模型为 MySQL」生成结构
Navicat 的「数据传输」功能对 SQL Server → MySQL 支持极弱,会直接跳过类型映射、忽略默认值语义、把 datetime2 当作 datetime 处理,导致精度丢失或导入失败。真正可靠的做法是走模型路径:
- 右键 SQL Server 中的目标表 → 选择「逆向表到模型」,生成可视化 ER 图
- 在模型窗口顶部菜单选「转换模型为」→ 明确指定
MySQL 8.0(不要选“自动”或低版本) - Navicat 会重写字段类型:比如把
BIT转成TINYINT(1)或BOOLEAN,UNIQUEIDENTIFIER转成CHAR(36),DATETIME2(7)转成DATETIME(6) - 检查转换后的模型,手动修正不合理的映射(例如把
NVARCHAR(MAX)改成TEXT,而非默认的VARCHAR(4000)) - 再从模型导出 SQL:右键模型 → 「导出 SQL」→ 保存为
.sql文件
导入前必须手动清理 SQL 文件中的 SQL Server 特有语法
导出的 SQL 文件仍含大量 SQL Server 原生成分,MySQL 服务端无法执行:
- 全局搜索并删除所有
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ...)索引选项(MySQL 不识别) - 将
DEFAULT GETDATE()或DEFAULT SYSUTCDATETIME()替换为具体时间字面量,如DEFAULT '2024-01-01 00:00:00' - 把
CREATE TABLE ... ON [PRIMARY]整行删掉(MySQL 无文件组概念) - 确认字符集声明为
CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci(尤其目标为 MySQL 8.0+)
用「运行 SQL 文件」导入,别用查询窗口执行
大表结构 + 百万级 INSERT 混合的 SQL 文件,若在 Navicat 查询窗口中粘贴执行,极易因客户端缓冲溢出、超时中断或 BLOB 截断失败:
- 右键目标 MySQL 数据库 → 「运行 SQL 文件」→ 选中已修正的
.sql文件 - 务必取消勾选「执行每个语句前暂停」,否则每条 INSERT 都要人工点确认
- 若文件 > 5MB,提前在 MySQL 服务端执行:
SET GLOBAL max_allowed_packet = 268435456;(256MB) - 导入过程中关闭 Navicat 其他连接,避免会话级
sql_mode冲突影响默认值校验
迁移后重点验证字段精度、NULL 行为与主键连续性
Navicat 显示“成功”只是语句执行完毕,不代表业务可用:
- 对比源表和目标表的
SHOW CREATE TABLE输出,确认TINYINT(1)是否被当布尔处理、IDENTITY是否转成AUTO_INCREMENT且起始值一致 - 查几条含
DATETIME2(7)的记录,看微秒部分是否完整保留(MySQL 5.6 不支持,必须用 5.7+ 或 8.0) - 执行
SELECT COUNT(*) FROM target_table和SELECT COUNT(*) FROM source_table,但更要查SELECT COUNT(*) FROM target_table WHERE id IS NULL——SQL Server 的NOT NULL约束可能在转换中被弱化 - 对含自增主键的表,执行
SELECT MAX(id) FROM target_table,确认没因插入失败导致 ID 断层
最常被跳过的一步是验证字段排序规则(collation):SQL Server 默认用 SQL_Latin1_General_CP1_CI_AS,而 MySQL 的 utf8mb4_0900_ai_ci 在大小写和重音处理上行为不同,模糊查询结果可能不一致——这点在线上环境爆发时很难回溯。











