# day06-MySQL-01

### 前言

在我们讲解 SpringBootWeb 基础知识(请求响应案例)的时候，我们讲到在 web 开发中，为了应用程序职责单一，方便维护，我们一般将 web 应用程序分为三层，即：Controller、Service、Dao 。

之前我们的案例中，是这样子的请求流程：浏览器发起请求，先请求 Controller；Controller 接收到请求之后，调用 Service 进行业务逻辑处理；Service 再调用 Dao，Dao 再解析 user.xml 中所存储的数据。

![image-20221205001241294](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205001241294.png)

xml 文件中可以存储数据，但是在企业项目开发中不会使用 xml 文件存储数据，因为不便管理维护，操作难度大。 在真实的企业开发中呢，都会采用数据库来存储和管理数据，那此时，web 开发调用流程图如下所示：

![image-20221205001346266](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205001346266.png)

首先来了解一下什么是数据库。

* 数据库：英文为 DataBase，简称 DB，它是存储和管理数据的仓库。

像我们日常访问的电商网站京东，企业内部的管理系统 OA、ERP、CRM 这类的系统，以及大家每天都会刷的头条、抖音类的 app，那这些大家所看到的数据，其实都是存储在数据库中的。最终这些数据，只是在浏览器或 app 中展示出来而已，最终数据的存储和管理都是数据库负责的。

![image-20221205001501275](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205001501275.png)

数据是存储在数据库中的，那我们要如何来操作数据库以及数据库中所存放的数据呢？

那这里呢，会涉及到一个软件：数据库管理系统（**D**ata**B**ase **M**anagement **S**ystem，简称 DBMS）

* DBMS 是操作和管理数据库的大型软件。将来我们只需要操作这个软件，就可以通过这个软件来操纵和管理数据库了。

此时又出现一个问题：DBMS 这个软件怎么知道要操作的是哪个数据库、哪个数据呢？是对数据做修改还是查询呢？

* 需要给 DBMS 软件发送一条指令，告诉这个软件我们要执行的是什么样的操作，要对哪个数据进行操作。而这个指令就是 SQL 语句

SQL（**S**tructured **Q**uery **L**anguage，简称 SQL）：结构化查询语言，它是操作关系型数据库的编程语言，定义了一套操作关系型数据库的统一标准。我们学习数据库开发，最为重要的就是学习 SQL 语句 。

> 关系型数据库：我们后面会详细讲解，现在大家只需要知道我们学习的数据库属于关系型数据库即可。

![image-20221205095039939](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205095039939.png)

结论：程序员给数据库管理系统(DBMS)发送 SQL 语句，再由数据库管理系统操作数据库当中的数据。

了解了数据库的一些简单概念之后，接下来我们再来介绍下目前主流的数据库，这里截取了排名前十的数据库：

![image-20221205120408757](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205120408757.png)

* Oracle：大型的收费数据库，Oracle 公司产品，价格昂贵。（通常是不差钱的公司会选择使用这个数据库）
* MySQL：开源免费的中小型数据库，后来 Sun 公司收购了 MySQL，而 Oracle 又收购了 Sun 公司。目前 Oracle 推出两个版本的 Mysql：社区版(开源免费)、商业版(收费)。
* SQL Server：Microsoft 公司推出的收费的中型数据库，C#、.net 等语言常用。
* PostgreSQL：开源免费的中小型数据库。
* DB2：IBM 公司的大型收费数据库产品。
* SQLLite：嵌入式的微型数据库。Android 内置的数据库采用的就是该数据库。
* MariaDB：开源免费的中小型数据库。是 MySQL 数据库的另外一个分支、另外一个衍生产品，与 MySQL 数据库有很好的兼容性。

那这么多数据库，我们全部都需要学习吗，其实并不用，我们只需要学习其中的一个就可以了，我们此次课程中学习的数据库是现在互联网公司开发使用最为流行的 MySQL 数据库。

此时大家可能会有一个疑问，我们现在学习的是 Mysql 数据库，我们以后去公司做开发，如果用到的是 Oracle 数据库或 SQL Server 数据库该怎么办？其实大家完全不用担心这个问题，因为这些数据库都是属于关系型数据库，要操作关系型数据库都是通过 SQL 语句来实现的，而 SQL 语句又是操作关系型数据库的统一标准。

> 结论：只要我们学会了 SQL 语句，就可以通过 SQL 语句来操作 Mysql，也可以通过 SQL 语句来操作 Oracle 或 SQL Server

课程内容安排：

![image-20221205122731402](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205122731402.png)

