会报错;因MySQL不支持SQL Server的TOP、GETDATE()、IDENTITY及方括号标识符(如[User]),需转换语法后导入。
SQL Server 的 .sql 文件直接导入 MySQL 会报错?别硬试
mysql 不认 sql server 的 top、getdate()、identity 声明,也不支持方括号标识符(如 [user])。直接用 mysql -u root -p 几乎必挂,常见错误是 <code>error 1064 (42000) 或 unknown column 'getdate()' in field list。
必须先做语法清洗,不是格式转换——重点在删/换/绕过 SQL Server 特有语法:
-
TOP N→ 改成LIMIT N(注意:MySQL 的LIMIT必须放在语句末尾,且不能和ORDER BY分开写) - 方括号
[xxx]→ 全部替换成反引号`xxx`,或直接去掉(如果标识符不冲突) -
GETDATE()→ 换成NOW();ISNULL()→ 换成IFNULL();LEN()→ 换成LENGTH() - 带默认值的列定义里含
IDENTITY(1,1)→ 删掉整段,改用AUTO_INCREMENT在建表后单独加
用 sed 和 perl 批量清洗比手动改快得多
小文件('GETDATE()' 里的字也换了)。
推荐分步执行(Linux/macOS 终端):
- 去方括号:
perl -i -pe 's/\[(.*?)\]/`$1`/g' dump.sql(只匹配非贪婪内容,避免嵌套误伤) - 换
TOP:sed -i 's/SELECT TOP \([0-9]\+\) /SELECT /; s/$/ LIMIT \1/' dump.sql(注意:这仅适用于单行SELECT TOP,多行需用 awk) - 函数替换:
sed -i 's/GETDATE()/NOW()/g; s/ISNULL(/IFNULL(/g; s/LEN(/LENGTH(/g' dump.sql - 删
IDENTITY行:sed -i '/IDENTITY/d' dump.sql(建表语句中这一行删掉即可,后续加AUTO_INCREMENT)
建表语句里 datetime 类型要检查精度兼容性
SQL Server 的 DATETIME2(7) 或 SMALLDATETIME 在 MySQL 中没有完全对应类型。MySQL 5.6+ 的 DATETIME 支持微秒(DATETIME(6)),但旧版只到秒级。
导出前若无法控制源格式,导入时容易遇到:
-
ERROR 1067 (42000): Invalid default value for 'created_at'(因默认值含毫秒,MySQL 不认) -
Truncated incorrect datetime value(时间字符串格式不符,如'2023-01-01T00:00:00'中的T)
稳妥做法:
- 把所有
DATETIME2(n)替换为DATETIME(丢精度但能过) - 把
DEFAULT GETDATE()改成DEFAULT CURRENT_TIMESTAMP(MySQL 5.6.5+ 支持) - 对含
T的 ISO 格式时间字符串(如'2023-01-01T12:34:56.123'),用sed预处理:sed -i "s/T/ /g; s/\.[0-9]\+//g" dump.sql
导入前务必关掉 MySQL 的严格模式
SQL Server 导出的语句常含隐式类型转换、空字符串插入 NOT NULL 字段等行为,MySQL 严格模式(STRICT_TRANS_TABLES)会直接拒绝。
临时关闭方法(导入期间生效):
- 连接时加参数:
mysql -u root -p --init-command="SET sql_mode=''" - 或在
dump.sql开头加一行:SET sql_mode = '';
注意:这不是长久方案,只是让导入跑通。导入成功后,应逐表检查数据完整性,特别是数值截断、时间归零、空值变默认值等情况——这些在日志里不会报错,但数据已失真。
最麻烦的从来不是语法转换,而是 SQL Server 默认值逻辑(如 DEFAULT ((1)))和约束(如 CHECK ([status] IN ('A','I')))在 MySQL 里没等价实现,得人工补。

















