mysqldump默认不生成if not exists,需用sed或perl手动替换;pg_dump不支持该语法,可用--inserts绕过;sql server需用if not exists+begin...end模板;推荐schemacrawler统一生成兼容ddl。
mysql 5.7+ 导出时加 if not exists 需手动补,mysqldump 默认不生成
mysqldump 工具本身从不自动在 create table 或 create database 语句前加 if not exists,哪怕你加了 --skip-create-options 或 --add-drop-table 也没用。这是设计使然——它专注“导出快照”,不是“生成可重入脚本”。
常见错误现象:直接拿 mysqldump 输出去执行,遇到库/表已存在就报错 ERROR 1007 (HY000): Can't create database 'xxx'; database exists 或 ERROR 1050 (42S01): Table 'xxx' already exists。
- 最直接的实操方式是导出后用
sed或perl批量替换(Linux/macOS):mysqldump -u root -p mydb | sed 's/CREATE TABLE `/CREATE TABLE IF NOT EXISTS `/g; s/CREATE DATABASE `/CREATE DATABASE IF NOT EXISTS `/g'
- 注意
CREATE DATABASE通常只出现在带--databases或--all-databases的导出中;单库导出一般没有这行,别白搜 - 如果表名含反引号或特殊字符,简单
sed可能误匹配;稳妥起见,用perl -pe做更精确的行首锚定:mysqldump -u root -p mydb | perl -pe 's{^(CREATE TABLE `[^`]+`)}{CREATE TABLE IF NOT EXISTS $1} or s{^(CREATE DATABASE `[^`]+`)}{CREATE DATABASE IF NOT EXISTS $1}'
PostgreSQL pg_dump 不支持 IF NOT EXISTS,但可用 --inserts + 自定义逻辑绕过
pg_dump 的 --if-exists 参数仅控制 DROP 语句(如 DROP TABLE IF EXISTS),对 CREATE 无影响。它压根不提供 CREATE TABLE IF NOT EXISTS 选项,因为 PostgreSQL 在 9.6 之前根本不支持该语法,而 pg_dump 要兼顾老版本兼容性。
使用场景:你想把 dump 脚本当“幂等初始化脚本”用,又不想改应用层逻辑。
- 推荐组合:导出用
pg_dump --inserts --column-inserts,这样生成的是INSERT INTO ... VALUES而非COPY,方便后续加ON CONFLICT DO NOTHING - 若必须保留
CREATE TABLE,只能靠外部工具注入——比如用 Python 脚本读取 dump 文件,对每行匹配^CREATE TABLE并前置IF NOT EXISTS(注意 PostgreSQL 语法要求是CREATE TABLE IF NOT EXISTS table_name (...),不能多空格或换行) - 性能影响:加
--inserts后体积变大、导入变慢,但换来的是可控的冲突处理能力;别在大数据量场景盲目套用
SQL Server 使用 sqlcmd + 模板 SQL 实现真正幂等导出
SQL Server 没有原生命令行导出工具能直接输出带 IF NOT EXISTS 的建表语句。SSMS 图形界面生成的脚本虽然可勾选“检查对象是否存在”,但那是 GUI 行为,不可复现、难自动化。
实操建议走“元数据查询 + 模板拼接”路线,比硬解析 sp_help 输出更稳:
- 核心思路:用
sys.tables和sys.columns查结构,用sys.dm_exec_describe_first_result_set(SQL Server 2012+)辅助推断类型,再套 T-SQL 模板 - 最小可行模板示例(用于单表):
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'mytable' AND type = 'U') BEGIN CREATE TABLE mytable (id INT PRIMARY KEY); END
- 容易踩的坑:SQL Server 的
IF NOT EXISTS对索引、约束不生效;主键/唯一约束仍可能因重复定义报错,得单独加IF NOT EXISTS判断sys.key_constraints - 兼容性注意:SQL Server 2008 不支持
CREATE TABLE IF NOT EXISTS,必须降级为IF NOT EXISTS (...) BEGIN CREATE TABLE ... END结构
通用方案:用 schemaCrawler 这类元数据工具生成带容错的 DDL
比起手写正则或拼 SQL,用专业元数据工具更可靠。SchemaCrawler(Java 写的开源 CLI)能直接输出符合目标数据库语法习惯的、带 IF NOT EXISTS 的建库建表语句,且支持 MySQL、PostgreSQL、SQL Server、Oracle 等主流库。
关键参数就两个:-command=schema(只导结构)、-outputformat=sql,再加 -infolevel=standard 控制细节粒度。
- 执行示例(MySQL):
schemacrawler.sh -server=mysql -database=mydb -host=localhost -port=3306 -user=root -password=xxx -command=schema -outputformat=sql -infolevel=standard > ddl.sql
- 它生成的语句默认就是
CREATE DATABASE IF NOT EXISTS+CREATE TABLE IF NOT EXISTS,不用额外加工 - 注意点:SchemaCrawler 不导数据,只导 DDL;如需数据,得另跑
mysqldump或pg_dump,再合并脚本 - 版本差异:v16+ 开始支持 PostgreSQL 的
IF NOT EXISTS,旧版可能只生成基础CREATE;用前先schemacrawler -version确认
真正的麻烦不在加不加 IF NOT EXISTS,而在不同数据库对“存在”的定义不一致——MySQL 看库名是否在 information_schema.SCHEMATA,PostgreSQL 看 pg_database,SQL Server 看 sys.databases。工具只是封装了这些差异,自己写就得一个个对齐。