以上课程内容拆解为 3 部分知识点：

![image-20221205122937131](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205122937131.png)

接下来我们就先进入到第一天的 Mysql 概述学习。

### 1. MySQL 概述

![image-20220610191829748](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220610191829748.png)

官网：<https://dev.mysql.com/>

#### 1.1 安装

**1.1.1 版本**

MySQL 官方提供了两个版本：

* 商业版本（MySQL Enterprise Edition）
  * 该版本是收费的，我们可以使用 30 天。 官方会提供对应的技术支持。
* 社区版本（MySQL Community Server）
  * 该版本是免费的，但是 MySQL 不会提供任何的技术支持。

> 本课程，采用的是 MySQL 的社区版本（8.0.31）

**1.1.2 安装**

官网下载地址：<https://downloads.mysql.com/archives/community/>

![image-20221205140643412](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205140643412.png)

这个安装包呢，大家可以不用下载，因为资料中已提供现成的安装包。 ![image-20221205140732982](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205140732982.png)

> 安装 MySQL 具体的步骤，参考资料中提供的 《MySQL 安装文档》 ，进行软件的安装即可。

**1.1.3 连接**

MySQL 服务器启动完毕后，然后再使用如下指令，来连接 MySQL 服务器：

```
mysql -u用户名 -p密码 [-h数据库服务器的IP地址 -P端口号]
```

> -h 参数不加，默认连接的是本地 127.0.0.1 的 MySQL 服务器
>
> -P 参数不加，默认连接的端口号是 3306

**上述指令，可以有两种形式：**

* 密码直接在-p 参数之后直接指定 （这种方式不安全，密码直接以明文形式出现在命令行）

![image-20221205143139656](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205143139656.png)

* 密码在-p 回车之后，在命令行中输入密码，然后回车

![image-20221205143418632](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205143418632.png)

**1.1.4 企业使用方式(了解)**

上述的 MySQL 服务器我们是安装在本地的，这个仅仅是在我们学习阶段，在真实的企业开发中，MySQL 数据库服务器是不会在我们本地安装的，是在公司的服务器上安装的，而服务器还需要放置在专门的 IDC 机房中的，IDC 机房呢，就需要保证恒温、恒湿、恒压，而且还要保证网络、电源的可靠性(备用电源及网络)。

![image-20220829110618240](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829110618240.png)

那我们要想使用服务器上的这台 MySQL 服务器，就需要在我们的电脑上去远程连接这台 MySQL。 而服务器上安装的 MySQL 数据库呢，并不是你一个人在访问，我们项目组的其他开发人员也是需要访问这台 MySQL 的。

![image-20220829110723526](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829110723526.png)

我们在学习阶段，如果想提前体验一下企业中数据库的使用方式，可以借助于 VMware 虚拟机来实现。我们可以在我们的电脑上安装一个 VMware，然后在 Vmware 虚拟机上在安装一个服务器操作系统 Linux，然后再在 Linux 服务器上安装各种企业级软件。

![image-20220829111237340](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829111237340.png)

接下来，就来演示一下，通过 MySQL 的客户端命令行，如何来连接服务器上部署的 MySQL ：

```
mysql -u用户名 -p密码 [-h数据库服务器的IP地址 -P端口号]
```

![image-20220829111522126](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829111522126.png)

#### 1.2 数据模型

介绍完了 Mysql 数据库的安装配置之后，接下来我们再来聊一聊 Mysql 当中的数据模型。学完了这一小节之后，我们就能够知道在 Mysql 数据库当中到底是如何来存储和管理数据的。

在介绍 Mysql 的数据模型之前，需要先了解一个概念：关系型数据库。

**关系型数据库（RDBMS）**

概念：建立在关系模型基础上，由多张相互连接的**二维表**组成的数据库。

而所谓二维表，指的是由行和列组成的表，如下图：

![image-20221205145028667](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205145028667.png)

二维表的优点：

* 使用表存储数据，格式统一，便于维护
* 使用 SQL 语言操作，标准统一，使用方便，可用于复杂查询

> 我们之前提到的 MySQL、Oracle、DB2、SQLServer 这些都是属于关系型数据库，里面都是基于二维表存储数据的。
>
> 结论：基于二维表存储数据的数据库就成为关系型数据库，不是基于二维表存储数据的数据库，就是非关系型数据库（比如大家后面要学习的 Redis，就属于非关系型数据库）。

**2). 数据模型**

介绍完了关系型数据库之后，接下来我们再来看一看在 Mysql 数据库当中到底是如何来存储数据的，也就是 Mysql 的数据模型。

