直接执行init.sql最省事,需mysql服务正常、有足够权限;脚本须按drop db→create db→use→create table→insert顺序编写,开头加set names utf8mb4,建表指定innodb和utf8mb4字符集,插入用insert ignore或replace避免重复报错。

直接执行 init.sql 脚本最省事
只要 MySQL 服务已正常运行,且你有 root 或具备 CREATE/INSERT 权限的账号,就不用写代码、不依赖框架,一条命令就能完成建库、建表、插数据三件事。
关键前提是:把所有 SQL 合并进一个 init.sql 文件,且顺序合理——先 DROP DATABASE IF EXISTS(可选),再 CREATE DATABASE,USE 切库,然后是 CREATE TABLE,最后才是 INSERT INTO。
常见错误现象:脚本里漏了 ;,或 INSERT 写在 CREATE TABLE 前面,导致报错 ERROR 1146 (42S02): Table 'xxx' doesn't exist。
-
init.sql开头加SET NAMES utf8mb4;,避免中文乱码 - 建表语句中显式指定
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci - 插入数据用
INSERT IGNORE INTO或REPLACE INTO,保证重复执行不中断 - 执行命令:
mysql -u root -p your_db_name (注意不是 <code>mysql -u root -p ,否则会连到 <code>information_schema)
用 INSERT IGNORE 避免初始化时主键/唯一键冲突
测试数据常含固定 ID(比如 id=1 的管理员用户),但表启用了 AUTO_INCREMENT。如果脚本反复执行,第二次就会因主键重复报错 ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'。
这时候不能删表重来,也不能手动改 AUTO_INCREMENT 值——容易破坏后续自增逻辑。正确做法是让插入逻辑“跳过已存在记录”。
-
INSERT IGNORE INTO users (id, username) VALUES (1, 'admin');—— 静默忽略冲突,不报错也不插入 -
INSERT INTO users (id, username) VALUES (1, 'admin') ON DUPLICATE KEY UPDATE username = VALUES(username);—— 冲突时更新,适合需覆盖字段的场景 - 慎用
REPLACE INTO:它本质是DELETE + INSERT,会触发自增 ID 跳变,且可能误删关联数据
初始化脚本必须检查表是否存在再操作
很多团队把初始化逻辑写进应用启动代码(比如 Spring Boot 的 @PostConstruct 或 Flyway),但若脚本没做防御性判断,第一次跑完再重启应用就会失败。
核心问题不在 SQL 本身,而在执行上下文是否可控。纯 SQL 脚本没有 if-else,只能靠语句组合模拟条件逻辑。
- 建表前加:
CREATE TABLE IF NOT EXISTS users (...); - 插入前查表是否为空(适用于必须只插一次的场景):
INSERT INTO config SELECT 'site_name', 'MyApp' FROM dual WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'site_name'); - 更稳妥的做法是拆成两个脚本:
schema.sql(只建结构,带IF NOT EXISTS)和data.sql(只插基础数据,用INSERT IGNORE)
字符集与排序规则别等出问题才想起
初始化时没设 utf8mb4,后面插入 emoji 或某些生僻汉字会直接报错 ERROR 1366 (HY000): Incorrect string value,而修复成本远高于一开始写对。
这不是“建议”,而是硬性前置条件:MySQL 8.0 默认 character_set_server 是 utf8mb4,但老版本或 Docker 镜像可能仍是 latin1;即使服务端正确,建库建表时没显式声明,也会继承默认值,导致表级字符集不一致。
- 创建数据库时必须写全:
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 每个
CREATE TABLE后追加:ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - 验证方式:
SHOW CREATE TABLE users;看输出里是否有DEFAULT CHARSET=utf8mb4
最容易被忽略的是:同一张表里不同字段用了不同字符集(比如 name VARCHAR(50) CHARACTER SET latin1),这种混合定义会让索引失效、JOIN 变慢,且无法通过 ALTER TABLE 一键修正——必须导出再重建。初始化阶段一次性写对,比后期排查强十倍。











