资讯动态

MySQL入门必看:create.sql与populate.sql脚本深度拆解

发布时间:2026/10/16 23:12:01 来源:尧图企业网站定制
1. 为什么这两份SQL脚本是入门MySQL绕不开的起点当年学MySQL的时候几乎人手一本《MySQL必知必会》。这本书最大的特点是边看边练每一章都有能直接跑通的SQL示例。但示例要能跑前提是有一份能复现出同样数据的环境。官方配套的create.sql和populate.sql就是干这个的前者负责把六张演示表建出来后者负责往表里塞进足够撑起全书示例的数据。可以说没有这两份脚本书里从SELECT到存储过程的每一章你都只能干瞪眼。很多初学者把这两份脚本当成双击一下就跑完的一次性工具能跑通就不再管了。但恰恰是这两份脚本藏着学习关系型数据库设计的最佳模板。我后来带过不少新人发现凡是能把create.sql逐行讲明白的SQL功底都不差凡是只会照着执行、从没认真读过内容的遇到自己建表就懵。这套结论我用了很多年基本没失灵过。这篇内容适合谁刚入门MySQL、想跟着书里例子敲一遍代码的新手想看看一套演示用业务库到底怎么设计的学习者哪怕是有几年经验、但一直没认真读过一套完整建表脚本的人也值得把这两份脚本从头到尾扫一遍收获不会小。1.1 没有这两份脚本整本书的示例寸步难行这本书的章节安排是从最简单的单表查询一路讲到存储过程、触发器、事务。每一章的示例都建立在同一套数据之上如果每次都在临时造数据不仅浪费时间而且你练出来的查询结果跟书上的完全对不上很容易卡在我这结果到底对不对的困惑里。create.sql和populate.sql就是为这件事生的。它们构建了一套稳定的、已知结果的迷你业务库让你每做完一个练习都能拿自己的输出跟书上的示例输出直接对照。这就是为什么我强烈建议每次开始一个新章节之前如果上一章的操作改动了表结构或数据就先重新执行一遍这两份脚本让数据回到出厂状态。脚本里做了DROP TABLE IF EXISTS处理就是为了让你能反复执行、反复重置。1.2 create.sql和populate.sql的分工简单来说create.sql管结构populate.sql管数据。执行create.sql之后你的库里会出现六张互相咬合的表模拟的是一个挺典型的商品销售场景。执行populate.sql之后这些表里就有了足够你折腾几周的测试数据。两者必须按顺序执行先建表后填数这一点在后面的章节里会看得更清楚。我见过一种错误的用法有人只跑create.sql到了查询章节发现SELECT出来全是空表然后开始怀疑自己SQL写错了。真相往往只是少跑了populate.sql。所以跑完两份脚本后第一时间数一数每张表的行数这是后面所有操作的前提。1.3 适合什么人认真读这两份脚本如果你是照着书学的顺序型读者建议在学到第4章检索数据之前先把脚本完整跑通。如果你已经学完一遍、正在复习我更推荐你换个视角别把它们当脚本当成一份别人写的优秀建表作业来拆解。我后面会逐个表拆开讲你对照自己手里的文件看会发现一份演示脚本里其实藏着一整套正规库设计的讲究。2. 建表脚本的核心设计一个商品销售库的逐表拆解逐行读create.sql你会发现它没用任何花哨的语法也没有故意炫技的写法但每一处选择都有自己的道理。这种克制恰恰是它值得反复读的原因。2.1 六张表各自管什么先看总览这六张表的职责可以用一张表说清楚表名职责关键字段跟谁关联vendors供应商vend_id主键、vend_name、vend_address 等被 products 引用products商品prod_id主键、vend_id外键、prod_name、prod_price引用 vendorscustomers客户cust_id主键、cust_name、cust_contact 等被 orders 引用orders订单主表order_num主键、order_date、cust_id外键引用 customersorderitems订单明细order_num order_item 联合主键、prod_id外键引用 orders 和 productsproductnotes商品备注note_id主键、prod_id外键、note_text引用 products这六张表的组合不是随随便便挑出来的。vendors和products是一对多一家供应商能供多个商品orders和customers也是一对多一个客户能下多个订单orders和orderitems是一对多一张订单里有多行商品明细而orderitems通过prod_id又挂回products等于在products和orders之间搭了一座桥让一个订单包含多个商品、一个商品出现在多个订单里这种多对多关系有了落脚点。后面你学JOIN、子查询、聚合函数、分组统计所有示例几乎都是在这张表网里打转。如果这张网设计得不合理你会发现自己做练习时总得穿越好几张表才能拿到想要的数据学习成本会高出一大截。2.2 联合主键与外键orderitems表里藏着的设计课这六张表里我最想让初学者反复看的是orderitems表。它的主键不是单独的一列自增id而是(order_num, order_item)联合主键。这个设计很值得琢磨。订单明细天然就有某个订单里的第几行商品这种语义用订单号加行号联合起来做唯一标识既不会重复又直接表达了业务含义还省掉了一个没意义的代理主键列。我见过不少人学完这本书好几年回头自己写订单明细表还是习惯性加一行自增id。倒也不是不能用但跟书里这个设计一比差距就在思路主键不是表里必须有一列叫id而是到底哪一列或哪几列能唯一标识一行。为了想明白这一点这份create.sql就值得反复读。外键方面的写法不同流传版本会有差异。有的版本显式写了FOREIGN KEY约束有的版本为了兼容老版本MySQL只建索引没加约束。你拿到手的脚本以实际内容为准。我的建议是如果手里是没有显式外键的版本可以自己动手补上约束再跑一遍亲自体会一下约束带来的保护和报错这比干看书理解外键要深刻得多。2.3 字段类型选择的讲究create.sql里字段类型的选择也很有意思。products表的prod_price用的是DECIMAL(8,2)而不是FLOAT这个细节非常关键。金额这种东西用FLOAT算会出现二进制浮点误差。你在MySQL里跑一下SELECT 0.10.2结果可能不是0.3而是0.30000000000000004。做演示或许看不出大问题但做金额计算误差会一路累积。DECIMAL是定点数按十进制位存储做金额加减乘除是精确的。书里选择DECIMAL(8,2)等于在你还没学到浮点数的坑之前就先帮你避开了。此外客户表里的地址、邮箱多用VARCHAR长度都控制在够用的范围内比如VARCHAR(50)。订单日期order_date用DATETIME。这些选择透露出的是一套够用就好的价值观演示库不需要给每个字段预留无限长度字段越短索引越省空间写入和查询的开销也越小。很多人生产环境里拍脑袋给VARCHAR(500)往往就是没看过这种克制设计的缘故。create.sql的建表语句里每个CREATE TABLE都提前用DROP TABLE IF EXISTS做清理。这里有一个顺序讲究带外键的子表要排在父表前面删。比如先删orderitems、再删orders、最后删customers这样才不会有外键悬空。脚本里通常已经按这个顺序排好了但如果你以后自己写清理脚本记得别把父子顺序搞反。3. 填充数据的顺序逻辑与数据量设计populate.sql看起来就是一长串INSERT语句但它能讲出来的东西比表面看到的要多得多。3.1 为什么插入顺序被外键锁死外键约束的核心含义是子表里引用的ID父表里必须已经存在。这个规则直接决定了populate.sql里的插入顺序。正确的顺序是这样的vendors —— 供应商没有被别人引用可以先插products —— 需要vend_id所以必须在vendors之后customers —— 没有依赖插哪都行一般跟着orders前面orders —— 需要cust_id所以必须在customers之后orderitems —— 需要order_num和prod_id所以在orders和products之后productnotes —— 需要prod_id所以在products之后。你要是试着把第2步和第5步对调在启用外键约束的版本里MySQL会直接甩给你一个报错内容类似Cannot add or update a child row: a foreign key constraint fails。这不是脚本坏了是数据依赖没满足。有意思的是很多配套版本的populate.sql在文件组织上并没有刻意把这些表的INSERT分得泾渭分明而是按文件的自然顺序平铺下来。但因为作者知道依赖关系所以整体上文件顺序天然就是先父后子。你如果好奇为什么populate.sql的顺序长这样答案就在这里。换句话说外键约束不只是写在建表语句里的一张声明它会在你插入、更新、删除时被MySQL强制执行。跑一遍populate.sql等于用实际动作把这个规则复习了一遍。3.2 每张表的数据量为什么是这么多populate.sql里每张表的数据量都不是随手定的我按常见版本大概说几个数vendors5个供应商products10个商品恰好分布在5家供应商下每家2个customers50个客户orders5到10条订单orderitems十几到二十几条订单明细productnotes3条商品备注长短不一。这些数字是有讲究的。10个商品分给5家供应商每家正好2个这样你学GROUP BY的时候按vend_id分组的统计结果非常规整能一眼验证对错。50个客户这个量特别关键。书里讲ORDER BY排序、LIMIT分页、按州聚合、子查询找交集这些示例时都需要一个不大不小的数据池。如果只有5个客户很多查询一眼就能看穿结果练习就失去了意义而50个客户正好让你在验证结果时既有一定工作量又不至于眼花缭乱。至于productnotes表只有3条备注却故意让它们长短不一这是为后面全文本搜索章节准备的。没有一条足够长的note_text全文检索和LIKE的匹配效果就完全体现不出来。这些小设计恰恰是练习数据最值得抄作业的地方。很多人给测试库随便怼几行数据然后抱怨单表查询看不出效果其实就是数据量没设计好。3.3 脚本里容易被忽略的存储过程段落还要提醒一点某些版本的populate.sql并不只是INSERT文件靠后的部分可能会包含存储过程或者函数的定义为书里后面讲过程化编程的章节做准备。如果你在文件里看到CREATE PROCEDURE、DELIMITER $$之类的内容别慌这很正常。也正因为可能有这种多语句段落执行populate.sql时最好用支持多语句的客户端工具。某些网页版的在线SQL执行器只允许一次跑一条语句拿它跑这种脚本大概率会卡在DELIMITER的解析上然后你以为是脚本有问题其实是工具不对。4. 跑通脚本的实操全记录环境、命令和五个高频报错光看懂还不够必须亲手跑通。这一节我把实际操作中会遇到的事情完整交代一遍。4.1 执行前的三件准备第一MySQL服务必须活着。Windows上检查服务管理器里的MySQL服务macOS上可以用brew services list看一下先确保mysqld在运行。第二客户端能连上。命令行执行mysql -uroot -p输入密码能进到mysql提示符就行。连不上的话先排查端口、账号、密码基础问题先解决。第三也是最容易被忽略的要先确认这两份脚本默认用的是哪个数据库。市面上流传的《MySQL必知必会》配套脚本有的开头自带CREATE DATABASE IF NOT EXISTS crashcourse有的只写了USE crashcourse还有的既不带建库也不带USE。第一次执行之前花十秒钟把文件前几行打开看一眼比盲目执行省事得多。如果脚本里没有建库语句你就手动补上CREATE DATABASE IF NOT EXISTS crashcourse DEFAULT CHARACTER SET utf8mb4; USE crashcourse;4.2 三种执行方式与我的建议方式一客户端内SOURCE。登录进MySQL之后直接执行SOURCE /绝对路径/create.sql;。注意路径里的反斜杠在MySQL客户端里可能引发转义问题Windows下也建议用正斜杠。方式二操作系统shell管道方式。在终端里执行mysql -uroot -p create.sql。这种方式跟客户端里的SOURCE是两个环境别搞混。方式三图形工具整段执行。Workbench、Navicat这类工具直接打开SQL文件执行整段脚本报错信息能直接定位到某一行对新手最友好。我的建议是前几遍用图形工具跑因为能看到每一条语句的执行状态熟练之后再切到命令行SOURCE更贴近真实工作流。跑的时候先执行create.sql等它完全结束再执行populate.sql别两段连着一起跑否则建表还没完成就开始插数据容易出幺蛾子。4.3 五个高频报错完整对照跑脚本报错是家常便饭关键是会看报错。我把高频问题整理成一张表报错内容真正原因解决办法ERROR 1046 (3D000): No database selected脚本没带USE语句当前会话也没选中库先建库并执行USE crashcourse;再跑脚本ERROR 1366 (HY000): Incorrect string value客户端和服务器字符集不一致中文内容插入失败连接后先执行SET NAMES utf8mb4;或者连接参数加--default-character-setutf8mb4ERROR 1216 / 1452: Cannot add or update a child row插入顺序违反外键约束按先父后子的顺序执行或确认缺少依赖数据ERROR 1419: You may not create stored function服务器开了log_bin创建存储函数权限受限以root登录执行SET GLOBAL log_bin_trust_function_creators1;ERROR 1064: You have an error in your SQL syntax常见原因是文件被Windows记事本存成了带BOM的编码用编辑器把脚本另存为UTF-8无BOM再执行前三个几乎是新手必踩。尤其是ERROR 1366凡是脚本里带了中文内容而客户端字符集不匹配的时候就会出现。这个问题不是脚本本身坏了而是连接环境的字符集没对齐一条SET NAMES utf8mb4就能解决。4.4 跑完之后怎么验证这没白跑没有报错不等于成功。跑完populate.sql之后最直接的验证是看看每张表到底有多少行USE crashcourse; SHOW TABLES; SELECT COUNT(*) FROM vendors; SELECT COUNT(*) FROM products; SELECT COUNT(*) FROM customers; SELECT COUNT(*) FROM orders; SELECT COUNT(*) FROM orderitems; SELECT COUNT(*) FROM productnotes;对照我前面说的量级如果某张表是0行基本可以断定中途报错中断了脚本后面的INSERT没执行到。这种情况别想办法救把脚本从头到尾重新完整跑一遍。还有一种更贴近书中练习的验证方式跑一个最小化的两表联结查询。只要商品和供应商这两张核心表的数据是通的后面的章节基本不会有大问题SELECT prod_name, vend_name FROM products INNER JOIN vendors ON products.vend_id vendors.vend_id ORDER BY prod_name;正常会返回10行商品每行带着对应的供应商名称。看到这个结果说明跑脚本这关过了。5. 把这两份脚本用出花来进阶练习与改造路线脚本跑通只是起点。真正把这套数据价值榨干的方法是把它当成一块反复打磨的试验田。5.1 按章回炉把脚本当成练习题场地我的建议是不要把这两份脚本当成一次性启动器。每学到新章节都回到这几张表上做延伸练习。学到ORDER BY就试试对customers表按州和联系人排序学到通配符LIKE就在products表的prod_desc上练手学到子查询就拿订购了某商品的所有客户这种经典题目反复变着花样写。等你把这些例子都跑熟了再尝试一个更狠的练法合上书模仿create.sql的风格从零设计一个属于你自己的小库比如一个简单的借书系统或者一个打卡系统。自己设计表结构、决定主外键、规划插入顺序再写一套填充数据。这样走完一遍你对这两份脚本的理解就不只是能跑而是知道为什么这么写。5.2 用mysqldump反向拆解建表写法这里有个进阶玩法。你在脚本建好的库里已经动手改过、加过自己的数据这时候用mysqldump把当前表结构导出来跟官方create.sql做对比mysqldump -uroot -p --no-data crashcourse schema_my.sql打开导出的schema_my.sql你会发现MySQL自己生成的语句多了很多反引号、表级选项、外键约束的完整声明。跟官方版本逐表对比你能直观理解SQL脚本有无数种写法关键是语义一致这件事。我自己当年就是靠这个对比把外键约束到底在干什么彻底搞明白的。5.3 三种改造方向补外键、加索引、扩数据方向一是补外键。如果手里的create.sql没有显式FOREIGN KEY你可以手动加上重新跑一遍体验约束带来的保护也体验违反约束时的报错。方向二是加索引并研究执行计划。比如给orders表的order_date加个索引ALTER TABLE orders ADD INDEX idx_order_date (order_date); EXPLAIN SELECT * FROM orders WHERE order_date 2005-01-01;对比加索引前后EXPLAIN结果里的扫描行数和type列你对索引的理解会比看书深刻得多。方向三是扩数据量。把50个客户扩展到500个甚至把订单数据造到几千条拿去做分页查询、性能对比和窗口函数练习效果完全是另一个维度。数据一多很多书上说的性能问题才真的浮出水面。5.4 我踩过的三个坑最后交代一点个人教训全是真金白银换来的。第一个坑是直接改原脚本。有一阵子我为了练手直接在create.sql里增加了一个字段结果后面章节的示例全乱套因为书里的INSERT和查询都是按原字段名写的。正确做法是复制一份脚本再改原版留着跑书上的例子。第二个坑是学习过程中没重置数据。有些章节练习会修改表结构、删除数据或改动字段值做完之后如果你不重置下一章查询的结果就跟书上对不上。养成习惯每次开新章节之前把create.sql和populate.sql重新SOURCE一遍。反正有DROP TABLE IF EXISTS兜底这套脚本天生就是为反复执行设计的。第三个坑和编码有关。在Windows上如果脚本文件被记事本存成了带BOM的UTF-8第一行会混进一个看不见的BOM字符导致第一条语句解析报错。解决方案很粗暴但有效用VS Code、Notepad这类工具把文件另存为UTF-8无BOM。5.5 从照搬到设计一份属于你自己的create.sql写到这我想说一句实在话。很多人学完这本书觉得书看完了、例子跑完了但一遇到自己建表就露怯。问题不在练习不够而在没有真正消化这份脚本背后的设计决策。你能不能用今天拆解过的思路重新审视甚至重新实现一份自己的create.sql如果能你的SQL水平就真的上了一个台阶。我自己带新人的时候特别喜欢把这份脚本打印出来让新人逐行讲一遍每段CREATE TABLE的意图。能讲明白的基本不需要再补基础讲不明白的回去翻书、照着脚本多练几遍。这套方法我用了很多年效果一直很稳定。要说这套脚本最大的价值其实不是让你学会了几个命令而是让你第一次见到一份正经业务库应该长什么样。从这个角度看它值得你反复翻出来品。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