MySQL 是关系型数据库，是基于二维表进行数据存储的，具体的结构图下:

![image-20220829111741419](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829111741419.png)

* 通过 MySQL 客户端连接数据库管理系统 DBMS，然后通过 DBMS 操作数据库
* 使用 MySQL 客户端，向数据库管理系统发送一条 SQL 语句，由数据库管理系统根据 SQL 语句指令去操作数据库中的表结构及数据
* 一个数据库服务器中可以创建多个数据库，一个数据库中也可以包含多张表，而一张表中又可以包含多行记录。

> 在 Mysql 数据库服务器当中存储数据，你需要：
>
> 1. 先去创建数据库（可以创建多个数据库，之间是相互独立的）
> 2. 在数据库下再去创建数据表（一个数据库下可以创建多张表）
> 3. 再将数据存放在数据表中（一张表可以存储多行数据）

#### 1.3 SQL 简介

SQL：结构化查询语言。一门操作关系型数据库的编程语言，定义操作所有关系型数据库的统一标准。

在学习具体的 SQL 语句之前，先来了解一下 SQL 语言的语法。

**1.3.1 SQL 通用语法**

1、SQL 语句可以单行或多行书写，以分号结尾。

![image-20221205151656214](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205151656214.png)

2、SQL 语句可以使用空格/缩进来增强语句的可读性。

![image-20221205151953441](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205151953441.png)

3、MySQL 数据库的 SQL 语句不区分大小写。

![image-20221205152112070](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205152112070.png)

4、注释：

* 单行注释：-- 注释内容 或 ## 注释内容(MySQL 特有)
* 多行注释： /\_ 注释内容 \_/

> 以上就是 SQL 语句的通用语法，这些通用语法大家目前先有一个直观的认识，我们后面在讲解每一类 SQL 语句的时候，还会再来强调通用语法。

**1.3.2 分类**

SQL 语句根据其功能被分为四大类：DDL、DML、DQL、DCL

| **分类** | **全称**                     | **说明**                      |
| ------ | -------------------------- | --------------------------- |
| DDL    | Data Definition Language   | 数据定义语言，用来定义数据库对象(数据库，表，字段)  |
| DML    | Data Manipulation Language | 数据操作语言，用来对数据库表中的数据进行增删改     |
| DQL    | Data Query Language        | 数据查询语言，用来查询数据库中表的记录         |
| DCL    | Data Control Language      | 数据控制语言，用来创建数据库用户、控制数据库的访问权限 |

![image-20221205152804250](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205152804250.png)

### 2. 数据库设计-DDL

下面我们就正式的进入到 SQL 语句的学习，在学习之前先给大家介绍一下我们要开发一个项目，整个开发流程是什么样的，以及在流程当中哪些环节会涉及到数据库。

#### 2.1 项目开发流程

![image-20220829112953742](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829112953742.png)

需求文档：

* 在我们开发一个项目或者项目当中的某个模块之前，会先会拿到产品经理给我们提供的页面原型及需求文档。

![image-20221205154101142](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205154101142.png)

设计：

* 拿到产品原型和需求文档之后，我们首先要做的不是编码，而是要先进行项目的设计，其中就包括概要设计、详细设计、接口设计、数据库设计等等。
* 数据库设计根据产品原型以及需求文档，要分析各个模块涉及到的表结构以及表结构之间的关系，以及表结构的详细信息。最终我们需要将数据库以及数据库当中的表结构设计创建出来。

开发/测试：

* 参照页面原型和需求进行编码，实现业务功能。在这个过程当中，我们就需要来操作设计出来的数据库表结构，来完成业务的增删改查操作等。

部署上线：

* 在项目的功能开发测试完成之后，项目就可以上线运行了，后期如果项目遇到性能瓶颈，还需要对项目进行优化。优化很重要的一个部分就是数据库的优化，包括数据库当中索引的建立、SQL 的优化、分库分表等操作。

在上述的流程当中，针对于数据库来说，主要包括三个阶段：

1. 数据库设计阶段
   * 参照页面原型以及需求文档设计数据库表结构
2. 数据库操作阶段
   * 根据业务功能的实现，编写 SQL 语句对数据表中的数据进行增删改查操作
3. 数据库优化阶段
   * 通过数据库的优化来提高数据库的访问性能。优化手段：索引、SQL 优化、分库分表等

接下来我们就先来学习第一部分数据库的设计，而数据库的设计就是来定义数据库，定义表结构以及表中的字段。

