前言
前面我们已经写完了 Spring Boot + MyBatis 知识点系列,里面经常会出现 Mapper、SQL、表字段、主键 id、关联查询这些内容。
但是如果数据库基础不牢,写项目的时候就很容易出现一些问题。
比如:
- 实体类字段和数据库字段对不上
- 不知道为什么每张表都要有 id
- 不知道主键和普通字段有什么区别
- 不知道两张表为什么要通过某个字段关联
- 写多表查询时,不理解表和表之间的关系
所以从这一篇开始,我们进入第二个系列:数据库基础知识系列。
这一篇先不急着写复杂 SQL,而是先把数据库中最基础的几个概念讲清楚:数据库、表、字段、记录、主键、外键。
这些内容看起来简单,但是后面学习 MySQL、MyBatis、多表查询、索引、事务时都会用到。
一、数据库是什么?
数据库可以理解为一个专门用来存储数据的仓库。
比如我们做一个员工管理系统,系统中会有很多数据:
- 员工信息
- 部门信息
- 班级信息
- 学员信息
- 登录用户信息
- 操作日志信息
这些数据不能只放在 Java 对象里,因为程序一关闭,内存中的数据就没了。
所以我们需要把数据保存到数据库中。
常见数据库有:
| 数据库 | 说明 |
|---|---|
| MySQL | Java 后端学习和企业开发中非常常用 |
| Oracle | 大型企业系统中常见 |
| SQL Server | 微软体系中常见 |
| PostgreSQL | 功能强大的开源数据库 |
| Redis | 常用于缓存,不是传统关系型数据库 |
我们这一系列主要学习的是 MySQL。
二、数据库和表的关系
可以把数据库理解成一个文件夹,把表理解成文件夹中的 Excel 表格。
比如我们创建一个项目数据库:
sql
create database tlias;
这个 tlias 就是一个数据库。
在这个数据库中,可以有很多张表:
text
tlias 数据库
├── emp 员工表
├── dept 部门表
├── clazz 班级表
├── student 学员表
└── operate_log 操作日志表
每张表专门保存一类数据。
比如:
emp表保存员工信息dept表保存部门信息student表保存学员信息operate_log表保存操作日志
也就是说:
数据库负责管理多张表,表负责存储某一类具体数据。
三、表是什么?
表是数据库中真正保存数据的结构。
比如员工表 emp 可以设计成这样:
| id | username | name | gender | phone |
|---|---|---|---|---|
| 1 | zhangsan | 张三 | 1 | 13800000000 |
| 2 | lisi | 李四 | 1 | 13900000000 |
| 3 | wangwu | 王五 | 2 | 13700000000 |
这张表中,每一列表示一个字段,每一行表示一条记录。
可以简单理解为:
text
一张表 = 一类数据
一列 = 一个字段
一行 = 一条记录
四、字段是什么?
字段就是表中的一列,用来描述数据的某个属性。
比如员工表中有这些字段:
text
id
username
name
gender
phone
它们分别表示:
| 字段名 | 含义 |
|---|---|
| id | 员工编号 |
| username | 用户名 |
| name | 姓名 |
| gender | 性别 |
| phone | 手机号 |
在 Java 中,我们通常会写一个实体类和数据库表对应。
比如数据库表是:
sql
create table emp (
id int primary key auto_increment,
username varchar(20),
name varchar(10),
gender tinyint,
phone varchar(11)
);
Java 实体类可以这样写:
java
public class Emp {
private Integer id;
private String username;
private String name;
private Integer gender;
private String phone;
// getter、setter 省略
}
可以看到,数据库字段和 Java 属性基本是一一对应的。
五、记录是什么?
记录就是表中的一行数据。
比如员工表中这一行:
| id | username | name | gender | phone |
|---|---|---|---|---|
| 1 | zhangsan | 张三 | 1 | 13800000000 |
这就是一条员工记录。
对应到 Java 中,可以封装成一个 Emp 对象:
java
Emp emp = new Emp();
emp.setId(1);
emp.setUsername("zhangsan");
emp.setName("张三");
emp.setGender(1);
emp.setPhone("13800000000");
所以我们在 MyBatis 中查询数据库时,经常会看到:
java
@Select("select id, username, name, gender, phone from emp where id = #{id}")
Emp getById(Integer id);
这句 SQL 查询出来的是数据库中的一条记录,然后 MyBatis 会把这条记录封装成一个 Emp 对象。
六、主键是什么?
主键是表中用来唯一标识一条记录的字段。
最常见的主键就是 id。
比如员工表中:
| id | username | name |
|---|---|---|
| 1 | zhangsan | 张三 |
| 2 | lisi | 李四 |
| 3 | wangwu | 王五 |
这里的 id 就是主键。
每个员工都有自己的 id,不能重复。
创建表时可以这样写:
sql
create table emp (
id int unsigned primary key auto_increment comment '员工ID',
username varchar(20) comment '用户名',
name varchar(10) comment '姓名'
);
这里:
sql
primary key
表示主键。
sql
auto_increment
表示自动递增。
也就是说,我们新增员工时不用手动指定 id,数据库会自动生成。
比如:
sql
insert into emp(username, name) values('zhangsan', '张三');
insert into emp(username, name) values('lisi', '李四');
数据库可能会自动生成:
| id | username | name |
|---|---|---|
| 1 | zhangsan | 张三 |
| 2 | lisi | 李四 |
七、为什么每张表都建议有主键?
主键非常重要,原因主要有三个。
1. 唯一标识数据
如果没有主键,数据库很难准确区分两条看起来相似的数据。
比如:
| name | gender | phone |
|---|---|---|
| 张三 | 1 | 13800000000 |
| 张三 | 1 | 13800000000 |
这两条数据完全一样时,如果没有 id,就很难区分到底是哪一条。
有了主键后:
| id | name | gender | phone |
|---|---|---|---|
| 1 | 张三 | 1 | 13800000000 |
| 2 | 张三 | 1 | 13800000000 |
即使其他字段一样,也可以通过 id 区分。
2. 方便查询、修改和删除
项目中经常会根据 id 操作数据。
比如根据 id 查询员工:
sql
select * from emp where id = 1;
根据 id 修改员工:
sql
update emp set name = '张三丰' where id = 1;
根据 id 删除员工:
sql
delete from emp where id = 1;
这也是为什么我们在 Spring Boot 项目中经常写:
java
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
Emp emp = empService.getById(id);
return Result.success(emp);
}
这里的 id 本质上就是数据库表中的主键。
3. 方便建立表关系
两张表之间建立关系时,也经常会用到主键。
比如员工属于某个部门。
部门表 dept:
| id | name |
|---|---|
| 1 | 学工部 |
| 2 | 教研部 |
员工表 emp:
| id | name | dept_id |
|---|---|---|
| 1 | 张三 | 1 |
| 2 | 李四 | 2 |
这里 emp.dept_id 保存的是部门表中的 dept.id。
这样就可以知道:
text
张三属于学工部
李四属于教研部
八、外键是什么?
外键是用来建立两张表之间关系的字段。
比如部门表:
sql
create table dept (
id int unsigned primary key auto_increment,
name varchar(20)
);
员工表:
sql
create table emp (
id int unsigned primary key auto_increment,
name varchar(10),
dept_id int unsigned
);
这里的 dept_id 就可以理解为员工表中的外键字段。
它指向部门表的 id。
关系如下:
text
emp.dept_id -> dept.id
也就是说:
员工表中的 dept_id 用来表示这个员工属于哪个部门。
九、要不要真的添加外键约束?
在数据库中,可以真正添加外键约束:
sql
alter table emp
add constraint fk_emp_dept_id
foreign key (dept_id) references dept(id);
这样数据库会帮我们保证:
text
emp.dept_id 必须是 dept 表中真实存在的 id
比如部门表中没有 id 为 10 的部门,那么员工表中就不能插入 dept_id = 10 的数据。
但是在很多 Java 后端项目中,实际开发时不一定会在数据库层面添加外键约束,而是通过业务代码控制数据关系。
原因是:
- 外键约束会让删除、修改数据时更严格
- 大项目中表关系复杂,外键维护成本较高
- 有些项目更倾向于在业务层保证数据一致性
所以初学阶段需要先理解外键思想:
一个表中的字段,保存另一个表的主键 id,用来建立两张表之间的关系。
至于是否真的添加数据库外键约束,要看项目规范。
十、数据库表和 Java 项目的关系
学习数据库不是孤立的,它和 Java 后端项目是直接关联的。
比如在 Spring Boot + MyBatis 项目中,常见关系是:
| 数据库 | Java 项目 |
|---|---|
| 表 | 实体类 |
| 字段 | 属性 |
| 一条记录 | 一个对象 |
| 多条记录 | List 集合 |
| 主键 id | 根据 id 查询、修改、删除 |
| 外键字段 | 多表关联查询 |
比如数据库表:
sql
select id, username, name, gender, phone from emp;
查询出来多条记录后,在 Java 中通常就是:
java
List<Emp> empList = empMapper.list();
如果查询一条记录:
sql
select id, username, name, gender, phone from emp where id = 1;
在 Java 中通常就是:
java
Emp emp = empMapper.getById(1);
所以理解数据库结构之后,再看 Mapper 层代码就会清楚很多。
十一、常见问题总结
1. 数据库和表有什么区别?
数据库可以包含多张表。
表是真正保存数据的地方。
比如 tlias 是数据库,emp、dept、student 是数据库中的表。
2. 字段和记录有什么区别?
字段是表中的列,记录是表中的行。
比如 name 是字段,张三 这一整行数据是一条记录。
3. 主键一定要叫 id 吗?
不一定。
主键可以叫 id,也可以叫 emp_id、user_id。
但是在学习项目和很多企业项目中,最常见的主键字段名就是 id。
4. 主键可以重复吗?
不可以。
主键的作用就是唯一标识一条数据,所以不能重复,也不能随便为空。
5. 外键一定要加数据库约束吗?
不一定。
外键思想很重要,但是否添加数据库外键约束,要看项目规范。
很多项目会保留外键字段,但不一定真的添加外键约束。
十二、总结
这一篇主要学习了数据库中最基础的几个概念:数据库、表、字段、记录、主键、外键。
数据库可以理解成存储数据的仓库,表是数据库中真正保存数据的结构。表中的一列叫字段,一行叫记录。
主键用来唯一标识一条数据,最常见的主键就是 id。外键用来建立两张表之间的关系,比如员工表中的 dept_id 可以关联部门表中的 id。
这些概念是后面学习 SQL、MyBatis、多表查询、索引和事务的基础。尤其是在写 Java 后端项目时,数据库表结构和实体类、Mapper 查询、接口参数都会联系在一起。
下一篇我们继续学习 MySQL 中常见的数据类型,看看 int、varchar、datetime、decimal 到底应该怎么选。