1. 打开Navicat之前:先搞清楚它到底解决了什么问题
很多初学者学MySQL,第一步被要求背SQL语句,第二步就是打开命令行敲命令,第三步觉得“这也太难用了”,于是转到Navicat图形界面。结果用了两天又觉得“Navicat就是个点鼠标的工具,用久了连SQL都不会写了”。
这个想法我见得太多了,但它其实错得很彻底。
Navicat不是让你放弃SQL,而是把MySQL表操作的整个生命周期——创建、查看结构、修改、删除——变成了可以随时看、随时点、随时验证的操作界面。它的价值不在于“替代”SQL,而在于让你每做一个图形操作,都能看到背后生成的SQL语句,从而反过来加深对SQL的理解。
我自己的经验是:用Navicat操作表结构时,一定养成“盯着SQL预览”的习惯。这样你点一次“增加字段”,屏幕上就多一句ALTER TABLE,点一次“修改字段类型”,SQL预览里就自动给出对应的CHANGE语句。时间一长,你对数据库操作的理解会比单纯背命令深刻得多。
所以这篇内容不打算讲那种“先打开Navicat,再点击新建连接”的基础到不能更基础的教程,而是把你真正会遇到的问题串一遍:连接失败怎么办、建表时字段类型怎么选、修改表结构背后发生了什么、删表时DROP和DELETE到底有什么区别,最后给一套模拟练习,让你照着做一遍,把知识点真正变成手下的肌肉记忆。
适合谁看?刚学MySQL的学生、转行做数据分析或后台开发的新人、以及要给组里新人做培训的老手。老手看这篇也能帮新人答疑,因为踩坑点都写出来了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 连接MySQL最容易翻车的几个环节
2.1 先确认MySQL服务真的在运行
第一次在Navicat里新建连接,很多人都栽在“明明MySQL装过了,为什么连接失败”上。不是你输错密码,而是MySQL服务根本没起来。
Windows上打开“服务管理器”(Win+R,输入services.msc),找名字里带MySQL的服务,比如MySQL80或者MySQL57,看状态是不是“正在运行”。没运行就右键启动,顺手把启动类型改为“自动”,免得每次开机都要手动启一次。
macOS或Linux上,常用的命令是brew services list或者systemctl status mysql。如果用的是Docker部署的MySQL,还要确认容器处于运行状态,并且端口映射正确。这里有个很容易忽略的地方:容器里MySQL的端口如果是3307映射到宿主机的3306,你在Navicat里填的端口应该是3306,而不是3307。
2.2 新建连接里每一项分别是什么意思
Navicat新建连接时弹出来的表单,很多人只顾着填用户名和密码,其他字段直接忽略。我来逐个说一下它们的作用:
- 连接名:只是在Navicat界面上显示的名字。它不影响实际的数据库连接,完全可以叫“本地测试库”或者“生产环境别乱动”。
- 主机:填IP地址或域名。连接本机填localhost或127.0.0.1。如果你的MySQL跑在另一台服务器上,这里就要填那台服务器的内网IP或公网IP。
- 端口:MySQL默认是3306。如果你在安装时改过端口,或者在Docker映射时改过,这里必须一一对应。
- 用户名和密码:就是MySQL的登录账号。一般用root,但生产环境更推荐单独建一个账号,权限只给需要的数据库,避免权限过大。
- 保存密码:我强烈建议自己开发的电脑上可以勾选,但如果是共用电脑或公司设备,最好别勾,防止别人直接从你的Navicat里拖走数据库凭证。
这些都填好之后,点“测试连接”,如果弹出“连接成功”,说明这一步已经通了。
2.3 常见的连接报错,一张表看清
我见过最常见的连接报错就那几种,直接抄答案:
| 报错代码或提示 | 原因 | 处理方式 |
|---|---|---|
| 2003 - Can't connect to MySQL server | 服务没启动,或者端口不通 | 检查服务状态、防火墙是否放行3306端口、容器映射是否正确 |
| 1045 - Access denied | 用户名或密码错误 | 确认账号、密码;MySQL 8默认认证插件是caching_sha2_password,老版本Navicat会连不上,升级Navicat版本或改用mysql_native_password |
| 1049 - Unknown database | 指定了不存在的数据库 | 连接时保留默认数据库留空,或者建好库之后重新选库 |
| 10061 - 由于目标计算机积极拒绝 | Windows下服务未启动 | 去服务管理器启动MySQL服务 |
补充一个国内环境常见的老坑:如果下的是比较老的Navicat(比如11.x),去连MySQL 8,会被认证插件卡住。这是因为MySQL 8默认用了caching_sha2_password,旧版客户端不支持。解决方案很简单,第一优先是升级Navicat版本,实在不行再考虑把用户的认证方式改回mysql_native_password。从安全角度讲,升级工具是正路,改插件是续命方案,别搞反了。
3. 创建表:别急着点“新建”,先弄明白字段和类型
3.1 建库时先管好字符集和排序规则
很多人打开Navicat,右键“连接”里的数据库想新建一个库,看到字符集选项就懵了。这里直接给结论:MySQL 8选utf8mb4,排序规则选utf8mb4_0900_ai_ci。
为什么不是utf8?因为MySQL里那个叫utf8的字符集其实只支持最多3个字节的字符,它存不了emoji,也存不了某些生僻汉字。而utf8mb4才是真正的“UTF-8全量实现”,最多4个字节。你把用户昵称字段设成utf8,用户一注册就传个emoji,插入直接报错,属于很经典的翻车现场。
排序规则里的_ai_ci表示accent insensitive和case insensitive,也就是排序时不区分重音、不区分大小写。日常业务用这个最省心。如果以后有特殊排序需求,比如拼音排序、二进制精确匹配,那再单独调整,不要上来就用奇怪的排序规则。
3.2 新建表里每个字段选项的含义
Navicat打开“新建表”,表格的每一行就是未来表中的一个字段。你需要理解这么几个列:
- 字段名:列的名字,建议不要用中文,不要用
order、group这类保留字,否则每次写SQL都要加反引号,麻烦得很。 - 类型:就是字段的数据类型,下面专门讲。
- 长度:比如varchar(50)里的50是字符长度,不是字节长度。int(11)里的11在MySQL 8里已经只是“显示宽度”,不限制取值范围,以前很多人以为是“最多存11位数字”,这是历史误解。
- 允许空值:如果字段业务上必须存在值,取消勾选,这样插入数据时不填就会直接报错,从数据库层面拦住脏数据。
- 键:设置主键、唯一索引、普通索引。
- 注释:给字段写说明。给字段加注释是专业素养的表现,不然半年后你看着一个
st字段,完全想不起来它到底代表什么。 - 默认值:插入时如果不给这个字段传值,数据库用什么值替代。比如创建时间字段可以默认填
CURRENT_TIMESTAMP。
3.3 字段类型选择的实战建议
类型选错了,后面改起来很麻烦,所以我直接给出最常见业务表里推荐的类型组合。
- 整数:用户ID、订单号这种没有小数概念的数字用
INT。如果可能超过21亿,用BIGINT。注意主键自增的字段通常用BIGINT UNSIGNED,因为从0开始用有符号的INT,理论上只够到21亿多,对电商大厂不够用,对大多数中小项目其实够用。为了省心,新建主键直接用BIGINT没毛病。 - 小数:价格、金额这类对精度敏感的数据,用
DECIMAL(10,2),别用DOUBLE或FLOAT。浮点数是近似值,会在加减乘除时产生误差。你要做一个购物车,商品总价如果因为浮点运算变成99.9999,到时候排查起来非常酸爽。 - 字符串:短文本用
VARCHAR,比如用户名、手机号、邮箱、地址。它按实际长度存储,所以不要一看到文本就设成255,更不要每个字段都是VARCHAR(1000),过大过长的字段定义会浪费内存和索引空间。超长文本,比如文章正文、商品详情,用TEXT或LONGTEXT。注意TEXT字段不能直接加默认值,这是MySQL一直以来的限制。另外,TEXT类型不能完整参与带有默认值的插入,需要靠页面层处理。 - 时间:创建时间用
DATETIME,默认值设CURRENT_TIMESTAMP。更新时间可以用TIMESTAMP类型并配合ON UPDATE CURRENT_TIMESTAMP,这样每次记录被更新时数据库自动改时间,比你在Java、Python里手动new Date()靠谱得多。
3.4 主键、自增和其它索引的关系
主键是每个表的核心,选主键有两个方向。第一选择是自增ID:BIGINT NOT NULL AUTO_INCREMENT,好处是插入效率高,不回看业务内容。第二是业务唯一键,比如身份证号、订单号。但我不建议直接用身份证当主键,因为业务规则一变,主键一旦想改就极度痛苦,而且身份证号长度也不短,做主键会在二级索引里重复占用空间。
索引不要贪多。在Navicat的索引页签里,你可以随时添加普通索引、唯一索引、全文索引。但索引不是越多越好——每次插入和更新数据时,索引都要同步维护,索引太多会显著拖慢写入速度。常见的做法是:先把查询逻辑想清楚,再决定哪些字段需要索引。比如用户表经常用手机号登录,那就给手机号建唯一索引,因为手机号本身就该唯一;如果经常按订单号查订单,就给订单号建唯一索引。至少要有主键索引,其余索引按需添加。
3.5 一个能直接抄的员工表建表案例
在Navicat的查询编辑器里执行下面这段,或者直接在图形界面新建表都可以:
sql复制CREATE TABLE employee (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
emp_no VARCHAR(20) NOT NULL COMMENT '工号',
name VARCHAR(50) NOT NULL COMMENT '姓名',
gender TINYINT NOT NULL DEFAULT 0 COMMENT '性别 0未知 1男 2女',
phone VARCHAR(20) DEFAULT NULL COMMENT '手机号',
email VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
department_id BIGINT DEFAULT NULL COMMENT '部门ID',
hire_date DATE DEFAULT NULL COMMENT '入职日期',
status TINYINT NOT NULL DEFAULT 1 COMMENT '状态 1在职 0离职',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_emp_no (emp_no),
KEY idx_department_id (department_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='员工表';
这个表基本把日常开发里最常用的字段设计都覆盖了:主键、业务唯一键、普通索引、时间字段的默认值、字段注释。你在Navicat图形界面里照着建一遍,然后打开“SQL预览”就能看到一份类似的语句。这就是图形操作和学习SQL之间最好的桥梁。
4. 查看表结构和修改表结构:其实每一次修改都是ALTER
4.1 查看表结构:三个入口各有用途
表建好之后,怎么快速看它的结构?Navicat里一般有三个入口:
- 右键表名 → 设计表:最常用。能看到所有字段、类型、默认值、索引,还能在这里直接改。
- 右键表名 → 复制SQL创建脚本:这个最实用。你可以拿到一份Create Table语句,无论是给同事看、还是想在另一个环境还原表结构,这个功能都极其高效。热搜词里有人问“DataGrip如何同步数据库表结构”,其实在Navicat里就没这个烦恼,直接复制SQL,去另一个库里执行一遍就行。
- 在查询编辑器里执行
DESC employee;或SHOW CREATE TABLE employee;:用命令行方式看结构,适合写给SQL脚本的自动化场景。
数据能不能看?能。双击表名,Navicat就默认展示前1000条数据。你要是想看更多,点击右上角的“限制”,改成10000也行。但注意这只是让你看数据,不是让你直接改线上数据的理由,后面会专门聊删除时的安全习惯。
4.2 加字段、改字段、删字段:UI背后全是ALTER
Navicat里改表结构,主要是在“设计表”窗口里完成。操作完之后点“保存”,它才会真正执行生成的SQL。你在这个窗口里做的每一个改动,都会在保存之前显示成SQL预览。我建议你多看几眼预览,试试自己能不能看懂。
加一个字段,UI操作是:设计表 → 在最后一行输入字段名和类型 → 保存。
它背后生成的SQL就是:
sql复制ALTER TABLE employee ADD COLUMN address VARCHAR(200) DEFAULT NULL COMMENT '住址' AFTER email;
AFTER email表示把新字段放在email字段后面,这是给字段排位置的语法。很多人在图形界面里拖动字段顺序,其实底层就是靠AFTER来调整位置。
修改字段类型,UI操作是:直接把类型从VARCHAR(20)改成VARCHAR(50),保存。背后对应两个选择:如果只是长度变了,通常生成MODIFY COLUMN;如果字段名也改了,那就生成CHANGE COLUMN。
sql复制-- 只改类型
ALTER TABLE employee MODIFY COLUMN phone VARCHAR(50) COMMENT '联系电话';
-- 字段名和类型一起改
ALTER TABLE employee CHANGE COLUMN phone mobile VARCHAR(30) COMMENT '手机号';
删字段,UI操作是:右键该行 → 删除字段 → 保存。背后的SQL是:
sql复制ALTER TABLE employee DROP COLUMN address;
这些都是很基础的操作,但要注意的点在于:每执行一次ALTER,MySQL都要重建表(具体取决于版本和ALGORITHM参数)。小表无所谓,但如果是一个几千万行的大表,ALTER TABLE可能会锁住表一段时间,影响线上业务。
4.3 修改大表字段时要注意什么
这里说一个我在生产环境踩过的坑。某次为了把一个订单表的备注字段从VARCHAR(100)改成VARCHAR(500),我直接在Navicat里保存了设计表。结果这张表有近两千万行数据,ALTER执行了将近二十分钟,期间表上的写操作全被堵住,线上订单创建直接超时。
如果你的表已经大到百万行以上,请先记住下面几条经验,再决定改不改表结构:
- 不要在业务高峰期改表结构。宁可凌晨两三点起来操作,也不要下午两点直接在线上改。
- 给表加字段或者改字段类型之前,先确认数据库版本。MySQL 8支持INSTANT算法,部分操作可以秒级完成,但也不是所有操作都支持,还是要有时间预期。
- 提前检查是否被外键引用或者被其他任务持有MDL锁。在Navicat里建完外键后,父表结构改动可能触发锁等待,可以先执行
SHOW PROCESSLIST;看看当前有没有长时间运行的长事务。 - 如果表确实太大,优先考虑用
pt-online-schema-change这类工具处理,不要在Navicat里直接保存设计表。
4.4 修改表名和自增值的坑
改表名在Navicat里有两种方式。一是右键“重命名表”,它执行的是RENAME TABLE employee TO staff;。二是写SQL。注意:改表名会连带让外键关系里的引用表名变化,如果有其他表外键关联这个表,要一并检查。
还有一个小需求经常有人问:删完表数据之后,自增ID不从1开始了怎么办?热搜里“怎么清数据库表,id从1开始”就是问这个。这个问题的答案取决于你要不要保留表结构:
- 如果表已经不要了,直接
DROP TABLE employee;再重建。 - 如果表还在,只是清空数据并让ID重新从1开始,用
TRUNCATE TABLE employee;——它清空所有行并且重置自增计数。 - 如果只想删除部分数据,并且让后续自增ID重新计数,那其实做不到用一条SQL安全做到。因为MySQL的自增计数器只增不减。你只能手动改:
sql复制ALTER TABLE employee AUTO_INCREMENT = 1;
但重点提醒一下:如果表里还有数据,或者清空之后新的最大值比1大,这个设置不会生效,MySQL会取max(id)+1作为新的起点。所以不要指望在还剩数据的情况下把ID重置成1。
5. 删除表操作:DROP、DELETE、TRUNCATE之间差在哪
5.1 三种删除方式的完整对比
删除是危险操作,但也最容易被新手搞混。Navicat里右键一个表,你能看到“删除表”“清空表”之类的选项,它们对应的SQL完全不同。我直接给一个对照表:
| 操作 | SQL | 删除内容 | 是否删表结构 | 自增ID是否重置 | 可回滚吗 | 速度 |
|---|---|---|---|---|---|---|
| 删除表 | DROP TABLE | 整张表没了 | 是 | 无意义 | 不可 | 很快 |
| 清空表 | TRUNCATE TABLE | 所有行数据 | 否 | 是 | 不可 | 很快 |
| 删除表数据 | DELETE FROM | 指定行数据 | 否 | 否 | 事务内可回滚 | 较慢 |
用生活化的例子说:DROP相当于把整本笔记本扔进碎纸机;TRUNCATE相当于撕掉笔记本里所有写过的页,但保留空本子;DELETE相当于用橡皮擦掉指定几页的内容,而且橡皮还没扔的时候你想反悔还能把涂掉的拿回来。
日常开发中,DELETE带WHERE是最常见的逻辑删除操作,比如删除离职员工的记录:
sql复制DELETE FROM employee WHERE emp_no = 'E10001';
如果忘了WHERE,那就是全表数据删除,这是数据库事故级别的问题。所以Navicat查询编辑器里执行DELETE之前,我的习惯是先执行同条件的SELECT,确认要删的行数是自己预期的,再回来执行DELETE。
5.2 在Navicat里误删了怎么办
Navicat没有回收站,这一点大家特别容易误会。你在图形界面里右键“删除表”,它执行的DROP TABLE是物理删除,不会像Windows回收站那样能双击还原。所以误删表的恢复思路,必须先靠MySQL层做一些准备。
常见的恢复手段有三种:
- 有备份就直接恢复。最稳的办法,不管是mysqldump定时备份还是云数据库快照,只要备份时间点能接受数据丢失量,直接恢复就行。
- 开启binlog日志,用mysqlbinlog找到误删之前的时间点做回放。这是MySQL的二进制日志,记录了所有数据变更。如果你有binlog,并且删除行为发生在日志保留期内,是可以把数据捞回来的。但这一步对经验要求比较高,平时没看过的可以先了解一下概念,真遇到的时候再找DBA或DBA朋友协助,别自己瞎试。
- 第三方数据恢复工具。效果取决于文件系统、存储引擎和删除后是否有写入覆盖,属于碰运气,不要指望。
所以最靠谱的防误删方案,是在删除之前就做好两道保险。第一道是备份,第二道是权限控制。生产库里别给所有人DROP权限,只给特定账号和特定数据库。Navicat里可以建立不同的连接配置,生产库的账号密码保存在专门的负责人电脑上,其他人只有只读权限。这从源头阻止了误删。
5.3 防止误删的四个习惯
我见过太多人在测试环境练手、在生产环境手滑。养成这几个习惯之后,基本能避免绝大多数删除事故:
- 执行DELETE之前先跑SELECT。这是老生常谈,但永远有效。
- 确认当前连接的数据库。Navicat左侧可以同时挂着生产库和测试库,两者颜色上其实没区别,所以建议把生产库的连接名写得特别醒目,比如“【生产】千万别乱动”,并且操作之前再瞄一眼当前连接名。
- 删除表结构或清空表之前,先用“复制SQL创建脚本”临时存一份,万一删完了想快速重建,还能粘贴回去。
- 关闭Navicat的“自动提交”之前先想清楚。默认情况下DDL语句(如DROP、TRUNCATE)会隐式提交,无法回滚,这点不像DELETE,用在事务里还能ROLLBACK。不要以为“没提交就不算数”,DROP和TRUNCATE是没有回头路的。
5.4 顺带说说表被锁的情况
热搜里有人问“怎么查看数据库表是否被锁”,这一点和删除操作也有关系。有时你执行DELETE或者TRUNCATE,结果一直卡住不结束,大概率是表上的锁没释放。
Navicat里可以直接通过“工具 → 服务器监控”或“信息页面”看到当前所有连接和正在执行的SQL。命令行标准写法是:
sql复制SHOW PROCESSLIST;
重点看State字段,如果大量线程卡在Waiting for table metadata lock、Waiting for table level lock这类状态,就说明有别的会话占着表锁。常见场景是:有一个查询或者事务一直开着没提交,占住了MDL锁;或者有人开着Navicat的事务窗口,执行了SELECT,一直没提交也没回滚。
这时候处理办法:把那个占用锁的会话kill掉,或者等它自己结束。如果被锁的是小表,用KILL 线程ID;可以快速解围。但如果你发现事务非常大,kill会导致事务回滚,需要评估回滚时间。最稳妥的排查方式,是让执行SELECT的查询尽快结束,避免长事务,尤其不要在Navicat里开了事务窗口后放着不管去做别的事。
6. 模拟练习:一张学生选课库带你走完所有表操作
6.1 训练目标:从0建出选课库
空谈太多没用,最后放一套模拟练习。这套练习题的设计初衷,是让刚接触MySQL和Navicat的人,在30分钟内把前面提到的所有操作自己走一遍。
业务场景:做一个学生选课系统,需要三张表——学生表、课程表、选课关系表。选课关系表通过外键关联学生和课程。
可以直接跟着下面的步骤走,建议先在Navicat图形界面操作一遍,再在查询编辑器里用SQL操作一遍,两种方式对照,理解会深得多。
6.2 第1关:建库和建表
在Navicat中新建数据库,库名school,字符集utf8mb4,排序规则utf8mb4_0900_ai_ci。
然后新建三张表。图形界面建完看SQL预览,语义如下:
sql复制CREATE TABLE student (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '学生ID',
student_no VARCHAR(20) NOT NULL COMMENT '学号',
student_name VARCHAR(50) NOT NULL COMMENT '姓名',
gender TINYINT NOT NULL DEFAULT 0 COMMENT '性别',
age INT DEFAULT NULL COMMENT '年龄',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_student_no (student_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生表';
CREATE TABLE course (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '课程ID',
course_code VARCHAR(20) NOT NULL COMMENT '课程编码',
course_name VARCHAR(100) NOT NULL COMMENT '课程名称',
credit DECIMAL(3,1) NOT NULL DEFAULT 2.0 COMMENT '学分',
PRIMARY KEY (id),
UNIQUE KEY uk_course_code (course_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='课程表';
CREATE TABLE student_course (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '选课记录ID',
student_id BIGINT UNSIGNED NOT NULL COMMENT '学生ID',
course_id BIGINT UNSIGNED NOT NULL COMMENT '课程ID',
score DECIMAL(5,2) DEFAULT NULL COMMENT '成绩',
select_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '选课时间',
PRIMARY KEY (id),
UNIQUE KEY uk_student_course (student_id, course_id),
CONSTRAINT fk_sc_student FOREIGN KEY (student_id) REFERENCES student (id),
CONSTRAINT fk_sc_course FOREIGN KEY (course_id) REFERENCES course (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='选课表';
这里出现了外键约束,可以看到一个完整的“选课表”是通过student_id和course_id去引用另外两张表的主键的。这样设计,保证了不会插入一个不存在的学生的选课记录,也从数据库层面维护了数据完整性。
练完之后,试着插入几条测试数据:
sql复制INSERT INTO student (student_no, student_name, gender, age) VALUES
('S001', '张三', 1, 20),
('S002', '李四', 2, 21),
('S003', '王五', 1, 19);
INSERT INTO course (course_code, course_name, credit) VALUES
('C001', '数据库原理', 3.0),
('C002', '计算机网络', 2.5),
('C003', '数据结构', 3.5);
INSERT INTO student_course (student_id, course_id, score) VALUES
(1, 1, 88.5),
(1, 2, 91.0),
(2, 1, 75.0),
(3, 3, 82.0);
这个过程中你会发现想通过外键往选课表里插入不存在的学生记录,MySQL会直接报错。这就是数据库在替你守住底线。
6.3 第2关:修改表结构
学生表缺一个“班级”字段,加一下:
sql复制ALTER TABLE student ADD COLUMN class_name VARCHAR(50) DEFAULT NULL COMMENT '班级' AFTER age;
学生表里年龄字段以后可能不用了,测试一下删除它:
sql复制ALTER TABLE student DROP COLUMN age;
李四的姓名长度可能不够,把student_name从VARCHAR(50)改成VARCHAR(100):
sql复制ALTER TABLE student MODIFY COLUMN student_name VARCHAR(100) NOT NULL COMMENT '姓名';
另外,给选课表加一个“学期”字段,并加上普通索引,方便按学期查询:
sql复制ALTER TABLE student_course ADD COLUMN semester VARCHAR(20) DEFAULT NULL COMMENT '学期' AFTER course_id;
ALTER TABLE student_course ADD INDEX idx_semester (semester);
做完之后,右键表 → 设计表,你会看到所有刚刚的改动都反映在了设计界面上。反过来讲,如果直接在图形界面操作,你也能在保存之前预览到这些SQL语句。
6.4 第3关:查结构和验证数据
分别用三种方式查看student表结构:
DESC student;SHOW CREATE TABLE student;- Navicat图形界面设计表
重点看SHOW CREATE TABLE的输出,它会把表的完整定义、字符集、索引、外键都打印出来。以后跨环境同步表结构,就是靠这份语句。
然后试试表之间关联查询,看外键到底带来了什么效果:
sql复制SELECT s.student_no, s.student_name, c.course_name, sc.score
FROM student_course sc
JOIN student s ON sc.student_id = s.id
JOIN course c ON sc.course_id = c.id
ORDER BY sc.score DESC;
这里就是热搜词里“mysql排序”的典型场景,用ORDER BY在最终结果集上做排序,而不是在WHERE子句里排序。
6.5 第4关:删除和重建
先试着只删除选课表中张三的数据库原理成绩:
sql复制DELETE FROM student_course WHERE student_id = 1 AND course_id = 1;
然后试试只删除某个学生的全部选课记录:
sql复制DELETE FROM student_course WHERE student_id = 2;
注意看,如果直接删除学生表里的张三:
sql复制DELETE FROM student WHERE id = 1;
会报错。因为student_course里还有张三的选课记录,外键约束阻止了这次删除。你必须先把选课表里对应的记录删掉,才能删除学生主记录。这就是外键在保护数据完整性。
如果想把选课表数据清空,并且让ID重新从1开始:
sql复制TRUNCATE TABLE student_course;
如果你真的想删除整张表再重建:
sql复制DROP TABLE student_course;
之后重新执行一遍建表语句,表就回来了。这个过程虽然会让人有点心疼,但它完整模拟了从创建到删除的整个生命周期。
6.6 为什么要用两种方式各做一遍
最后这一步练习,建议你硬着头皮在Navicat图形界面操作一遍后,再用SQL各操作一遍。
图形界面的优势是直观,你永远能看见自己正在改的是什么表、哪些字段。SQL的优势是精确,它不受图形界面版本影响,任何MySQL环境都能执行。两者不是二选一的关系。面试考你的是SQL,工作里提高效率的是Navicat,你两边都熟练了,才算真正掌握了MySQL表操作。
我做了这些年数据库相关的工作,最深的体会是:表结构操作是数据库最基本的功夫,越是基础的东西,越值得反复练。很多人抱怨Navicat用多了不会写SQL,其实问题不在工具,而在使用工具的人没有养成看SQL预览的习惯。只要你每次点击“保存”之前,都认真看一眼那几行语句,Navicat不仅不会让你忘记SQL,反而会成为你学SQL最快的捷径。