#### 2.2 数据库操作

我们在进行数据库设计，需要使用到刚才所介绍 SQL 分类中的 DDL 语句。

DDL 英文全称是 Data Definition Language(数据定义语言)，用来定义数据库对象(数据库、表)。

DDL 中数据库的常见操作：查询、创建、使用、删除。

**2.2.1 查询数据库**

**查询所有数据库：**

```sql
show databases;
```

命令行中执行效果如下：

![image-20220829124104154](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829124104154.png)

**查询当前数据库：**

```sql
select database();
```

命令行中执行效果如果：

![image-20221205174615074](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205174615074.png)

> 我们要操作某一个数据库，必须要切换到对应的数据库中。
>
> 通过指令：select database() ，就可以查询到当前所处的数据库

**2.2.2 创建数据库**

**语法：**

```sql
create database [ if not exists ] 数据库名;
```

案例： 创建一个 itcast 数据库。

```sql
create database itcast;
```

命令行执行效果如下：

![image-20220829124219427](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829124219427.png)

\==注意：在同一个数据库服务器中，不能创建两个名称相同的数据库，否则将会报错。==

![image-20220829124250514](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829124250514.png)

* 可以使用 if not exists 来避免这个问题

```sql
-- 数据库不存在,则创建该数据库；如果存在则不创建
create database if not extists itcast;
```

命令行执行效果如下： ![image-20220829124326741](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829124326741.png)

**2.2.3 使用数据库**

**语法：**

```sql
use 数据库名 ;
```

> 我们要操作某一个数据库下的表时，就需要通过该指令，切换到对应的数据库下，否则不能操作。

案例：切换到 itcast 数据

```sql
use itcast;
```

命令执行效果如下：

![image-20220829124929708](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829124929708.png)

**2.2.4 删除数据库**

**语法：**

```sql
drop database [ if exists ] 数据库名 ;
```

> 如果删除一个不存在的数据库，将会报错。
>
> 可以加上参数 if exists ，如果数据库存在，再执行删除，否则不执行删除。

案例：删除 itcast 数据库

```sql
drop database if exists itcast; -- itcast数据库存在时删除
```

命令执行效果如下：

![image-20220829125006142](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829125006142.png)

> 说明：上述语法中的 database，也可以替换成 schema
>
> * 如：create schema db01;
> * 如：show schemas;
>
> <img src="https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205180608004.png" alt="image-20221205180608004" data-size="original">

#### 2.3 图形化工具

**2.3.1 介绍**

前面我们讲解了 DDL 中关于数据库操作的 SQL 语句，在我们编写这些 SQL 时，都是在命令行当中完成的。大家在练习的时候应该也感受到了，在命令行当中来敲这些 SQL 语句很不方便，主要的原因有以下 3 点：

1. 没有任何代码提示。（全靠记忆，容易敲错字母造成执行报错）
2. 操作繁琐，影响开发效率。（所有的功能操作都是通过 SQL 语句来完成的）
3. 编写过的 SQL 代码无法保存。

在项目开发当中，通常为了提高开发效率，都会借助于现成的图形化管理工具来操作数据库。

目前 MySQL 主流的图形化界面工具有以下几种：

![image-20221205184802646](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205184802646.png)

DataGrip 是 JetBrains 旗下的一款数据库管理工具，是管理和开发 MySQL、Oracle、PostgreSQL 的理想解决方案。

官网： <https://www.jetbrains.com/zh-cn/datagrip/>

**2.3.2 安装**

安装： 参考资料中提供的《DataGrip 安装手册》

> 说明：DataGrip 这款工具可以不用安装，因为 Jetbrains 公司已经将 DataGrip 这款工具的功能已经集成到了 IDEA 当中，所以我们就可以使用 IDEA 来作为一款图形化界面工具来操作 Mysql 数据库。

**2.3.3 使用**

**2.3.3.1 连接数据库**

1、打开 IDEA 自带的 Database

![image-20221205190929756](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205190929756.png)

2、配置 MySQL

![image-20221205191143072](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205191143072.png)

3、输入相关信息

![image-20221205192606038](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205192606038.png)

4、下载 MySQL 连接驱动

![image-20221205192847190](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205192847190.png)

5、测试数据库连接

![image-20221205193304124](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205193304124.png)

6、保存配置

![image-20221205193409856](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205193409856.png)

默认情况下，连接上了 MySQL 数据库之后， 数据库并没有全部展示出来。 需要选择要展示哪些数据库。具体操作如下：

![](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/8.gif)

**2.3.3.2 操作数据库**

