文章目录
- [MySQL 基础:从数据库概念到表结构管理](#MySQL 基础:从数据库概念到表结构管理)
-
- 一、数据库基本了解
-
- [1.1 什么是数据库?](#1.1 什么是数据库?)
- [1.2 数据库分类:关系型 vs 非关系型](#1.2 数据库分类:关系型 vs 非关系型)
- [1.3 为什么选择学习 MySQL ?](#1.3 为什么选择学习 MySQL ?)
- [1.4 连接 MySQL](#1.4 连接 MySQL)
- [二、SQL 概述与分类](#二、SQL 概述与分类)
- 三、DDL:数据库操作
- 四、DDL:数据表操作
-
- [4.1 创建表](#4.1 创建表)
-
- [4.1.1 数据类型](#4.1.1 数据类型)
- [4.1.2 约束](#4.1.2 约束)
- [4.2 查看表](#4.2 查看表)
- [4.3 修改表](#4.3 修改表)
- [4.4 删除表](#4.4 删除表)
- [4.5 DDL 增删改查总览](#4.5 DDL 增删改查总览)
- 五、实践习题
- 附:命令速查
MySQL 基础:从数据库概念到表结构管理
本文是 MySQL 系列的第一篇。从"为什么需要数据库"讲起,理清关系型与非关系型的本质区别,然后进入 MySQL 的实际操作:连接、SQL 分类、以及 DDL 对数据库和表结构的完整管理。
一、数据库基本了解
1.1 什么是数据库?
在没有数据库的时代,数据存储在文件里。但文件有几个解决不了的问题:多人同时读写会冲突、数据量大了查询变慢、没有权限控制、数据之间的关联(比如"这个订单属于哪个用户")难以表达和维护。
数据库就是解决这些问题:让数据被安全、高效、有组织地存储和访问。
1.2 数据库分类:关系型 vs 非关系型
数据库依照数据的存储形式分为两类:关系型数据库(SQL)和 非关系型数据库(NoSQL)。
| 对比维度 | 关系型数据库(SQL) | 非关系型数据库(NoSQL) |
|---|---|---|
| 存储形式 | 行列表格,固定列结构 | 键值对 / 文档 / 列式 / 图,结构灵活 |
| 表结构 | 先定义 schema,再写入数据 | 不强制预定义,字段可随时变化 |
| 数据关联 | 通过外键建立表间关系 | 无原生关联,或通过其他方式实现 |
| 事务支持 | 完整 ACID | 各产品程度不同,通常较弱 |
| 代表产品 | MySQL、Oracle、PostgreSQL、SQL Server | Redis、MongoDB、HBase、Neo4j |
| 适用场景 | 结构规整的业务数据(用户、订单、财务) | 高并发缓存、海量日志、社交图谱 |
NoSQL 四种存储模型:
| 模型 | 数据形状 | 典型产品 | 适合场景 |
|---|---|---|---|
| 键值存储 | 字典,key → value | Redis | 缓存、会话管理 |
| 文档存储 | JSON/BSON 文档 | MongoDB | 内容管理、用户画像 |
| 列式存储 | 按列组织 | HBase | 大数据分析 |
| 图存储 | 节点 + 边 | Neo4j | 社交关系、推荐系统 |
选择逻辑:业务数据是规整的表格(用户、订单、商品),用关系型。面对海量日志、实时缓存、复杂关系网络,用对应的 NoSQL。
1.3 为什么选择学习 MySQL ?
MySQL 在关系型数据库中是入门首选:开源免费、市场占有率高、标准 SQL 语法跨平台通用、提供 Python/Java/C++ 等多种语言接口、C/S 架构。
MySQL 最早由瑞典 MySQL AB 开发,经历 SUN 公司收购,最终归属 Oracle。
理解C/S 架构是理解 MySQL 工作方式的基础。MySQL 分为服务端和客户端两部分:
| 角色 | 程序 | 职责 |
|---|---|---|
| 服务端(Server) | mysqld |
后台守护进程,负责数据的存储、读写和管理,监听 3306 端口 |
| 客户端(Client) | 任何与服务器通信的工具或代码。例如命令行工具 mysql / 图形工具 MySQL Workbench、Navicat / Java/Python 等写的程序代码驱动 |
向服务端发送 SQL 语句,接收返回结果 |
客户端(你操作的界面)── SQL 语句 ──→ 服务端(mysqld,存数据的进程)
←── 查询结果 ──

客户端和服务端可以在同一台机器上(本地连接用 127.0.0.1),也可以异地部署。理解了 C/S 分离,就可以理解远程连接需要确定IP地址和端口号。
1.4 连接 MySQL
bash
# 完整格式
mysql -h 服务端IP -P 端口 -u 用户名 -p
# 四种常用写法
mysql -uroot -p123456 # 密码明文,不推荐(留在 shell 历史里)
mysql -u root -p # 最常用:交互式输入密码,密码不可见
mysql --host=127.0.0.1 --port=3306 --user=root --password # 长选项格式
mysql -h 192.168.1.100 -P 3306 -u root -p # 连接远程服务器
| 参数 | 含义 | 默认值 |
|---|---|---|
-h |
host,服务端主机地址 | 127.0.0.1 |
-P |
Port,端口(大写) | 3306 |
-u |
user,用户名 | 必填 |
-p |
password,密码 | 无 |
退出:quit 或 exit。
远程连接需要服务端开放网络权限(
bind-address)和防火墙端口。生产环境通常不直接开放 3306,而是通过 SSH 隧道或 VPN。
二、SQL 概述与分类
SQL(Structured Query Language)是所有关系型数据库通用的操作语言。换一个数据库产品,核心语法不变,会有一些特殊的特有的函数或语法。
根据操作对象的不同,SQL 分为四类:
| 分类 | 全称 | 操作对象 | 核心动词 | 一句话 |
|---|---|---|---|---|
| DDL | Data Definition Language | 数据库、表、列(结构) | CREATE ALTER DROP |
管容器的形状 |
| DML | Data Manipulation Language | 表中的记录(数据) | INSERT UPDATE DELETE |
管容器里的内容 |
| DQL | Data Query Language | 表中的记录(查询) | SELECT |
从容器里取东西看 |
| DCL | Data Control Language | 权限与安全 | GRANT REVOKE |
管谁能碰容器 |
DDL、DML、DQL 都遵循"增删改查"的操作模式,只是各自操作的对象层级不同。
下面从 DDL 开始,即本期我们先学习数据库和表结构的增删改查。
SQL 书写规范:
- 语句以分号结尾
- 关键字建议大写,表名列名小写
- 注释用
--(双短横加空格)或/* */。 - 可使用空格和缩进来增强语句的可读性
三、DDL:数据库操作
DDL 的第一层操作对象是数据库本身,我们依照增删改查的逻辑讲解总结。
sql
-- ========== 增 ==========
CREATE DATABASE mydb; -- 基本创建
CREATE DATABASE IF NOT EXISTS mydb; -- 不存在才创建(推荐)
CREATE DATABASE mydb CHARSET='utf8mb4'; -- 指定字符集
MySQL 的
utf8是不完整的(最多 3 字节,存不了 emoji)。新建库可以统一用utf8mb4。
sql
-- ========== 查 ==========
SHOW DATABASES; -- 列出所有数据库(注意有 s)
SELECT DATABASE(); -- 查看当前在哪个数据库
sql
-- ========== 选 ==========
USE mydb; -- 后续操作默认在此库下执行
sql
-- ========== 改 ==========
ALTER DATABASE mydb CHARSET='utf8mb4'; -- 只能改字符集等属性,不能改名
数据库名称无法直接重命名。需要改名只能导出 → 建新库 → 导入。
sql
-- ========== 删 ==========
DROP DATABASE mydb; -- ⚠️ 不可逆,库中所有表和数据一并删除
四、DDL:数据表操作
先 USE 选中数据库,再操作表。同样按照增删改查的逻辑讲解总结。
4.1 创建表
sql
CREATE TABLE 表名 (
字段名1 数据类型 [列级约束],
字段名2 数据类型 [列级约束],
...
[表级约束]
);
sql
-- 示例:用户表(每个字段后面的关键字含义见下方"约束"章节)
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(100) NOT NULL,
email VARCHAR(100),
age TINYINT UNSIGNED,
balance DECIMAL(10, 2) DEFAULT 0.00,
created DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE (username)
);
4.1.1 数据类型
| 分类 | 类型 | 说明 | 使用场景 |
|---|---|---|---|
| 整数 | TINYINT |
1 字节,有符号 -128~127,无符号 0~255 | 年龄、状态码 |
| 整数 | INT |
4 字节,无符号 0~42 亿 | 主键 ID、大部分数值字段 |
| 整数 | BIGINT |
8 字节 | 日志流水号、超大主键 |
| 小数 | FLOAT |
单精度浮点,约 7 位有效数字,有精度损失 | 对精度要求不高的数值 |
| 小数 | DOUBLE |
双精度浮点,约 15 位有效数字,有精度损失 | 科学计算、统计指标 |
| 小数 | DECIMAL(M,D) |
精确小数,M 总位数 D 小数位,无精度损失 | 金额、财务数据 |
| 字符串 | CHAR(N) |
定长,始终占 N 字符空间,不足补空格 | 手机号、身份证号、MD5 |
| 字符串 | VARCHAR(N) |
变长,按实际长度 +1 字节前缀存储 | 用户名、邮箱、地址 |
| 字符串 | TEXT |
长文本,最大 65535 字节 | 文章正文、简介 |
| 日期 | DATE |
YYYY-MM-DD |
生日、日期字段 |
| 日期 | DATETIME |
YYYY-MM-DD HH:MM:SS |
创建时间、更新时间 |
| 对比 | CHAR | VARCHAR |
|---|---|---|
| 存储方式 | 定长,存 'ab' 到 CHAR(3) 实际占 3 字符,右侧补空格 | 变长,存 'ab' 到 VARCHAR(3) 只占 2 字符 + 1 字节长度前缀 |
| 空间效率 | 固定长度数据更省(无前缀开销) | 可变长度数据更省 |
| 查询效率 | 略快(每行等长,定位快) | 略慢(需先读长度前缀) |
| 适用 | 长度固定的数据(手机号、身份证号、MD5) | 长度差异大的数据(用户名、邮箱、地址) |
| 对比 | DATETIME | TIMESTAMP |
|---|---|---|
| 存储内容 | 字面日期时间,存什么就是什么 | Unix 时间戳(1970-01-01 起的秒数) |
| 时间范围 | 1000-01-01 ~ 9999-12-31 | 1970-01-01 ~ 2038-01-19 |
| 受时区影响 | 否 | 是(存入时转 UTC,取出时转回当前时区) |
| 占用空间 | 8 字节(5.6.4+ 为 5 字节) | 4 字节 |
| 推荐 | 多数场景 | 需要自动时区转换时 |
N 表示字符数 ,不是字节数。
VARCHAR(100)能存 100 个中文。
4.1.2 约束
| 约束 | 关键字 | 作用 | 场景 |
|---|---|---|---|
| 主键 | PRIMARY KEY |
唯一且非空,一行一条的身份证 | 每张表必有一个,建议 id INT UNSIGNED AUTO_INCREMENT |
| 非空 | NOT NULL |
不允许存 NULL | 核心业务字段(用户名、密码、手机号) |
| 唯一 | UNIQUE |
值不可重复,但允许 NULL | 用户名、邮箱、身份证号 |
| 默认值 | DEFAULT |
不填时自动使用默认值 | 库存默认 0、余额默认 0.00、时间默认当前 |
| 外键 | FOREIGN KEY |
值必须引用另一张表的主键 | 订单表中的 user_id 引用用户表的 id |
| 对比 | PRIMARY KEY | UNIQUE |
|---|---|---|
| 可否为 NULL | ❌ 不可 | ✅ 可(且允许多个 NULL) |
| 一张表能有几个 | 1 个 | 多个 |
| 典型场景 | 行标识(id) | 业务唯一字段(邮箱、手机号) |
每种约束的写法:
sql
-- 1. 主键(PRIMARY KEY)
-- 列级写法(单列主键,最常用):
CREATE TABLE t1 (
id INT UNSIGNED PRIMARY KEY,
name VARCHAR(20)
);
-- 表级写法(复合主键时使用):
CREATE TABLE t2 (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id) -- 两列组合作为主键
);
-- 2. 非空(NOT NULL)
CREATE TABLE t3 (
id INT UNSIGNED PRIMARY KEY,
name VARCHAR(20) NOT NULL, -- name 不允许 NULL
email VARCHAR(50)
);
-- 3. 唯一(UNIQUE)
CREATE TABLE t4 (
id INT UNSIGNED PRIMARY KEY,
username VARCHAR(50) UNIQUE, -- 列级写法
email VARCHAR(50),
UNIQUE (email) -- 表级写法
);
-- 4. 默认值(DEFAULT)
CREATE TABLE t5 (
id INT UNSIGNED PRIMARY KEY,
stock INT UNSIGNED DEFAULT 0, -- 不填默认 0
created DATETIME DEFAULT CURRENT_TIMESTAMP -- 不填默认当前时间
);
-- 5. 外键(FOREIGN KEY)
-- 只表级写法:
CREATE TABLE orders (
id INT UNSIGNED PRIMARY KEY,
user_id INT UNSIGNED,
product VARCHAR(100),
FOREIGN KEY (user_id) REFERENCES users(id) -- user_id 必须引用 users 表的 id 列
);
| 写法 | 位置 | 适用 |
|---|---|---|
| 列级约束 | 写在字段定义同一行末尾 | NOT NULL、DEFAULT、单列的 UNIQUE、单列的 PRIMARY KEY |
| 表级约束 | 写在所有字段定义之后,独立一行 | 复合主键、外键(只有表级)、多列 UNIQUE |
AUTO_INCREMENT 配合主键:插入时不指定主键值或设为 NULL/0,数据库自动递增。DELETE 删记录后自增序号不重置,TRUNCATE 清空表后重置。
4.2 查看表
sql
SHOW TABLES; -- 当前库有哪些表
DESC 表名; -- 查看表结构(字段、类型、约束)
4.3 修改表
sql
-- 改表名
RENAME TABLE 旧名 TO 新名;
-- 字段操作
ALTER TABLE 表名 ADD 列名 类型 [约束]; -- 增
ALTER TABLE 表名 MODIFY 列名 新类型 [约束]; -- 改(不改名)
ALTER TABLE 表名 CHANGE 旧列名 新列名 新类型 [约束]; -- 改(改名)
ALTER TABLE 表名 DROP 列名; -- 删
| 对比 | MODIFY | CHANGE |
|---|---|---|
| 能不能改列名 | ❌ 不能 | ✅ 能 |
| 语法复杂度 | 只写一次列名 | 新旧列名都写 |
| 使用场景 | 只调整类型或约束 | 需要同时改列名 |
4.4 删除表
sql
DROP TABLE 表名; -- ⚠️ 不可逆,结构 + 数据全部删除
4.5 DDL 增删改查总览
| 层级 | 增 | 查 | 改 | 删 |
|---|---|---|---|---|
| 数据库 | CREATE DATABASE |
SHOW DATABASES |
ALTER DATABASE(仅字符集) |
DROP DATABASE |
| 表 | CREATE TABLE |
SHOW TABLES / DESC |
RENAME TABLE / ALTER TABLE |
DROP TABLE |
| 字段 | ALTER ... ADD |
DESC |
ALTER ... MODIFY / CHANGE |
ALTER ... DROP |
DDL 始终操作的是数据库、表、列这三个层级的结构定义。它所关注的是我们数据库和数据表的结构,与具体的记录增删改查无关。
五、实践习题
题 1 :创建一个名为 company 的数据库,字符集使用 utf8mb4。如果该库已存在则不重复创建。
题 2 :进入 company 数据库,然后创建一张 employees 表,包含以下字段:
| 字段 | 类型 | 约束 |
|---|---|---|
| id | INT UNSIGNED | 主键,自增 |
| name | VARCHAR(30) | 非空 |
| phone | CHAR(11) | 非空,唯一 |
| department | VARCHAR(20) | 无 |
| salary | DECIMAL(10,2) | 默认 0.00 |
| hire_date | DATE | 无 |
题 3 :查看当前库中所有表,然后查看 employees 的表结构。
题 4 :在 employees 表中添加一个 email 字段,类型 VARCHAR(100)。
题 5 :将 email 字段的类型改为 VARCHAR(150),并设置为非空。
题 6 :将 department 字段重命名为 dept,类型不变。
题 7 :删除 email 字段。
参考答案与讲解
题 1 答案:
sql
CREATE DATABASE IF NOT EXISTS company CHARSET='utf8mb4';

IF NOT EXISTS 避免重复建库报错。utf8mb4 是完整的 UTF-8 实现,能存储 emoji 和所有 Unicode 字符。MySQL 的 utf8 是别名,指向不完整的 3 字节实现,新项目统一用 utf8mb4。注意IF NOT EXISTS的位置。
题 2 答案:
sql
USE company;
CREATE TABLE employees (
id INT UNSIGNED AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
phone CHAR(11) NOT NULL UNIQUE,
department VARCHAR(20),
salary DECIMAL(10, 2) DEFAULT 0.00,
hire_date DATE,
PRIMARY KEY (id)
);

选型解释:
id用INT UNSIGNED:4 字节,0~42 亿,够绝大多数业务主键。UNSIGNED禁止负数,范围翻倍phone用CHAR(11):手机号固定 11 位,定长 CHAR 比 VARCHAR 效率更高,且没有长度前缀的额外开销salary用DECIMAL(10, 2):金额必须精确,不能使用FLOAT或DOUBLE(有精度损失)。10 位总长度含 2 位小数,即最大99999999.99UNIQUE加在phone上:手机号在业务上不应重复
题 3 答案:
sql
SHOW TABLES;
DESC employees;


SHOW TABLES 列出当前库中所有表名。DESC 显示每个字段的名称、类型、是否允许 NULL、键类型、默认值等信息。建完表后执行 DESC 检查结构是否符合预期,是日常开发习惯。
题 4 答案:
sql
ALTER TABLE employees ADD email VARCHAR(100);

新增字段默认追加到表的最后一列。此时 email 没有 NOT NULL 约束,已存在的行会自动填 NULL。
题 5 答案:
sql
ALTER TABLE employees MODIFY email VARCHAR(150) NOT NULL;

MODIFY 只改类型和约束,不改列名。这里同时扩大了长度(100→150)并加了非空约束。如果表中已有行的 email 为 NULL,这条语句会报错,需先 UPDATE 填充数据再改约束。
题 6 答案:
sql
ALTER TABLE employees CHANGE department dept VARCHAR(20);

CHANGE 同时改列名和类型。必须写新旧两个列名,类型也要写(即使不改类型也要原样写上) 。如果只改类型不改名,用 MODIFY 更简洁。
题 7 答案:
sql
ALTER TABLE employees DROP email;

字段和数据一并删除,不可恢复。生产环境执行前务必确认。
附:命令速查
| 操作 | 语句 |
|---|---|
| 连接本机 | mysql -u root -p |
| 连接远程 | mysql -h IP -P 3306 -u root -p |
| 创建数据库 | CREATE DATABASE IF NOT EXISTS 库名 CHARSET='utf8mb4'; |
| 查看数据库 | SHOW DATABASES; |
| 选择数据库 | USE 库名; |
| 删除数据库 | DROP DATABASE 库名; |
| 创建表 | CREATE TABLE 表名 (字段 类型 [约束], ...); |
| 查看表列表 | SHOW TABLES; |
| 查看表结构 | DESC 表名; |
| 改表名 | RENAME TABLE 旧名 TO 新名; |
| 添加字段 | ALTER TABLE 表名 ADD 列名 类型 [约束]; |
| 修改字段 | ALTER TABLE 表名 MODIFY 列名 新类型 [约束]; |
| 删除字段 | ALTER TABLE 表名 DROP 列名; |
| 删除表 | DROP TABLE 表名; |
以上为个人学习总结,旨在梳理个人理解。如有疏漏或不当之处,欢迎指正与交流。如果文章对你有帮助,别忘了点个赞、留个言,让更多的小伙伴看到~ 我们下篇再见!