**创建数据库：**

![image-20221205195346655](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205195346655.png)

![image-20221205195510716](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205195510716.png)

> 有了图形化界面工具后，就可以方便的使用图形化工具：创建数据库，创建表、修改表等 DDL 操作。
>
> 其实工具底层也是通过 DDL 语句操作的数据库，只不过这些 SQL 语句是图形化界面工具帮我们自动完成的。

**查看所有数据库：**

![image-20221205195128343](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205195128343.png)

![image-20221205195833439](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205195833439.png)

#### 2.4 表操作

学习完了 DDL 语句当中关于数据库的操作之后，接下来我们继续学习 DDL 语句当中关于表结构的操作。

关于表结构的操作也是包含四个部分：创建表、查询表、修改表、删除表。

**2.4.1 创建**

**2.4.1.1 语法**

```sql
create table  表名(
	字段1  字段1类型 [约束]  [comment  字段1注释 ],
	字段2  字段2类型 [约束]  [comment  字段2注释 ],
	......
	字段n  字段n类型 [约束]  [comment  字段n注释 ]
) [ comment  表注释 ] ;
```

> 注意： \[ ] 中的内容为可选参数； 最后一个字段后面没有逗号

案例：创建 tb\_user 表

* 对应的结构如下：

![image-20220829143005524](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829143005524.png)

* 建表语句：

```sql
create table tb_user (
    id int comment 'ID,唯一标识',   # id是一行数据的唯一标识（不能重复）
    username varchar(20) comment '用户名',
    name varchar(10) comment '姓名',
    age int comment '年龄',
    gender char(1) comment '性别'
) comment '用户表';
```

> 数据表创建完成，接下来我们还需要测试一下是否可以往这张表结构当中来存储数据。

双击打开 tb\_user 表结构，大家会发现里面没有数据：

![image-20221205211008929](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205211008929.png)

添加数据：

![](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/9.gif)

此时我们再插入一条数据：

![image-20221205214447060](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205214447060.png)

我们之前提到过：id 字段是一行数据的唯一标识，不能有重复值。但是现在数据表中有两个相同的 id 值，这是为什么呢？

* 其实我们现在创建表结构的时候， id 这个字段我们只加了一个备注信息说明它是一个唯一标识，但是在数据库层面呢，并没有去限制字段存储的数据。所以 id 这个字段没有起到唯一标识的作用。

> 想要限制字段所存储的数据，就需要用到数据库中的约束。

**2.4.1.2 约束**

概念：所谓约束就是作用在表中字段上的规则，用于限制存储在表中的数据。

作用：就是来保证数据库当中数据的正确性、有效性和完整性。（后面的学习会验证这些）

在 MySQL 数据库当中，提供了以下 5 种约束：

| **约束** | **描述**                   | **关键字**     |
| ------ | ------------------------ | ----------- |
| 非空约束   | 限制该字段值不能为 null           | not null    |
| 唯一约束   | 保证字段的所有数据都是唯一、不重复的       | unique      |
| 主键约束   | 主键是一行数据的唯一标识，要求非空且唯一     | primary key |
| 默认约束   | 保存数据时，如果未指定该字段值，则采用默认值   | default     |
| 外键约束   | 让两张表的数据建立连接，保证数据的一致性和完整性 | foreign key |

> 注意：约束是作用于表中字段上的，可以在创建表/修改表的时候添加约束。

案例：创建 tb\_user 表

* 对应的结构如下：

![image-20220829143005524](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829143005524.png)

> 在上述的表结构中:
>
> * id 是一行数据的唯一标识
> * username 用户名字段是非空且唯一的
> * name 姓名字段是不允许存储空值的
> * gender 性别字段是有默认值，默认为男

* 建表语句：

```sql
create table tb_user (
    id int primary key comment 'ID,唯一标识',
    username varchar(20) not null unique comment '用户名',
    name varchar(10) not null comment '姓名',
    age int comment '年龄',
    gender char(1) default '男' comment '性别'
) comment '用户表';
```

> 数据表创建完成，接下来测试一下表中字段上的约束是否生效

![image-20221205215309011](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205215309011.png)

![image-20221205215632599](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205215632599.png)

大家有没有发现一个问题：id 字段下存储的值，如果由我们自己来维护会比较麻烦(必须保证值的唯一性)。MySQL 数据库为了解决这个问题，给我们提供了一个关键字：auto\_increment（自动增长）

> 主键自增：auto\_increment
>
> * 每次插入新的行记录时，数据库自动生成 id 字段(主键)下的值
> * 具有 auto\_increment 的数据列是一个正数序列开始增长(从 1 开始自增)

```sql
create table tb_user (
    id int primary key auto_increment comment 'ID,唯一标识', #主键自动增长
    username varchar(20) not null unique comment '用户名',
    name varchar(10) not null comment '姓名',
    age int comment '年龄',
    gender char(1) default '男' comment '性别'
) comment '用户表';
```

测试：主键自增

![](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/10.gif)

**2.4.1.3 数据类型**

在上面建表语句中，我们在指定字段的数据类型时，用到了 int 、varchar、char，那么在 MySQL 中除了以上的数据类型，还有哪些常见的数据类型呢？ 接下来,我们就来详细介绍一下 MySQL 的数据类型。

MySQL 中的数据类型有很多，主要分为三类：数值类型、字符串类型、日期时间类型。

**数值类型**

| 类型          | 大小     | 有符号(SIGNED)范围                                        | 无符号(UNSIGNED)范围                                         | 描述         |
| ----------- | ------ | ---------------------------------------------------- | ------------------------------------------------------- | ---------- |
| TINYINT     | 1byte  | (-128，127)                                           | (0，255)                                                 | 小整数值       |
| SMALLINT    | 2bytes | (-32768，32767)                                       | (0，65535)                                               | 大整数值       |
| MEDIUMINT   | 3bytes | (-8388608，8388607)                                   | (0，16777215)                                            | 大整数值       |
| INT/INTEGER | 4bytes | (-2147483648，2147483647)                             | (0，4294967295)                                          | 大整数值       |
| BIGINT      | 8bytes | (-263，263-1)                                         | (0，2^64-1)                                              | 极大整数值      |
| FLOAT       | 4bytes | (-3.402823466 E+38，3.402823466351 E+38)              | 0 和 (1.175494351 E-38，3.402823466 E+38)                 | 单精度浮点数值    |
| DOUBLE      | 8bytes | (-1.7976931348623157 E+308，1.7976931348623157 E+308) | 0 和 (2.2250738585072014 E-308，1.7976931348623157 E+308) | 双精度浮点数值    |
| DECIMAL     |        | 依赖于 M(精度)和 D(标度)的值                                   | 依赖于 M(精度)和 D(标度)的值                                      | 小数值(精确定点数) |

```sql
示例:
    年龄字段 ---不会出现负数, 而且人的年龄不会太大
	age tinyint unsigned

	分数 ---总分100分, 最多出现一位小数
	score double(4,1)
```

**字符串类型**

| 类型         | 大小                    | 描述                |
| ---------- | --------------------- | ----------------- |
| CHAR       | 0-255 bytes           | 定长字符串(需要指定长度)     |
| VARCHAR    | 0-65535 bytes         | 变长字符串(需要指定长度)     |
| TINYBLOB   | 0-255 bytes           | 不超过 255 个字符的二进制数据 |
| TINYTEXT   | 0-255 bytes           | 短文本字符串            |
| BLOB       | 0-65 535 bytes        | 二进制形式的长文本数据       |
| TEXT       | 0-65 535 bytes        | 长文本数据             |
| MEDIUMBLOB | 0-16 777 215 bytes    | 二进制形式的中等长度文本数据    |
| MEDIUMTEXT | 0-16 777 215 bytes    | 中等长度文本数据          |
| LONGBLOB   | 0-4 294 967 295 bytes | 二进制形式的极大文本数据      |
| LONGTEXT   | 0-4 294 967 295 bytes | 极大文本数据            |

char 与 varchar 都可以描述字符串，char 是定长字符串，指定长度多长，就占用多少个字符，和字段值的长度无关 。而 varchar 是变长字符串，指定的长度为最大占用长度 。相对来说，char 的性能会更高些。

```sql
示例：
    用户名 username ---长度不定, 最长不会超过50
	username varchar(50)

	手机号 phone ---固定长度为11
	phone char(11)
```

**日期时间类型**

| 类型        | 大小 | 范围                                        | 格式                  | 描述           |
| --------- | -- | ----------------------------------------- | ------------------- | ------------ |
| DATE      | 3  | 1000-01-01 至 9999-12-31                   | YYYY-MM-DD          | 日期值          |
| TIME      | 3  | -838:59:59 至 838:59:59                    | HH:MM:SS            | 时间值或持续时间     |
| YEAR      | 1  | 1901 至 2155                               | YYYY                | 年份值          |
| DATETIME  | 8  | 1000-01-01 00:00:00 至 9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值     |
| TIMESTAMP | 4  | 1970-01-01 00:00:01 至 2038-01-19 03:14:07 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值，时间戳 |

```sql
示例:
	生日字段  birthday ---生日只需要年月日
	birthday date

	创建时间 createtime --- 需要精确到时分秒
	createtime  datetime
```

**2.4.1.4 案例**

需求：根据产品原型/需求创建表((设计合理的数据类型、长度、约束)

> 参考资料中提供的《黑马-tlias 智能学习辅助系统》页面原型，设计员工管理模块的表结构
>
> 暂不考虑所属部门字段

产品原型及需求如下：

![image-20220829151032029](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829151032029.png)

![](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829151228102.png)

![](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20220829151245450.png)

**步骤：**

1. 阅读产品原型及需求文档，看看里面涉及到哪些字段。
2. 查看需求文档说明，确认各个字段的类型以及字段存储数据的长度限制。
3. 在页面原型中描述的基础字段的基础上，再增加额外的基础字段。

使用 SQL 创建表：

```sql
create table emp (
  id int unsigned primary key auto_increment comment 'ID',
  username varchar(20) not null unique comment '用户名',
  password varchar(32) default '123456' comment '密码',
  name varchar(10) not null comment '姓名',
  gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',
  image varchar(300) comment '图像',
  job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管',
  entrydate date comment '入职时间',
  create_time datetime not null comment '创建时间',
  update_time datetime not null comment '修改时间'
) comment '员工表';
```

除了使用 SQL 语句创建表外，我们还可以借助于图形化界面来创建表结构，这种创建方式会更加直观、更加方便。

操作步骤如下：

1. 在指定操作的数据库上，右键 New ==> Table

![image-20221205230447721](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205230447721.png)

2. 编辑表结构的相关信息

![image-20221205231846161](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205231846161.png)

**2.4.1.5 设计表流程**

通过上面的案例，我们明白了，设计一张表，基本的流程如下：

1. 阅读页面原型及需求文档
2. 基于页面原则和需求文档，确定原型字段(类型、长度限制、约束)
3. 再增加表设计所需要的业务基础字段(id 主键、插入时间、修改时间)

![image-20221205232253088](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205232253088.png)

> 说明：
>
> * create\_time：记录的是当前这条数据插入的时间。
> * update\_time：记录当前这条数据最后更新的时间。

**2.4.2 查询**

> 关于表结构的查询操作，工作中一般都是直接基于**图形化界面操作**。

**查询当前数据库所有表**

```sql
show tables;
```

![image-20221205233746548](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205233746548.png)

**查看指定表结构**

```sql
desc 表名 ;#可以查看指定表的字段、字段的类型、是否可以为NULL、是否存在默认值等信息
```

![image-20221205234114053](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205234114053.png)

**查询指定表的建表语句**

```sql
show create table 表名 ;
```

![image-20221205234334696](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205234334696.png)

![image-20221205234444906](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205234444906.png)

**2.4.3 修改**

> 关于表结构的修改操作，工作中一般都是直接基于**图形化界面操作**。

**添加字段**

```sql
alter table 表名 add  字段名  类型(长度)  [comment 注释]  [约束];
```

案例： 为 tb\_emp 表添加字段 qq，字段类型为 varchar(11)

```sql
alter table tb_emp add  qq  varchar(11) comment 'QQ号码';
```

> 图形化操作：添加字段

![image-20221205235542272](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205235542272.png)

![image-20221205235657807](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205235657807.png)

**修改数据类型**

```sql
alter table 表名 modify  字段名  新数据类型(长度);
```

```sql
alter table 表名 change  旧字段名  新字段名  类型(长度)  [comment 注释]  [约束];
```

案例：修改 qq 字段的字段类型，将其长度由 11 修改为 13

```sql
alter table tb_emp modify qq varchar(13) comment 'QQ号码';
```

案例：修改 qq 字段名为 qq\_num，字段类型 varchar(13)

```sql
alter table tb_emp change qq qq_num varchar(13) comment 'QQ号码';
```

> 图形化操作：修改数据类型和字段名

![image-20221205235950010](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221205235950010.png)

![image-20221206000030734](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221206000030734.png)

**删除字段**

```sql
alter table 表名 drop 字段名;
```

案例：删除 tb\_emp 表中的 qq\_num 字段

```sql
alter table tb_emp drop qq_num;
```

> 图形化操作：删除字段

![image-20221206000159237](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221206000159237.png)

**修改表名**

```sql
rename table 表名 to  新表名;
```

案例：将当前的 tb\_emp 表的表名修改为 emp

```sql
rename table tb_emp to emp;
```

> 图形化操作：修改表名

![image-20221206000636659](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221206000636659.png)

**2.4.4 删除**

> 关于表结构的删除操作，工作中一般都是直接基于**图形化界面操作**。

删除表语法：

```sql
drop  table [ if exists ]  表名;
```

> if exists ：只有表名存在时才会删除该表，表名不存在，则不执行删除操作(如果不加该参数项，删除一张不存在的表，执行将会报错)。

案例：如果 tb\_emp 表存在，则删除 tb\_emp 表

```sql
drop table if exists tb_emp;  -- 在删除表时，表中的全部数据也会被删除。
```

> 图形化操作：删除表

![image-20221206001026916](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221206001026916.png)

### 3. 数据库操作-DML

DML 英文全称是 Data Manipulation Language(数据操作语言)，用来对数据库中表的数据记录进行增、删、改操作。

* 添加数据（INSERT）
* 修改数据（UPDATE）
* 删除数据（DELETE）

#### 3.1 增加(insert)

insert 语法：

* 向指定字段添加数据

  ```sql
  insert into 表名 (字段名1, 字段名2) values (值1, 值2);
  ```
* 全部字段添加数据

  ```sql
  insert into 表名 values (值1, 值2, ...);
  ```
* 批量添加数据（指定字段）

  ```sql
  insert into 表名 (字段名1, 字段名2) values (值1, 值2), (值1, 值2);
  ```
* 批量添加数据（全部字段）

  ```sql
  insert into 表名 values (值1, 值2, ...), (值1, 值2, ...);
  ```

案例 1：向 tb\_emp 表的 username、name、gender 字段插入数据

```sql
-- 因为设计表时create_time, update_time两个字段不能为NULL，所以也做为要插入的字段
insert into tb_emp(username, name, gender, create_time, update_time)
values ('wuji', '张无忌', 1, now(), now());
```

案例 2：向 tb\_emp 表的所有字段插入数据

```sql
insert into tb_emp(id, username, password, name, gender, image, job, entrydate, create_time, update_time)
values (null, 'zhirou', '123', '周芷若', 2, '1.jpg', 1, '2010-01-01', now(), now());
```

案例 3：批量向 tb\_emp 表的 username、name、gender 字段插入数据

```sql
insert into tb_emp(username, name, gender, create_time, update_time)
values ('weifuwang', '韦一笑', 1, now(), now()),
       ('fengzi', '张三疯', 1, now(), now());
```

> 图形化操作：双击 tb\_emp 表查看数据

![image-20221206002807531](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221206002807531.png)

Insert 操作的注意事项：

1. 插入数据时，指定的字段顺序需要与值的顺序是一一对应的。
2. 字符串和日期型数据应该包含在引号中。
3. 插入的数据大小，应该在字段的规定范围内。

#### 3.2 修改(update)

update 语法：

```sql
update 表名 set 字段名1 = 值1 , 字段名2 = 值2 , .... [where 条件] ;
```

案例 1：将 tb\_emp 表中 id 为 1 的员工，姓名 name 字段更新为'张三'

```sql
update tb_emp set name='张三',update_time=now() where id=1;
```

案例 2：将 tb\_emp 表的所有员工入职日期更新为'2010-01-01'

```sql
update tb_emp set entrydate='2010-01-01',update_time=now();
```

![image-20221206004425527](https://cdn.jsdelivr.net/npm/zui-xin-ban-java-web-kai-fa-jiao-cheng@1.0.1/assets1/image-20221206004425527.png)

> 注意事项:
>
> 1. 修改语句的条件可以有，也可以没有，如果没有条件，则会修改整张表的所有数据。
> 2. 在修改数据时，一般需要同时修改公共字段 update\_time，将其修改为当前操作时间。

#### 3.3 删除(delete)

delete 语法：

```SQL
delete from 表名  [where  条件] ;
```

案例 1：删除 tb\_emp 表中 id 为 1 的员工

```sql
delete from tb_emp where id = 1;
```

案例 2：删除 tb\_emp 表中所有员工

```sql
delete from tb_emp;
```

> 注意事项:
>
> • DELETE 语句的条件可以有，也可以没有，如果没有条件，则会删除整张表的所有数据。
>
> • DELETE 语句不能删除某一个字段的值(可以使用 UPDATE，将该字段值置为 NULL 即可)。
>
> • 当进行删除全部数据操作时，会提示询问是否确认删除所有数据，直接点击 Execute 即可。
