MySQL库表操作
SQL语句基础
SQL简介
- SQL:结构化查询语言 (Structured Query Language),是非过程化 的语言,在关系型数据库上执行数据操作、数据检索以及数据维护的标准语言。使用SQL语句,程序员和数据库管理员可以完成如下的任务
- 改变数据库的结构
- 更改系统的安全设置
- 增加用户对数据库或表的许可权限
- 在数据库中检索需要的信息
- 对数据库的信息进行更新
SQL语句分类
- MySQL致力于支持全套ANSI/ISO SQL标准。在MySQL数据库中,SQL语句主要可以划分为以下几类
- DDL (Data Definition Language):数据定义语言,定义对数据库对象(库、表、列、索引)的操作,如:CREATE、DROP、ALTER、RENAME、 TRUNCATE等
- DML (Data Manipulation Language): 数据操作语言,定义对数据库记录的操作,如:INSERT、DELETE、UPDATE、SELECT等
- DCL (Data Control Language): 数据控制语言 ,定义对数据库、表、字段、用户的访问权限和安全级别,如:
- GRANT、REVOKE等
- Transaction Control:事务控制
- COMMIT、ROLLBACK、SAVEPOINT等
SQL语句的书写规范
- 在数据库系统中,SQL语句不区分大小写(建议用大写) ,但字符串常量区分大小写
- SQL语句可单行或多行书写,以";"结尾。
- 关键词不能跨多行或简写。
- 用空格和缩进来提高语句的可读性。
- 子句通常位于独立行,便于编辑,提高可读性。
- 注释:
- /* */ 和 // 为多行注释
- -- 和 # 为单行注释
数据库操作
数据库的登录及退出
- 登录格式
bash
mysql -u用户名 -h服务器的主机地址 -p密码 -A
-
分析
- -u 后面跟登录数据库的用户名,这里使用root
- -h 后面的参数是服务器的主机地址,在这里客户端和服务器在同一台机器上,所以输入 localhost 或者 IP 地址
- -p 后面是用户登录密码,注意:-p 和密码之间没有空格。如果出现空格,系统将不会把后面的字符串当成密码来对待,没有密码时不写
- -A参数:不预读数据库信息,加上该参数则不预读数据库中的表等信息,不会有表名及列名的补全,但读取速度会加快,不加该参数可能使用数据库时出现下列提示(不影响使用)
mysqlReading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A

- 显示信息解释:
- Commands end with; or\g:mysql 命令是以分号(;)或"\g"来结束的,遇到这个结束符就开始执行命令
- Your MySQL connection id is 22:数据库的连接次数
- Server version: 8.0.37 Source distribution : 版本
- Type 'help;' or '\h' for help:输入"help;"或者"\h"可以看到帮助信息
- Type '\c' to clear the current input statement:表示遇到"\c"就清除前面的命令,注意不是清屏
- 退出:exit quit \q
mysql
PS C:\Users\Administrator> mysql -uroot -p
Enter password: ******
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 8.0.37 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>\q
# 注意:带有密码登录,会有警告,提示不安全
PS C:\Users\Administrator> mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 8.0.37 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
查看数据库
- 格式:
mysql
mysql> show databases [like 条件]; # 注意有s
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
- MySQL自带数据库
- Information_schema: 主要存储了系统中的一些数据库对象信息,如:用户表信息、列信息、权限信息、字符集信息、分区信息等。(数据字典表)
- performance_schema:主要存储数据库服务器的性能参数
- mysql: 存储了系统的用户权限信息及帮助信息
- sys: 5.7新增,之前版本需要手工导入。这个库是通过视图的形式把information_schema 和performance_schema结合起来,查询出更加令人容易理解的数据
- 使用条件查看
mysql
mysql> show databases like 'sys';
+----------------+
| Database (sys) |
+----------------+
| sys |
+----------------+
1 row in set (0.00 sec)
- 带有通配符的条件
- %:匹配任意零个或多个字符
- _ :匹配任意单个字符
mysql
mysql> show databases like 's%';
+---------------+
| Database (s%) |
+---------------+
| sys |
+---------------+
1 row in set (0.00 sec)
- 显示时间
mysql
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2023-02-10 09:39:14 |
+---------------------+
1 row in set (0.00 sec)
- 显示数据库版本
mysql
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.37 |
+-----------+
1 row in set (0.00 sec)
创建数据库
- 格式:
mysql
create database 数据库名
- 示例:
mysql
mysql> create database testdb;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb |
+--------------------+
- 若数据库已存在,则报错
mysql
mysql> create database testdb;
ERROR 1007 (HY000): Can't create database 'testdb'; database exists
- 查看创建数据库的语句
mysql
# 格式
show create database 数据库名
mysql
mysql> show create database testdb;
+----------+----------------------------------------------------------------------------------------------------------------------------------+
| Database | Create Database |
+----------+----------------------------------------------------------------------------------------------------------------------------------+
| testdb | CREATE DATABASE `testdb` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+----------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
# 分析:
# 上述显示创建数据库语句的内容可看做3段内容
# CREATE DATABASE `testdb` :表示创建数据库testdb
# /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ :表示注释内容,显示字符集采用utf8mb4方案,一个字符需要 1 ~ 4 个字节。可以存储一些 emoji 表情; utf8mb4_0900_ai_ci表示字符比较规则即ai为不区分重音,ci为不区分大小写
# /*!80016 DEFAULT ENCRYPTION='N' */ 表示数据库未加密
- 注意:在创建数据库或查看创建数据库语句时,database没有s
mysql 中的反引号
- 上例中查看的sql语句有反引号,其作用可以避免一些与SQL语法冲突的问题,同时可以使代码更加规范化和易读性更强
- 如
select name, address from table;
其中table若当做表名但其为关键字回报错,加上反引号可以避免与SQL关键字的冲突:
mysql
mysql> select name, address from `table`;
- 注意:
- 只有保留关键字和特殊字符需要使用反引号,普通的表名和列名不需要
- 数据类型之间可以加或者不加反引号,但为了代码规范化,建议加上
切换数据库
- 查看当前使用的数据库,格式:
mysql
select database();
mysql
mysql> select database();
+------------+
| database() |
+------------+
| NULL |
+------------+
-
注意:当前没有使用数据库,则显示空
-
选择数据库,格式:
mysql
use 数据库名
mysql
mysql> use testdb;
Database changed
mysql> select database(); # 再次查看
+------------+
| database() |
+------------+
| testdb |
+------------+
查看当前用户
mysql
mysql> select user();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
删除数据库
- 格式:
mysql
drop database 数据库名
- 示例:
mysql
mysql> drop database testdb;
Query OK, 0 rows affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
小结
bash
# 新建数据库
create database 数据库名
# 设为当前数据库
use 数据库名
# 查看当前使用的数据库
select database();
# 显示所有数据库
show databases;
# 删除数据库
drop database 数据库名
# 查看当前登录的用户及主机名
select user();
MySQL 字符集
- MySQL字符集包括字符集(CHARACTER)和排序规则(校对规则)(COLLATION)两个概念
字符集
- Character Set(字符集):是字符的编码规则,规定了字符在数据库中的存储格式,比如占多少空间,支持哪些字符等
- 不同的字符集有不同的编码规则,在运维和使用MySQL数据库中,选取合适的字符集非常重要,如果选择不恰当,轻则影响数据库性能,严重的可能导致数据存储乱码
- mysql 5.7的默认字符集是latin1,而8.0中是utf8mb4;
- mysql8的库表创建以及程序中尽可能使用utf8mb4字符集(可支持emoji)
- mysql中的utf8字符集是utf8mb3字符集的别名,避免使用
mysql
# latin1支持西欧字符、希腊字符等
# gbk支持中文简体字符,但是不是国际通用字符集
# big5支持中文繁体字符
# utf8几乎支持世界所有国家的字符。
# utf8mb4完全兼容UTF-8,用四个字节存储更多的字符
- MySQL数据库在开发运维中,字符集选用规则如下:
- 如果系统开发面向国外业务,需要处理不同国家、不同语言,则应该选择utf-8或者utf8mb4
- 如果只需要支持中文,没有国外业务,则为了性能考虑,可以采用GBK
字符序
- 字符序就是字符排序的规则集合
- 如:使用A>B>a>b的规则来进行排序或者另一种规则a>b>A>B顺序排序
- 字符序主要对字符的排序有影响
查看MySQL字符集
- 查看所有支持的字符集
mysql
# 格式1:
mysql> show character set;
+----------+---------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+---------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| binary | Binary pseudo charset | binary | 1 |
............
# 字段含义
# Charset: 字符集的名称;
# Description:字符集的简单描述;
# Default collation:该字符集的默认字符序;
# Maxlen:该字符集中字符最大存储长度。
# 或者使用\g替代定界符分号
mysql> show character set\g
mysql
# 格式2:
# \G表示将查询结果进行按列打印,即将查到的结构旋转90度变成纵向显示,不需要分号
mysql> show character set\G
*************************** 1. row ***************************
Charset: armscii8
Description: ARMSCII-8 Armenian
Default collation: armscii8_general_ci
Maxlen: 1
*************************** 2. row ***************************
Charset: ascii
Description: US ASCII
Default collation: ascii_general_ci
Maxlen: 1
*************************** 3. row ***************************
Charset: big5
Description: Big5 Traditional Chinese
Default collation: big5_chinese_ci
Maxlen: 2
*************************** 4. row ***************************
Charset: binary
Description: Binary pseudo charset
Default collation: binary
Maxlen: 1
......
- 查看指定字符集
mysql
mysql> show character set like 'gbk';
+---------+------------------------+-------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+------------------------+-------------------+--------+
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
+---------+------------------------+-------------------+--------+
1 row in set (0.00 sec)
mysql> show character set like 'utf%';
+---------+------------------+--------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+------------------+--------------------+--------+
| utf16 | UTF-16 Unicode | utf16_general_ci | 4 |
| utf16le | UTF-16LE Unicode | utf16le_general_ci | 4 |
| utf32 | UTF-32 Unicode | utf32_general_ci | 4 |
| utf8mb3 | UTF-8 Unicode | utf8mb3_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_0900_ai_ci | 4 |
+---------+------------------+--------------------+--------+
查看MySQL字符序
- MySQL字符序命名规则:
- 以字符序对应的字符集名称开头
- 以国家名居中(或以general居中)
- 后缀:
- bin:二进制;
- ci:大小写不敏感;
- cs:大小写敏感;
- ai:口音(Accent)不敏感;
- as:口音敏感;
- ks:假名(Kanatype)敏感
- 查看支持的字符序
mysql
mysql> show collation;
# 字段含义
# Collation:字符序名称;
# Charset:该字符序关联的字符集;
# Id:字符序ID;
# Default:该字符序是否是所关联的字符集的默认字符序。armscii8_general_ci就是armscii8的默认字符序,而armscii8_bin就不是;
# Compiled:字符集是否已编译到服务器中;
# Sortlen:这与对以字符集表示的字符串进行排序所需的内存量有关;
# Pad_attribute:这表明了字符序在比较字符串时对末尾padding的处理。NO PAD表明在比较字符串时,末尾的padding也会考虑进去,否则不考虑。
- 指定条件查询
mysql
mysql> show collation where charset = "utf8mb4";
查看当前字符集的设置
- 通过变量查看
mysql
mysql> show variables like 'character_set%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 # 重要 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 # 重要 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
- 变量含义
mysql
character_set_client:MySQL客户端的字符集。
character_set_connection:数据通信链路字符集,当MySQL客户机向服务器发送请求时,请求数据以该字符集进行编码。
character_set_database:数据库默认使用的字符集。
character_set_filesystem:MySQL服务器文件系统字符集,该值是固定的binary。
character_set_results:服务器返回给客户端的结果使用的字符集。
character_set_server:服务器默认的字符集。
character_set_system:服务器存储元数据使用的字符集。
utf8和utf8mb4的区别
-
MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节 的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8mb4外不需要做其他转换。当然,为了节省空间,一般情况下使用utf8也就够了。
-
既然utf8能够存下大部分中文汉字,那为什么还要使用utf8mb4呢? 原来mysql支持的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。也就是说,任何不在基本多文本平面的 Unicode字符,都无法使用 Mysql 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符,如表情等等(utf8的缺点)。
-
因此在8.0之后,建议大家使用utf8mb4这种编码。
数据库对象
数据库对象的命名规则
-
命名使用具有意义的英文词汇,词汇中间以下划线分隔
-
名称由字母、数字、#、下划线、$组成,必须以英文字母开头
-
不要使用MySQL的保留字
-
所有数据库对象使用小写字母,实际上MySQL中是可以设置大小写是否敏感的,为了保证统一性应使用小写表示
-
在同一个数据库对象集合内对象不能同名
生产中对象命名规范
- 数据库:
- 数据库命名尽量不超过30个字符
- 数据库命名一般为项目名称+代表库含义的简写,比如IM项目的工作流数据库,可以是 im_flow
- 命名应使用小写
- 表:
- 常规表:以t_开头,t代表table的意思,命名规则即 t + 模块(包含模块含义的简写)+ 表(包含表含义的简写),比如用户模块的教育信息表:t_user_eduinfo
- 临时表:temp前缀+模块+表+日期后缀:temp_user_eduinfo_20240520
- 备份表(用于保存和归档历史数据或者作为灾备恢复的数据)命名规则,bak前缀+模块+表+日期后缀:bak_user_eduinfo_20231219
- 同一个模块的表尽可能使用相同的前缀,表名称尽可能表达含义
- 多个单词以下划线 _ 分隔
- 常规表表名尽量不超过30个字符,temp表和bak表视情况而定,也尽量简短为宜,命名应使用小写
表的基本操作
数据类型
- 类型组成:数字、文本、日期/时间类型
- 整型
数据类型 | 字节数 | 带符号值范围 | 不带符号值范围 |
---|---|---|---|
tinyint | 1 | [-128,[127] | [0,255] |
smallint | 2 | [-32768,32767] | [0,65535] |
mediumint | 3 | [-8388608,8388607] | [0,16777215] |
int | 4 | [-2147483648,2147483647] | [0,4294967295] |
bigint | 8 | [-9223372036854775808,9223372036854775807] | [0,18446744073709551616] |
- 注意:
- 实际开发的角度,一定要为合适的列选取合适的数据类型,如
- 一个枚举字段只有0和1两个枚举值,选用TINYINT就足够了,但在开发场景下却使用了BIGINT,这就造成了资源浪费
- 简单计算一下,假使该数据表中有100W数据,那么总共浪费了700W字节也就是6.7M左右,如果更多的表这么做了,那么浪费的更多
- 整型(N)表现形式:有时代码写法为int(10),表示数字宽度限制,要求如下:
- 无论N等于多少,int永远占4个字节
- N表示的是显示宽度,不足则补0,超过长度则会无视长度直接显示整个数字
- 实际开发的角度,一定要为合适的列选取合适的数据类型,如
- 浮点型
数据类型 | 字节数 | 备注 |
---|---|---|
float | 4 | 单精度浮点型 |
double | 8 | 双精度浮点型 |
-
注意:可以使用float(M,D)、double(M,D)格式限制宽度按(M)和精度(D),如float(3,2),不指定M、D的时,会按照实际的精度来处理
-
定点型:decimal(size,d) ,作为字符串存储的 DOUBLE 类型,允许固定的小数点,由于float、double类型存在精度丢失问题,即写入数据库的数据未必是插入数据库的数据,而decimal无论写入数据中的数据是多少,都不会存在精度丢失问题,这就是要引入decimal类型的原因,decimal类型常见于银行系统、互联网金融系统等对小数点后的数字比较敏感的系统中,结论:float/double在db中存储的是近似值,而decimal则是以字符串形式进行保存
mysql
mysql> create database mydb1_test;
mysql> use mydb1_test;
Database changed
mysql> create table t1(float_num float(10,2) , double_num double(20,2) , decimal_num decimal(20,2));
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql> insert into t1 value (1234567.66,1234567899000000.66,123456789000000.66);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------------+---------------------+--------------------+
| float_num | double_num | decimal_num |
+------------+---------------------+--------------------+
| 1234567.62 | 1234567899000000.80 | 123456789000000.66 |
+------------+---------------------+--------------------+
mysql
# 注意:Query OK, 0 rows affected, 2 warnings (0.03 sec)含义如下:该信息是MySQL数据库执行SQL语句的结果。它表示SQL语句成功执行,但是没有影响到任何行,并且出现了两个警告。
"Query OK" 表示查询操作成功。
"0 rows affected" 表示SQL语句执行后,影响到数据库中的0行数据。
"2 warnings" 表示在执行这个查询时,发出了两个警告。
"(0.03 sec)" 表示查询执行的时间。
可以通过命令 show warnings; 查看警告信息
- 文本型
数据类型 | 描述 |
---|---|
char(size) | 保存固定长度的字符串(可包含字母、数字以及特殊字 符)。在括号中指定字符串的长度。最多 255 个字符。 |
varchar(size) | 保存可变长度的字符串(可包含字母、数字以及特殊字 符)。在括号中指定字符串的最大长度。最多 255 个字 符。 注释:如果值的长度大于 255,则被转换为 TEXT 类型。 |
tinytext | 存放最大长度为 255 个字符的字符串。 |
text | 存放最大长度为 65,535 个字符的字符串。 |
blob | 用于 BLOBs (Binary Large OBjects)。存放最多 65,535 字节的数据。 |
mediumtext | 存放最大长度为 16,777,215 个字符的字符串。 |
mediumelob | 用于 BLOBs (Binary Large OBjects)。存放最多 16,777,215 字节的数据。 |
longtext | 存放最大长度为 4,294,967,295 个字符的字符串。 |
longblob | 用于 BLOBs (Binary Large OBjects)。存放最多 4,294,967,295 字节的数据。 |
enum(x,y,z,etc.) | 允许输入可能值的列表。可以在 ENUM 列表中列出最大 65535 个值。如果列表中不存在插入的值,则插入空值。 注释:这些值是按照你输入的顺序存储的。 可以按照此格式输入可能的值: ENUM('X','Y','Z') |
set | 与 enum 类似, SET 最多只能包含 64 个列表项,不过 SET 可存储一个以上的值。 |
-
注意:
-
blob和text都是为了存储很大数据而设计的字符串数据类型,blob采用二进制形式存储无排序规则和字符集,text采用字符形式存储且有排序规则和字符集适用于存储如文章内容、评论等
-
char是固定长度字符串,其长度范围为0~255且与编码方式无关,无论字符实际长度是多少,都会按照指定长度存储,不够的用空格补足,char类型数据时会将结尾的所有空格处理掉
mysqlmysql> create table t2(char_value char(5) , varchar_value varchar(5)); Query OK, 0 rows affected (0.01 sec) mysql> insert into t2 value('a','a'); Query OK, 1 row affected (0.00 sec) mysql> insert into t2 value(' a',' a'); Query OK, 1 row affected (0.01 sec) mysql> insert into t2 value('a ','a '); Query OK, 1 row affected (0.00 sec) mysql> insert into t2 value(' a ',' a '); Query OK, 1 row affected (0.00 sec) mysql> select * from t2; +------------+---------------+ | char_value | varchar_value | +------------+---------------+ | a | a | | a | a | | a | a | | a | a | +------------+---------------+ 4 rows in set (0.00 sec) mysql> select length(char_value),length(varchar_value) from t2; +--------------------+-----------------------+ | length(char_value) | length(varchar_value) | +--------------------+-----------------------+ | 1 | 1 | | 3 | 3 | | 1 | 3 | | 3 | 5 | +--------------------+-----------------------+ 4 rows in set (0.00 sec)
-
-
date 类型
数据类型 | 字节数 | 格式 | 备注 |
---|---|---|---|
date | 3 | yyyy-MM-dd | 存储日期值 |
time | 3 | HH:mm:ss | 存储时分秒 |
year | 1 | yyyy | 存储年 |
datetime | 8 | yyyy-MM-dd HH:mm:ss | 存储日期+时间 |
timestamp | 4 | yyyy-MM-dd HH:mm:ss | 存储日期+时间,可作时间戳 |
mysql
mysql> create table t3( date_value date,time_value time,year_value year,datetime_value datetime,timestamp_value timestamp);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t3 values(now(), now(), now(), now(), now());
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> select * from t3;
创建表
- 格式:
mysql
create table 表名 (表选项)
- 表定义选项格式为:
mysql
列名1 列类型1 约束, 列名2 列类型2 约束,......
-
默认的情况是,表被创建到当前的数据库中。若表已存在、没有当前数据库或者数据库不存在,则会出现错误
-
使用 crate table 创建表时,必须指定以下信息:
- 要创建的表的名称不区分大小写,不能使用SQL语言中的关键字,如DROP、ALTER、INSERT等。
- 必须指定数据表中每个列(字段)的名称和数据类型,如果创建多个列,要用逗号隔开
-
示例1:创建数据库并新建表
数据表属于数据库,在创建数据表之前,应使用语句"use <数据库>"指定操作在哪个数据库中进行,如果没有选择数据库,就会抛出 No database selected 的错误
mysql
mysql> select database(); # 查看当前数据库
mysql> create database mydb2_stuinfo; # 创建数据库
Query OK, 1 row affected (0.02 sec)
mysql> use mydb2_stuinfo; # 使用数据库
Database changed
mysql> create table student1(id int, name varchar(30), sex char(2), age int unsigned, score float, addr varchar(50));
Query OK, 0 rows affected (0.02 sec)
mysql> show tables;
+-------------------------+
| Tables_in_mydb2_stuinfo |
+-------------------------+
| student1 |
+-------------------------+
- 示例2:新建员工表
mysql
mysql> create database mydb3_employee;
Query OK, 1 row affected (0.01 sec)
mysql> use mydb3_employee;
Database changed
mysql> create table tb1(id int(11), name varchar(25), salary float);
Query OK, 0 rows affected, 1 warning (0.03 sec)
mysql> show tables;
+--------------------------+
| Tables_in_mydb3_employee |
+--------------------------+
| tb1 |
+--------------------------+
1 row in set (0.00 sec)
- 练习:在mydb2_stuinfo库中新建班级表class1,字段如下:cla_num int(5) , cla_name varchar(10) , number int(4) , monitor varchar(20) ,creation_date date
mysql
mysql> use mydb2_stuinfo;
mysql> create table class1(cla_num int(5), cla_name varchar(10), number int(4),monitor varchar(20),creation_date date);
mysql> desc class1;
+---------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+-------+
| cla_num | int | YES | | NULL | |
| cla_name | varchar(10) | YES | | NULL | |
| number | int | YES | | NULL | |
| monitor | varchar(20) | YES | | NULL | |
| creation_date | date | YES | | NULL | |
+---------------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
查看表
- show语句:显示当前数据库中已有的数据表
mysql
show tables [from 数据库名][like wild];
mysql
mysql> show tables;
+-------------------------+
| Tables_in_mydb2_stuinfo |
+-------------------------+
| class1 |
| student1 |
+-------------------------+
2 rows in set (0.00 sec)
mysql> show tables from mydb3_employee; # 查看另一个库的表示信息
+--------------------------+
| Tables_in_mydb3_employee |
+--------------------------+
| tb1 |
+--------------------------+
1 row in set (0.00 sec)
- describe语句:查看数据表中各列的信息
mysql
{describe|desc}表名[列名];
# or
show columns from 表名称;
mysql
mysql> use mydb2_stuinfo;
mysql> desc student1;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
mysql
mysql> show columns from student1;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
- 字段意义分析:
- Field :字段名称
- type:字段类型
- null:是否允许为空
- key:索引类型
- default:默认值
- extra:填充
- 使用\G可以查看更全面的表定义信息
mysql
mysql> show create table student1\G
*************************** 1. row ***************************
Table: student1
Create Table: CREATE TABLE `student1` (
`id` int DEFAULT NULL,
`name` varchar(30) DEFAULT NULL,
`sex` char(2) DEFAULT NULL,
`age` int unsigned DEFAULT NULL,
`score` float DEFAULT NULL,
`addr` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
删除表
- 格式:
mysql
drop table [if exists] 表名;
mysql
mysql> use mydb3_employee;
Database changed
mysql> show columns from tb1;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(25) | YES | | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> drop table tb1;
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
Empty set (0.00 sec)
- 注意:
-
用户必须拥有执行 drop table 命令的权限,否则数据表不会被删除
-
推荐使用
if exists
字句,即先判断是否存在,存在则删除,如:mysqlmysql> drop table if exists tb1; Query OK, 0 rows affected (0.01 sec)
-
删除数据库表之前,一定要备份数据,以免数据丢失。
-
在删除数据库表之前,要确保该表没有被其他的表所引用,否则可能会破坏外键约束。
-
在删除数据库表之前,要确保该表的数据已经备份,并且不再需要使用。
-
在删除数据库表之前,要确保该表的数据已经被清空,否则会破坏外键约束。
-
在删除数据库表之前,要确保该表的所有索引都已经被删除。如果还存在索引,可能会导致删除失败。
-
在删除数据库表之前,要确保该表的所有相关程序已经停止运行,以免影响其他程序的正常运行。
-
修改表
- 更改表名(重命名):
mysql
# 法1:
alter table 表名 rename 新表名;
# 法2:
rename table 表名 to 新表名;
mysql
mysql> use mydb2_stuinfo;
Database changed
mysql> show tables;
+-------------------------+
| Tables_in_mydb2_stuinfo |
+-------------------------+
| class1 |
| student1 |
+-------------------------+
1 row in set (0.00 sec)
mysql> create table student2(id int(11), name varchar(30), salary float);
Query OK, 0 rows affected, 1 warning (0.05 sec)
mysql> desc student2;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql> alter table student2 rename student3; # 修改
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+-------------------------+
| Tables_in_mydb2_stuinfo |
+-------------------------+
| class1 |
| student1 |
| student3 |
+-------------------------+
2 rows in set (0.01 sec)
mysql> rename table student3 to teacher1; # 修改
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+-------------------------+
| Tables_in_mydb2_stuinfo |
+-------------------------+
| class1 |
| student1 |
| teacher1 |
+-------------------------+
2 rows in set (0.00 sec)
- 添加新列
mysql
alter table 表名 add 新列名 列类型 [after|first] 列名;
# after:在指定列之后插入新列
# first:在第一列插入新列
# 注意:无before关键字
mysql
# 例:增加一列password
mysql> alter table student1 add password char(8);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
# 注意:数据库操作后得到的反馈,表明操作的结果。这个信息表示:
Records: 2: 表示成功导入或处理的记录总数是2条。
Duplicates: 0: 表示在操作过程中没有发现重复的记录。
Warnings: 0: 表示在操作过程中没有产生任何警告。
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| password | char(8) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
7 rows in set (0.00 sec)
# 例:再添加一个新列notes varchar(30),位置在score之前
mysql> alter table student1 add notes varchar(30) after age;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| notes | varchar(30) | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| password | char(8) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
# 例:再第一列添加一个新列
mysql> alter table student1 add aa int first;
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| aa | int | YES | | NULL | |
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| notes | varchar(30) | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| password | char(8) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
9 rows in set (0.00 sec)
- 删除列
bash
alter table 表名 DROP 列名;
mysql
# 例:删除上例的notes、aa列
mysql> alter table student1 drop notes;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> alter table student1 drop aa;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| password | char(8) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
- 修改列名
mysql
alter table 表名 change 旧列名 新列名 列类型;
mysql
mysql> alter table student1 change password passwd char(8); # 改名
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc student1;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| passwd | char(8) | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+
7 rows in set (0.01 sec)
- 修改列类型
mysql
alter table 表名 modify 列名 列类型;
mysql
# 插入新列,修改类型
mysql> alter table student1 add birthday char(10); # 增加
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| passwd | char(8) | YES | | NULL | |
| birthday | char(10) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
mysql> alter table student1 modify birthday date; # 修改
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| passwd | char(8) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
修改列位置
mysql
alter table 表名 modify 列名 列类型 after 某列;
mysql
# 例:添加新列
mysql> alter table student1 add notes varchar(30) after name;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
# 将notes移动到最后
mysql> alter table student1 modify notes varchar(30) after birthday;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
# 删除该列
mysql> alter table student1 drop notes;
复制表的结构
- 方法一:在create table语句的末尾添加like子句,可以将源表的表结构复制到新表中,语法格式如下:
mysql
create table 新表名 like 源表
mysql
mysql> use mydb2_stuinfo;
mysql> insert into student1 value(1000,"zhangsan","M",18,98.5,"xi'an","12345678","2005-10-01");
Query OK, 1 row affected (0.00 sec)
mysql> insert into student1 value(1001, "lisi", "W", 20,66.79, "baoji","87654321","2003-5-01");
mysql> select * from student1;
mysql> create table student2 like student1;
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+-------------------------+
| Tables_in_mydb2_stuinfo |
+-------------------------+
| class1 |
| student1 |
| teacher1 |
+-------------------------+
3 rows in set (0.00 sec)
mysql> select * from student2; # 注意:只是复制结构框架
Empty set (0.00 sec)
- 方法二:在create table语句的末尾添加一个select语句,可以实现表结构的复制,甚至可以将源表的表记录拷贝到新表中,下面的语法格式将源表的结构和记录都拷贝到新表中。
mysql
create table 新表名 select * from 源表
mysql
mysql> create table student3 select * from student1;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show tables;
+-------------------------+
| Tables_in_mydb2_stuinfo |
+-------------------------+
| class1 |
| student1 |
| student2 |
| student3 |
| teacher1 |
+-------------------------+
4 rows in set (0.00 sec)
mysql> select * from student3;
- 方法三:如果已经存在一张结构一致的表,复制数据:
mysql
mysql> select * from student2;
Empty set (0.00 sec)
mysql> insert into student2 select * from student1;
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from student2;
mysql> drop table if exists student2;
mysql> drop table if exists student3;
mysql> drop table if exists teacher1;
数据库字典
-
数据字典:类似于系统编目或花名册,它保存数据库服务器上的元数据信息(数据库的整体属性信息)
-
元数据(meta data):即"data about data" 关于数据的数据,理解为描述数据的数据,内容包括:数据库的属性信息、数据表的属性信息、字段的属性信息、视图的属性信息、用户信息、统计类信息等。
-
information_schema数据库是MySQL系统自带的数据库,它提供了数据库元数据的访问方式
bash
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb1_test |
| mydb2_stuinfo |
| mydb3_employee |
| mydb4_product |
| mysql |
| performance_schema |
| sys |
+--------------------+
8 rows in set (0.00 sec)
- information_schema就像是MySQL实例的一个百科全书,记录了数据库当中大部分我们需要了结的信息,比如字符集,权限相关,数据库实体对象信息,外检约束,分区,压缩表,表信息,索引信息,参数,优化,锁和事物等等。
- 通过information_schema我们可以窥透整个MySQL实例的运行情况,可以了结MySQL实例的基本信息,甚至优化调优,维护数据库等,可以说是真正的一部百科全书。
mysql
mysql> use information_schema ;
mysql> show tables;
# 常用表解释
tables-存放数据库里所有的数据表、以及每个表所在数据库。
schemata-存放数据库里所有的数据库信息
views-存放数据库里所有的视图信息。
columns-存放数据库里所有的列信息。
triggers-存放数据库里所有的触发器。
routines-存放数据库里所有存储过程和函数。
key_column_usage-存放数据库所有的主外键
table_constraints-存放数据库全部约束。
statistics-存放了数据表的索引。
......
小结
mysql
# 新建表
create tables 表名(列名1 类型 , 列名2 类型 ......);
# 查看表结构
desc 表名;
# 修改表名
alter table 旧表名 rename 新表名;
# 表中添加新列
alter table 表名 add 新列名 列类型 [after|first] 列名; (after为之后)
# 删除列
alter table 表名 DROP 列名;
# 修改列名
alter table 表名 change 旧列名 新列名 列类型;
# 修改列类型
alter table 表名 modify 列名 列类型;
# 移动列
alter table 表名 modify 列名 列类型 after 某列;
# 删除表
drop table if exists 表名;
## 表的约束
### 概念
- 为什么需要约束
- 真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性,如:有一个字段是身份证,要求是唯一的
- 定义字段的类型无法满足对表的约束:
- 表字段是否可以为NULL,有没有默认值,表字段的解释能不能加上
- 对于数字类型的字段可不可以指定默认表示的位数,可不可以将这个字段设置称为唯一标识该行的数据
- 本质上Mysql是一套数据存储解决方案,除了解决基本的数据存储功能之外,还要保证数据尽可能的安全,减少用户的误操作可能性, 约束的体现,不仅仅可以体现在数据库层面,在我们进行用户业务逻辑编码的时候,我们其实也可以做判断(约束),约束其实不仅仅只能出现在数据库层而上,编码层面也是可以体现
- 约束是什么:约束是在表上强制执行的数据校验规则,本质上是Mysql通过限制用户操作的方式,来达到维护数据本身安全及数据完整性的一套方案
- 数据的完整性要从以下四个方面考虑:
- 实体完整性(Entity Integrity):例如,同一个表中,不能存在两条完全相同无法区分的记录
- 域完整性(Domain Integrity):例如:年龄范围0-120,性别范围"男/女"
- 引用完整性(Referential Integrity):例如:员工所在部门,在部门表中要能找到这个部门
- 用户自定义完整性(User-defined Integrity):例如:用户名唯一、密码不能为空等,本部门经理的工资不得高于本部门职工的平均工资的5倍。
- 约束作为数据库对象,存放在系统表中,也有自己的名字
- 常见约束:
- 非空约束
- 默认值约束
- 主键约束
- 外键约束
- 唯一约束
- 检查约束
- 创建约束的时机:
- 在建表的同时创建
- 建表后创建(修改表)
- 约束可定义列级或表级约束
### 语法
- 列级约束:在定义列的同时定义约束
```mysql
create table 表名 (列名 类型 约束 )
- 表级约束:在定义了所有列之后定义的约束
mysql
create table 表名 constraint 约束名 约束类型 (列信息)
- 创建表之后添加约束:
mysql
alter table 表名 add constraint 约束名 约束类型(要约束的列名)
- 约束名推荐采用:表名_列名_约束类型简介
非空约束
-
作用:限定某个字段/某列的值不允许为空
-
两个值:null(默认的)和not null(不为空)
-
列字段默认一般都是空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算
-
所有数据类型的值都可以是NULL,空字符串不等于NULL,0也不等于NULL
-
示例:
mysql
mysql> use mydb2_stuinfo;
Database changed
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| passwd | char(8) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
# 插入数据
mysql> insert into student1(id,name) values('1002','张三');
Query OK, 1 row affected (0.00 sec)
mysql> insert into student1(id,name) values('1003','李四');
Query OK, 1 row affected (0.00 sec)
mysql> select * from student1;
+------+----------+------+------+-------+-------+----------+------------+
| id | name | sex | age | score | addr | password | birthday |
+------+----------+------+------+-------+-------+----------+------------+
| 1000 | zhangsan | M | 18 | 98.50 | xi'an | 12345678 | 2005-10-01 |
| 1001 | lisi | w | 20 | 66.79 | baoji | 87654321 | 2003-05-01 |
| 1002 | 张三 | NULL | NULL | NULL | NULL | NULL | NULL |
| 1003 | 李四 | NULL | NULL | NULL | NULL | NULL | NULL |
+------+----------+------+------+-------+-------+----------+------------+
4 rows in set (0.00 sec)
# 显示sex之后的列都为NULL,表示内容没有填
- 若需要某些字段必须写入,应该怎么处理,如:创建一个班级表,包含班级名和班级所在的教室,站在正常的业务逻辑中:如果班级没有名字,你不知道你在哪个班级,如果教室名字可以为空,就不知道在哪上课,所以我们在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中,这就是"约束"
mysql
mysql> create table myclass1(class_name varchar(20) not null, class_room varchar(20) not null, class_id int); # 无约束
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass1;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(20) | NO | | NULL | |
| class_id | int | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
# 插入数据时:
mysql> insert into myclass1 (class_room) values('计科1');
ERROR 1364 (HY000): Field 'class_name' doesn't have a default value # 失败,因为name有约束不能为空
mysql> insert into myclass1 (class_name,class_room) values('A104','计科1'); # 同时插入成功
Query OK, 1 row affected (0.00 sec)
mysql> select * from myclass1;
+------------+------------+----------+
| class_name | class_room | class_id |
+------------+------------+----------+
| A104 | 计科1 | NULL |
+------------+------------+----------+
1 row in set (0.00 sec)
# id字段无约束,可以为空
- 以上为创建表时的设置,也可以创建之后修改:
mysql
# 语法:
alter table <数据表名> change column <字段名> <字段名> <数据类型> not null;
mysql
mysql> alter table student1 change column id id int not null;
mysql
# 也可以通过modify修改
mysql> alter table student1 modify name varchar(30) not null;
# modify字句中省略not null 相当于设置为可以为空
mysql
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | NO | | NULL | |
| name | varchar(30) | NO | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| passwd | char(8) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
- 删除not null
mysql
mysql> alter table student1 modify id int null;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
# 或者
mysql> alter table student1 modify name varchar(30);
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | NULL | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| passwd | char(8) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
默认值约束
- 作用:给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默认值。
mysql
mysql> create table teacher1(id int not null, name varchar(30) not null, sex char(2) default '女');
Query OK, 0 rows affected (0.03 sec)
mysql> desc teacher1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | | NULL | |
| name | varchar(30) | NO | | NULL | |
| sex | char(2) | YES | | 女 | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql> insert into teacher1(id,name) values(1001,'林雪');
Query OK, 1 row affected (0.00 sec)
mysql> select * from teacher1;
+------+--------+------+
| id | name | sex |
+------+--------+------+
| 1001 | 林雪 | 女 |
+------+--------+------+
1 row in set (0.00 sec)
mysql> insert into teacher1(id,name,sex) values(1002,'石磊','男'); # 也可以全字段插入
Query OK, 1 row affected (0.01 sec)
mysql> select * from teacher1;
+------+--------+------+
| id | name | sex |
+------+--------+------+
| 1001 | 林雪 | 女 |
| 1002 | 石磊 | 男 |
+------+--------+------+
2 rows in set (0.00 sec)
mysql
# 创建表之后增加默认值:
mysql> alter table student1 modify sex char(2) default '女';
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc student1;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | 女 | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| passwd | char(8) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
mysql> insert into student1 (id,name) values(1004,'王五');
Query OK, 1 row affected (0.01 sec)
mysql> select * from student1;
- 默认值的生效:数据在插入的时候不给该字段赋值,就使用默认值
- 注意:若某字段都设置了not null和default约束,则按照不插入时会选择默认值,插入时选择插入值,所以此时not null毫无意义
mysql
mysql> alter table teacher1 add age int not null default 18;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc teacher1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | | NULL | |
| name | varchar(30) | NO | | NULL | |
| sex | char(2) | YES | | 女 | |
| age | int | NO | | 18 | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
# not null和defalut一般不需要同时出现,因为default本身有默认值,不会为空
列描述comment
- 列描述没有实际含义,专门用来描述字段,会根据表创建语句保存,供操作者来查看该列的含义,相当于C/C++的注释
mysql
mysql> create table myclass2( class_name varchar(20) not null comment '教室',class_room varchar(20) default '计科2');
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass2;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO | | NULL | |
| class_room | varchar(20) | YES | | 计科2 | |
+------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> show create table myclass2\G
*************************** 1. row ***************************
Table: myclass2
Create Table: CREATE TABLE `myclass2` (
`class_name` varchar(20) NOT NULL COMMENT '教室',
`class_room` varchar(20) DEFAULT '计科2' COMMENT '班级'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
主键约束
- 作用:数据库存储数据不是唯一的目的,还要考虑到提取数据,一般要求数据库表中的记录要有一个特定的唯一标识,来表示唯一性,这个唯一的特定标识就是主键,类似于序号学号这样的唯一标识,可以根据主键来唯一地筛选出一条记录
- 主键:primary key,用来唯一的约束该字段里面的数据
- 特点:
- 主键字段不能为空,不能重复
- 一张表中最多只能有一个主键
- 主键所在的列通常是整数类型
- 主键约束是最频繁的约束
- 注意:当创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引(能够根据主键查询 的,就根据主键查询,效率更高)。如果删除主键约束了,主键约束对应的索引就自动删除了,需要注意的一点是,不要修改主键字段的值。因为主键是数据记录的唯一标识,如果修改了主键的 值,就有可能会破坏数据的完整性。
- 示例: 创建时增加主键
mysql
mysql> create table t1 ( id int unsigned primary key comment '学号不能为空', name varchar(20) not null ,sex char(2) default '男');
Query OK, 0 rows affected (0.02 sec)
mysql> desc t1;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int unsigned | NO | PRI | NULL | |
| name | varchar(20) | NO | | NULL | |
| sex | char(2) | YES | | 男 | |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql> insert into t1 values(1,'孙文','女');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+----+--------+------+
| id | name | sex |
+----+--------+------+
| 1 | 孙文 | 女 |
+----+--------+------+
1 row in set (0.00 sec)
mysql> insert into t1(id,name) values(2,'李文华');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+----+-----------+------+
| id | name | sex |
+----+-----------+------+
| 1 | 孙文 | 女 |
| 2 | 李文华 | 男 |
+----+-----------+------+
2 rows in set (0.00 sec)
mysql> insert into t1(id,name) values(1,'黎明');
ERROR 1062 (23000): Duplicate entry '1' for key 't1.PRIMARY'
# 再次插入出错,因为需要保持唯一性
- 示例:修改表,追加主键
mysql
mysql> alter table teacher1 add primary key(id);
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc teacher1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(30) | NO | | NULL | |
| sex | char(2) | YES | | 女 | |
| age | int | NO | | 18 | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
- 注意:如果该字段内有重复值,则不能以该字段新增为主键,必须先把重复的数据去掉然后才能添加该列为主键
- 删除主键:
mysql
alter table 表名 drop primary key;
mysql
mysql> alter table teacher1 drop primary key;
Query OK, 2 rows affected (0.04 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> desc teacher1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | | NULL | |
| name | varchar(30) | NO | | NULL | |
| sex | char(2) | YES | | 女 | |
| age | int | NO | | 18 | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
- 复合主键:在创建表的时候,在所有字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段作为主键,可以使用复合主键,这些字段合在一起是一个主键,也就是让多个字段联合在一起作为唯一标识,单个字段主键重复是没有问题的,只要不是成为复合主键的字段一起冲突就行
mysql
mysql> create table t2 (id int, hostname varchar(10), ip varchar(20), port int unsigned, primary key (ip,port));
Query OK, 0 rows affected (0.02 sec)
mysql> desc t2;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| hostname | varchar(10) | YES | | NULL | |
| ip | varchar(20) | NO | PRI | NULL | |
| port | int unsigned | NO | PRI | NULL | |
+----------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> insert into t2 values(1,'node1','192,168,48,2',120);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t2;
+------+----------+--------------+------+
| id | hostname | ip | port |
+------+----------+--------------+------+
| 1 | node1 | 192,168,48,2 | 120 |
+------+----------+--------------+------+
1 row in set (0.00 sec)
mysql> insert into t2 values(2,'node2','192,168,48,3',120);
Query OK, 1 row affected (0.00 sec) # 可以单个记录重复
mysql> insert into t2 values(3,'node2','192,168,48,2',120);
ERROR 1062 (23000): Duplicate entry '192,168,48,2-120' for key 't2.PRIMARY' # 复合主键一起冲突,报错
主键自增长
- 作用:给主键添加自增长的数值
- auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键
- 注意:
- 自增长字段必须是整数,自增长字段可以不设置初始值,默认从1开始递增.
- 被自增长的字段必须作为主键或者其他具有唯一性的键使用,(必须保证这一列字段具有唯一性的字段)
- 自增长字段也可以插入数据,只要不与已有数据重复即可,之后新增数据会从最大值开始递增.
- 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值).
- 一张表当中最多只能有一个自增长的列
- 约束的字段必须具备 NOT NULL 属性
- 示例:
mysql
# 先增加主键
mysql> use mydb2_stuinfo;
Database changed
mysql> alter table student1 modify id int primary key;
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
# 设置自增长
mysql> alter table student1 modify id int auto_increment;
Query OK, 3 rows affected (0.05 sec)
Records: 3 Duplicates: 0 Warnings: 0
# 查看
mysql> desc student1;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | | NULL | |
| sex | char(2) | YES | | 女 | |
| age | int unsigned | YES | | NULL | |
| score | float | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
| passwd | char(8) | YES | | NULL | |
| birthday | date | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)
mysql> insert into student1(name) values('关六');
Query OK, 1 row affected (0.00 sec)
mysql> select * from student1;
# 发现自动增长
- 指定自增长的起始值:如果第一条记录设置了该字段的初始值,那么新增加的记录就从这个初始值开始自增。例如,如果表中插入的第一条记录的 id 值设置为 5,那么再插入记录时,id 值就会从 5 开始往上增加
mysql
# 指定自增长的起始值为100
mysql> create table t3 ( id int primary key auto_increment, systemname varchar(10) not null )auto_increment=100;
Query OK, 0 rows affected (0.02 sec)
# 插入一条记录
mysql> insert into t3(systemname) values('Linux');
Query OK, 1 row affected (0.00 sec)
# 插入一条记录
mysql> insert into t3(systemname) values('windows');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t3;
+-----+------------+
| id | systemname |
+-----+------------+
| 100 | Linux |
| 101 | windows |
+-----+------------+
2 rows in set (0.01 sec)
唯一性约束
- 产生原因:一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键,唯一键就可以解决表中有多个字段需要唯一性约束的问题
- 作用:限制某个字段/某列的值不能重复
- 唯一键和主键的关系:
- 主键更多的是标识唯一性
- 唯一键更多的是保证在业务上,不要和别的信息出现重复
- 主键只能有一个,唯一键能设置多个
- 主键和唯一键不是对立关系而是补充关系,目的是让数据库创建出一个表具有非常强的约束,彻底杜绝用户的误插入,在一张表当中,可以有一个主键,也可以同时具有唯一键, 它们不是用来对比的,只是负责数据在不同层面的唯一性,既要保证选择成为主键的属性字段不能重复不能为空,同时也要保证本身具有唯一性的列的字段不能出现冲突
- 主键用来查找,唯一键用来保证数据的完整性
- 如:学生信息中有身份证号和学号两个字段,可以把身份证号设置成为主键,而所有学生的学号也不能重复,此时就可以把学号设置成唯一键
- 示例:创建表时实现
mysql
mysql> create table t4( id int primary key, name varchar(20) unique comment '名子不能重名,可以为空' );
Query OK, 0 rows affected (0.02 sec)
mysql> desc t4;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(20) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
# 插入数据
mysql> insert into t4 values(1,'刘文');
Query OK, 1 row affected (0.00 sec)
# 唯一键数据重复,插入失败
mysql> insert into t4 values(1,'刘文');
ERROR 1062 (23000): Duplicate entry '1' for key 't4.PRIMARY'
mysql> insert into t4 values(2,'张磊');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t4;
+----+--------+
| id | name |
+----+--------+
| 1 | 刘文 |
| 2 | 张磊 |
+----+--------+
2 rows in set (0.00 sec)
- 唯一键冲突,自增涨字段值不连续
mysql
# 设置id列为自增长
mysql> alter table t4 modify id int auto_increment;
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
# 插入一条记录
mysql> insert into t4(name) values('张磊磊');
ysql> select * from t4;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 刘文 |
| 2 | 张磊 |
| 3 | 张磊磊 |
+----+-----------+
3 rows in set (0.00 sec)
# 插入一条相同姓名记录
mysql> insert into t4(name) values('张磊磊');
ERROR 1062 (23000): Duplicate entry '张磊磊' for key 't4.name'
# 在插入一条记录,由于上述唯一键冲突,自增长会出现不连续
mysql> insert into t4(name) values('钱明');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t4;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 刘文 |
| 2 | 张磊 |
| 3 | 张磊磊 |
| 5 | 钱明 |
+----+-----------+
4 rows in set (0.00 sec)
外键约束
- 作用:限定某个表的某个字段的引用完整性
- 概念
- 主表(父表):被引用的表、被参考的表
- 从表(子表):引用别人的表,参考别人的表
- 外键:从表中的某个字段引用自主表的某个字段或多个字段
- 引用键:主表被引用的字段
- 外键约束主要定义在从表上,主表则必须是有主键约束或唯一键约束.当定义外键后**,要求外键列数据必须在主表的主键列存在或为null.**
- 格式:
mysql
foreign key (从表的字段名称) references 主表名字(主表的字段名称) # 建立外键关联
-
学生表通过class_id和班级表产生关联,在语义上,class_id称为外键,此时的这个学生表就相当于从表,班级表相当于是主表, 比如我们新增一个class_id为30的学生,但是班级表中得先有id为30的班级,才能在学生表中添加, 要删除班级表中id为20的班级,首先必须保证学生表中没有对应班级为class_id =20的学生.,当然我们也可以新增一个class_id为NULL的学生,表示该学生还没有分配班级, 外键可以为空!
-
注意:
- 主表必须已经存在于数据库中,或者是当前正在创建的表。如果是后一种情况,则主表与从表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性。
- 必须为主表定义主键。
- 主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这个外键的内容就是正确的。
- 在主表的表名后面指定列名或列名的组合。这个列或列的组合必须是主表的主键或候选键。
- 外键中列的数目必须和主表的主键中列的数目相同。
- 外键中列的数据类型必须和主表主键中对应列的数据类型相同。
-
定义从表的时候,设置外键其实就是设置了一个关系,在从表当中插入数据的时候,会对插入数据进行校验,校验插入的数据是否存在于主表字段当中,外键就是增加了表和表之间的约束关系.
-
示例:
mysql
# 定义主表
mysql> create table myclass3(id int primary key, name varchar(20) not null comment '班级名');
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass3;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(20) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql
# 定义从表:
mysql> create table myclass3_stu( id int primary key, name varchar(30) not null comment '学生名', class_id int, foreign key (class_id) references myclass3(id) );
Query OK, 0 rows affected (0.02 sec)
mysql> desc myclass3_stu;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(30) | NO | | NULL | |
| class_id | int | YES | MUL | NULL | |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql
# 主表中插入数据
mysql> insert into myclass3 values(10,'C++'),(20,'Java');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from myclass3;
+----+------+
| id | name |
+----+------+
| 10 | C++ |
| 20 | Java |
+----+------+
2 rows in set (0.00 sec)
mysql
# 从表中正常插入数据:
mysql> insert into myclass3_stu values(1,'Li',10),(2,'Sun',20);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from myclass3_stu;
+----+------+----------+
| id | name | class_id |
+----+------+----------+
| 1 | Li | 10 |
| 2 | Sun | 20 |
+----+------+----------+
2 rows in set (0.00 sec)
mysql
# 从表中插入没有班级的记录,受外键控制,报错
mysql> insert into myclass3_stu values(3,'wang',30);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`stu_info`.`myclass3_stu`, CONSTRAINT `myclass3_stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass3` (`id`))
shell
# 从表中,收到外键控制,可以使用null替代,表示没有分配班级
mysql> insert into myclass3_stu values(3,'wang',null);
Query OK, 1 row affected (0.00 sec)
mysql> select * from myclass3_stu;
+----+------+----------+
| id | name | class_id |
+----+------+----------+
| 1 | Li | 10 |
| 2 | Sun | 20 |
| 3 | wang | NULL |
+----+------+----------+
3 rows in set (0.00 sec)
检查约束
- 作用:检查约束(check)是用来检查数据表中字段值有效性的一种手段,一般用于设置值的范围
- 注意
- 设置检查约束时要根据实际情况进行设置,这样能够减少无效数据的输入
- 在默认值和非空约束可看作是特殊的检查约束
- 注意检查约束在8.0.16之前,MySQL默认但不会强制的遵循check约束(写不报错,但是不生效,需要通触发器完成),之后就开始正式支持这个约束了
- 示例1:创建表时设置检查约束
mysql
mysql> create table t5(id int primary key, name varchar(20), salary float, check(salary>0 and salary<10000) );
Query OK, 0 rows affected (0.02 sec)
mysql> desc t5;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> insert into t5 values(1,'Li',5984);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t5 values(2,'wang',12000);
ERROR 3819 (HY000): Check constraint 't5_chk_1' is violated.
- 示例2:修改表时添加检查约束
mysql
# 格式:
alter table 表名 add constraint <检查约束名> check(检查约束)
mysql
mysql> alter table t5 add constraint check_id check(id>0);
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
删除表的约束
mysql
# 删除not null约束
alter table 表名 modify 列名 类型;
# 删除unique约束
alter table 表名 drop index 惟一约束名;
# 删除primary key约束
alter table 表名 drop primary key;
# 删除foreign key约束
alter table 表名 drop foreign key 外键名;
存储引擎
-
数据库存储引擎 是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据,不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是存储引擎。
-
插件式存储引擎是MySQL数据库最重要的特性之一, 用户可以根据应用的需要选择如何存储和索引数据、 是否使用事务等,如:
- MyISAM :
- Mysql 5.5之前的默认数据库引擎,最为常用。
- 拥有较高的插入,查询速度,但不支持事务应用于以读写操作为主, 很少更新 、 删除 , 并对事务的完整性、 并发性要求不高的情况
- InnoDB :
- 事务型速记的首选引擎,支持ACID事务,支持行级锁定
- 应用于对事务的完整性要求高,在并发条件下要求数据的一致性的情况。
- InnoDB:是MySQL的默认数据库引擎
- MEMORY :
- 所有数据置于内存的存储引擎,拥有极高的插入,更新和查询效率。
- 但是会占用和数据量成正比的内存空间。并且其内容会在MYSQL重新启动是会丢失。
- Archive :
- 非常适合存储大量的独立的,作为历史记录的数据。
- 因为它们不经常被读取,则拥有高效的插入速度,但其对查询的支持相对较差
- Federated :将不同的 MySQL 服务器联合起来,逻辑上组成一个完整的数据库。非常适合分布式应用
- CSV :
- 逻辑上由逗号分割数据的存储引擎。
- 它会在数据库子目录里为每个数据表创建一个 .csv 文件。
- 这是一种普通文本文件,每个数据行占用一个文本行。
- CSV 存储引擎不支持索引。
- BlackHole: 黑洞引擎,写入的任何数据都会消失,一般用于记录 binlog 做复制的中继
- ERFORMANCE_SCHEMA:该引擎主要用于收集数据库服务器性能参数。
- MyISAM :
-
默认情况下, 创建表不指定表的存储引擎, 则会使用配置文件的my.ini中default-storage-engine=InnoDB指定的InnoDB
-
查看支持的引擎命令:
mysql
show engines \g
- 查看当前默认存储引擎
mysql
mysql> show variables like '%storage_engine%';
+---------------------------------+-----------+
| Variable_name | Value |
+---------------------------------+-----------+
| default_storage_engine | InnoDB |
| default_tmp_storage_engine | InnoDB |
| disabled_storage_engines | |
| internal_tmp_mem_storage_engine | TempTable |
+---------------------------------+-----------+
- 在创建表时, 可以指定表的存储引擎:
mysql
create table (...) engine=InnoDB;
完整建表语句
mysql
create table 表名(
列名 列类型 [auto_increment] [default 默认值][列约束]
...
[表约束]
) [engine=表类型] [default] charset=字符集;
列类型: 该列的数据的存储类型
auto_increment: 自动增尙只能是数值类型的列
defaul 默认值: 设置该列的默认值
约束: 对列的一些限制
engine: 表类型, 也叫表的存储引擎
charset: 设置表的字符篥
MYSQL库表设计:范式
概念
-
MySQL
的库表设计,在很多时候我们都是率性而为,往往在前期的设计中考虑并不全面,同时对于库表结构的划分也并不明确,所以很多时候在开发过程中,代码敲着敲着会去重构某张表结构,甚至大面积重构多张表结构,这种随心所欲的设计方式,无疑给开发造成了很大困扰。 -
范式 (
Normal Form
)是指设计数据库时要遵守的一些原则 -
在设计
DB
库表结构时,需要遵守该规范,可以让在项目之初,设计的库表结构更为合理且优雅。数据库范式中,声名远扬的有三大范式,但除此之外也有一些其他设计规范,如:- 数据库三大范式(
1NF、2NF、3NF
) - 第四范式(
4NF
)和第五范式:完美范式(5NF
) - 巴斯-科德范式(
BCNF
) - 域键范式
- 反范式设计
- 数据库三大范式(
-
小结:三大范式之间,是递进的关系,后续的范式都基于前一个范式的基础上推行,比如:今天我要先炒菜,然后吃饭,最后洗碗,这三者属于递进关系,后者都建立在前者之上,其顺序不能颠倒,比如先吃饭再炒菜,这必然是行不通的。数据库的三大范式也一样,第二范式必须建立在第一范式的基础之上,如若设计的库表第一范式都不满足,那定然是无法满足第二范式的。
第一范式(1NF)
-
原则 :库表设计时为了确保原子性 ,其存储数据具备不可再分性,,例:
-
在上述的学生表中,其中有一个
student
学生列,这一列存储的数据则明显不符合第一范式:原子性的规定,因为这一列的数据还可以再拆分为姓名、性别、身高三项数据,因此为了符合第一范式,应该将表结构更改为: -
如果不去拆分列满足第一范式,会造成什么影响?
- 客户端语言和表之间无法很好的生成映射关系。
- 查询到数据后,需要处理数据时,还需要对
student
字段进行额外拆分。 - 插入数据时,对于第一个字段的值还需要先拼装后才能进行写入。
第二范式(2NF)
-
原则 :表中的所有列,其数据都必须依赖于主键 ,也就是一张表只存储同一类型的数据,不能有任何一列数据与主键没有关系,例:
-
虽然此时已经满足了数据库的第一范式,但此刻观察
course
课程、score
分数这两列数据,跟前面的几列数据实际上依赖关系并不大,同时也由于这样的结构,导致前面几列的数据出现了大量冗余,所以此时可以再次拆分一下表结构: -
经过上述结构优化后,之前的一张表被拆分成学生表、课程表、成绩表三张,每张表中的
id
字段作为主键,其他字段都依赖这个主键。无论在那张表中,都可以通过id
主键确定其他字段的信息,每张表的业务属性都具备"唯一性",也就是每张表都只会描述了"一件事情",不会存在一张表中会出现两个业务属性。
第三范式(3NF)
-
原则 :表中每一列数据不能与主键之外的字段有直接关系,例:
-
比如这张学生表,目前即符合第一范式,也符合第二范式,但看最后的两个字段,
department
表示当前学生所属的院校,dean
则表示这个院系的院长是谁。一般来说,一个学生的院长是谁,首先是取决于学生所在的院系的,因此最后的dean
字段明显与department
字段存在依赖关系,因此需要进一步调整表结构: -
经过进一步的结构优化后,又将原本的学生表拆为了院系表、学生表两张,学生表中则是只存储一个院系
ID
,由院系表存储院系相关的所有数据。至此,学生表中的每个非主键字段与其他非主键字段之间,都是相互独立的,之间不会再存在任何依赖性,所有的字段都依赖于主键。 -
为什么要这样调整?不调整会发生什么问题:
- 当一个院系的院长换人后,需要同时修改学生表中的多条数据。
- 当一个院长离职后,需要删除该院长的记录,会同时删除多条学生信息。
- 如果设计的表结构,无法满足第三范式,在操作表时就会出现异常,使得整个表较难维护。
三范式小结
- 范式小结
- 1NF:确保原子性,表中每一个列数据都必须是不可再分的字段。
- 2NF:确保唯一性,每张表都只描述一种业务属性,一张表只描述一件事。
- 3NF:确保独立性,表中除主键外,每个字段之间不存在任何依赖,都是独立的。
- 没有按照范式设计表时,会存在几个问题
- 整张表数据比较冗余,同一个学生信息会出现多条。
- 表结构特别臃肿,不易于操作,要新增一个学生信息时,需添加大量数据。
- 需要更新其他业务属性的数据时,比如院系院长换人了,需要修改所有学生的记录。
- 经过三范式的设计优化后,整个库中的所有表结构,会显得更为优雅,灵活性也会更强。
巴斯-科德范式(BCNF)
-
概念:
- 前提 :一般在一张表中,可以用于区分每行数据的一个列,通常会被设为主键 ,例如常用的
ID
字段就是如此,这类主键通常被称为单一主键,即一个列组成的主键。但除此之外,还有一个联合主键的概念,也就是由多个列组成的主键 - 巴斯-科德范式也被称为
3.5NF
,是第三范式的补充版。 - 第三范式的要求是:任何非主键字段 不能与其他非主键字段间存在依赖关系,也就是要求每个非主键字段之间要具备独立性 。而巴斯-科德范式在第三范式的基础上,进一步要求:任何主属性不能对其他主键子集存在依赖。
- 大白话:规定了联合主键中的某列值,不能与联合主键中的其他列存在依赖关系
- 前提 :一般在一张表中,可以用于区分每行数据的一个列,通常会被设为主键 ,例如常用的
-
例:
-
分析
- 这张学生表,此时假设以
classes
班级字段、class_adviser
班主任字段、name
学生姓名字段,组合成一个联合主键,在这里我们可以通过联合主键,确定学生表中任何一个学生的信息,比如:熊竹老师管的计算机-2201班,哪个竹子同学有多高啊?可以通过上述的联合主键精准定位到表中第一条数据,并且最终能够给出答案为185cm
。 - 出现问题:在这张表中,一条学生信息中的班主任,取决于学生所在的班级,比如「竹子同学、子竹同学」在「计算机-2201班」,所以它们的班主任都是「熊竹老师」,因此班主任字段其实也依赖于班级字段。那会造成什么问题呢?
- 当一个班级的班主任老师换人后,需要同时修改学生表中的多条数据。
- 当一个班主任老师离职后,需要删除该老师的记录,会同时删除多条学生信息。
- 想要增加一个班级时,同时必须添加学生姓名数据,因为主键不允许为空。
- 这张学生表,此时假设以
-
通过上述分析可以明显得知,如果联合主键中的一个字段依赖于另一个字段,同样也会造成不小的问题,使得整张表的维护性变差,因此这里需要进一步调整结构:
-
经过结构调整后:
- 原本的学生表则又被拆为了班级表、学生表两张,在学生表中只存储班级
ID
,然后使用classes_id
班级ID
和name
学生姓名两个字段作为联合主键。 - 之前的三个问题也不存在,如换班主任后只需要更改班级表,无需修改学生表中的学生信息;增加班级时,只需要在班级表中新增数据,也不会影响学生表。
- 原本的学生表则又被拆为了班级表、学生表两张,在学生表中只存储班级
-
小结:第三范式只要求非主键字段 之间,不能存在依赖关系,但没要求联合主键中的字段 不能存在依赖,因此第三范式并未考虑完善,巴斯-科德范式修正的就是这点,是对第三范式的补充及完善,修正了第三范式。
第四范式(4NF)
- 多值依赖 :表中的字段之间存在一对多的关系,也就是一个字段的具体值会由多个字段来决定(一个表中至少需要有三个独立的字段才会出现多值依赖问题)
- 示例:
经典的业务,用户角色权限表,各字段含义:
user_name
字段 -- 用户名
role
字段 -- 角色信息:
USER
:普通用户角色。ADMIN
:管理员角色。ROOT
:超级管理员角色。
permission
字段 -- 权限信息:
*
:超级管理员拥有的权限级别,*
表示所有。BACKSTAGE
:管理员拥有的权限级别,表示可以操作后台。LOGIN
:普通用户拥有的权限级别,表示可以登录访问平台。
-
此时假设我们需要新增一条数据,那表中的权限字段究竟填什么?这个值是需要依赖多个字段决定的,权限来自于角色,而角色则来自于用户。也就是说,一个用户可以拥有多个角色,同时一个角色可以拥有多个权限,所以此时咱们无法单独根据用户名去确定权限值,权限值必须依赖用户、角色两个字段来决定,这种一个字段的值取决于多个字段才能确定的情况,就被称为多值依赖。
-
因此第四范式的定义就是要消除表中的多值依赖关系,上述表格拆分为:

- 观察上述的五张表正是大名鼎鼎的权限五表,将原本的用户角色权限表,拆分成了用户表、角色表、权限表、用户角色关系表、角色权限关系表。
- 经过这次拆分之后,一方面用户表、角色表、权限表中都不会有数据冗余,第二方面无论是要删除亦或新增一个角色、权限时,都不会影响其他表。后面的两张关系表,主要是为了维护用户、角色、权限三者之间的关系。
第五范式(5NF)/完美范式
-
定义:建立在
4NF
的基础上,进一步消除表中的连接依赖,直到表中的连接依赖都是主键所蕴含的。 -
第五范式解决的是无损连接问题,基本没有实际意义,了解即可,因为无损连接很少出现,而且难以察觉。
第六范式(6NF)/域键范式
- 域键范式,也被称之为终极范式,但目前也仅有学术机构在研究,在生产环境中实际的用途也不大。
反范式
-
概念:不遵循 数据库范式设计的结构,就被称为反范式结构。
-
遵循数据库范式设计优点如下:
- 避免了大量的数据冗余。
- 节省了大量存储空间。
- 表整体结构更为优雅,能让
SQL
操作更加便捷且减少出错。
-
但随着范式的级别越高,设计出的结构会更加精细化,原本一张表的数据会被分摊到多张表中存储,表的数量随之越来越多。会存在一个致命问题,也就是当同时需要这些数据时,只能采用联表查询 的形式检索数据,有时候甚至为了一个字段的数据,也需要做一次连表查询才能获得。这其中的开销无疑是花费巨大的,尤其是当连接的表不仅两三张而是很多张时,有可能还会造成索引失效,这种情况带来的资源、时间开销简直是一个噩梦,这会严重地影响整个业务系统的性能。
-
因此,也正是由于上述一些问题,在设计库表结构时,我们不一定要
100%
遵守范式准则。这种违反数据库范式的设计方法,就被称之为 反范式设计。 -
设计原则:无论哪种范式只要能够对业务有利,那就可以称之为好的设计方案。在设计时千万不要拘泥于规则之内,一定要结合实际业务考虑,遵循业务优先的原则去设计结构。
-
注意:不是所有不遵循数据库范式的结构设计都被称为反范式,反范式设计是指自己知道会破坏范式,但对业务带来好处大于坏处时,刻意设计出破坏范式的结构。
数据库范式设计总结
-
经过一系列的阐述后,其实不难发现,越到后面的范式,越难令人理解,同时为了让表满足更高级别的范式,越往后付出代价也越大,而且拆分出的表数量也会越多
-
一般项目中仅需满足到第三范式或
BC
范式即可,因为这个度刚刚好,再往后就会因为过于精细化设计,导致整体性能反而下降。 -
控制到第三范式级别,一方面数据不会有太多冗余,第二方面也不会对性能影响过大。同时,如若打破范式的设定能对业务更有利,那也可以违背范式原则去设计。
-
生产项目中库表结构设计的是否合理,区别如下:
- 不合理的结构设计会造成的问题:
- 数据冗余,会浪费一定程度上的存储空间
- 不便于常规
SQL
操作(例如插入、删除),甚至会出现异常
- 合理的结构设计带来的好处:
- 节省空间,
SQL
执行时能节省内存空间,数据存储时能节省磁盘空间 - 数据划分较为合理,
DB
性能整体较高,并且数据也非常完整 - 结构便于维护和进行常规
SQL
操作
- 节省空间,
- 不合理的结构设计会造成的问题:
-
各范式之间的递进关系图:
-
范式概念:
- 第一范式:原子性,每个字段的值不能再分。
- 第二范式:唯一性,表内每行数据必须描述同一业务属性的数据。
- 第三范式:独立性,表中每个非主键字段之间不能存在依赖性。
- 巴斯范式:主键字段独立性,联合主键字段之间不能存在依赖性。
- 第四范式:表中字段不能存在多值依赖关系。
- 第五范式:表中字段的数据之间不能存在连接依赖关系。
- 域键范式:试图研究出一个库表设计时的终极完美范式。
MySQL数据库账户及授权
密码策略
- 从 MySQL 8.0开始,默认身份验证插件 从
mysql_native_password
更改为caching_sha2_password
。 - MySQL 5.7 的默认密码插件 一直以来都是
mysql_native_password
。拥有密码验证快的优点,无需在网络中发送实际密码,并且不需要加密的连接。然而,mysql_native_password 依赖于 SHA1 算法,但 NIST(美国国家标准与技术研究院)已建议停止使用 SHA1 算法,因为 SHA1 和其他哈希算法(例如 MD5)已被证明非常容易破解。 - 查看数据库当前密码策略:
bash
mysql> show variables like "%password%";
+----------------------------------------------+-----------------+
| Variable_name | Value |
+----------------------------------------------+-----------------+
| # 是否自动生成RSA密钥对文件
caching_sha2_password_auto_generate_rsa_keys | ON |
| # 哈希回合数
caching_sha2_password_digest_rounds | 5000 |
| # RSA 私钥文件
caching_sha2_password_private_key_path | private_key.pem |
| # RSA 公钥文件
caching_sha2_password_public_key_path | public_key.pem |
| # MySQL密码过期时间,单位为天
default_password_lifetime | 0 |
| # 超时断开
disconnect_on_expired_password | ON |
| # 随机密码长度
generated_random_password_length | 20 |
| # 是否支持代理用户控制认证插件
mysql_native_password_proxy_users | OFF |
| # 不允许用户使用最近n次使用过的密码
password_history | 0 |
| # 修改密码时是否需要提供当前用户使用的密码,OFF不需要,ON需要
password_require_current | OFF |
| # 不允许用户使用最近n天内使用过的密码
password_reuse_interval | 0 |
|
report_password | |
|
sha256_password_auto_generate_rsa_keys | ON |
|
sha256_password_private_key_path | private_key.pem |
|
sha256_password_proxy_users | OFF |
|
sha256_password_public_key_path | public_key.pem |
+----------------------------------------------+-----------------+
- 查看密码设置策略:
mysql
mysql> SHOW VARIABLES LIKE 'validate_password%';
Empty set (0.01 sec)
# 注意:若显示为空,则表示未安装插件
mysql> INSTALL COMPONENT 'file://component_validate_password';
Query OK, 0 rows affected (0.01 sec)
mysql> show variables like 'validate_password%';
+--------------------------------------+--------+
| Variable_name | Value |
+--------------------------------------+--------+
| # 是否能将密码设置成当前用户名
validate_password.check_user_name | ON |
| # 插件用于验证密码强度的字典文件路径,默认为空
validate_password.dictionary_file | |
| # 密码最小长度,默认为8,有最小值为4的限制
validate_password.length | 8 |
| # 密码至少要包含的小写字母和大写字母的个数
validate_password.mixed_case_count | 1 |
| # 密码至少要包含的数字个数
validate_password.number_count | 1 |
| # 密码强度检查等级
validate_password.policy | MEDIUM |
| # 密码必须包含的特殊字符个数
validate_password.special_char_count | 1 |
+--------------------------------------+--------+
7 rows in set (0.00 sec)
- 密码强度检查等级解释(validate_password.policy)
等级 | 检查对象 |
---|---|
0 or LOW | 检查长度 |
1 or MEDIUM | 检查长度、数字、大小写、特殊字符 |
2 or STRONG | 检查长度、数字、大小写、特殊字符、字典文件 |
- 设置密码强度检查参数:
bash
# 查看密码策略
mysql> show variables like 'validate_password.%';
# 设置密码验证强度检查策略
mysql> set global validate_password.policy=low; # 或0
# 设置至少要包含大/小写字母的个数
mysql> set global validate_password.mixed_case_count=0;
# 设置至少要包含数字的个数
mysql> set global validate_password.number_count=6;
# 设置至少包含特殊字符个数
mysql> set global validate_password.special_char_count=0;
# 设置密码长度
mysql> set global validate_password.length=6;
# 再次查看
mysql> show variables like 'validate_password.%';
+-------------------------------------------------+-------+
| Variable_name | Value |
+-------------------------------------------------+-------+
| validate_password.changed_characters_percentage | 0 |
| validate_password.check_user_name | ON |
| validate_password.dictionary_file | |
| validate_password.length | 6 |
| validate_password.mixed_case_count | 0 |
| validate_password.number_count | 6 |
| validate_password.policy | LOW |
| validate_password.special_char_count | 0 |
+-------------------------------------------------+-------+
8 rows in set, 1 warning (0.00 sec)
# 刷新权限,生效
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
- 修改密码:
mysql
# 查看root用户信息
mysql> select user, host, plugin from mysql.user;
+------------------+-----------+-----------------------+
| user | host | plugin |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session | localhost | caching_sha2_password |
| mysql.sys | localhost | caching_sha2_password |
| root | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
4 rows in set (0.00 sec)
# 注意:主机名为localhost,远程主机为%
mysql> alter user 'root'@'localhost' identified by '123456';
Query OK, 0 rows affected (0.01 sec)
# 修改完后刷新权限才能生效
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
登录账户管理
-
mysql8的账户权限管理原则:先创建账户,在赋予权限。
-
用户信息存放在 mysql数据库下的 user 表。
mysql
# 查看当前的用户信息
mysql> select user();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
mysql> use mysql;
Database changed
mysql> show tables;
mysql> desc user;
mysql> select user,host,authentication_string from user;
+------------------+-----------+------------------------------------------------------------------------+
| user | host | authentication_string |
+------------------+-----------+------------------------------------------------------------------------+
| mysql.infoschema | localhost | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| mysql.session | localhost | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| mysql.sys | localhost | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| root | localhost | $A$005$!*x/);h8Z!iF%o5HWRWyqUPd09P6PsTkRsktjW5GLxBdspO50tAVdTcN0 |
+------------------+-----------+------------------------------------------------------------------------+
4 rows in set (0.00 sec)
新建登录账户
- 格式:
mysql
create user 'username'@'localhost' identified by 'password';
- 含义:
- username: 创建的用户名。
- localhost: 指定该用户在哪个主机上可以登陆,如果是本地用户可用 localhost ,如果想让该用户可以从任意远程主机登陆,可以使用通配符 %。
- password: 该用户的登陆密码。
- 示例:
mysql
# 注意:密码要符合设置的密码规则
mysql> create user 'test1'@'localhost' identified by '123456';
# 查看信息
mysql> select user, host, plugin from mysql.user;
mysql> exit
Bye
# 使用 test1 账户登录
PS C:\Users\Administrator> mysql -u test1 -p
Enter password: ******
# 此时只能看到有限的库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
+--------------------+
2 rows in set (0.01 sec)
账户授权
-
作用:通过账户权限限制普通账户 的工作范围及内容,赋权原则如下:
- root账号绝对禁止允许任何IP都可以访问,即登录方式不能用%。
- 应用账号和管理账号要分离。
- 赋权最小化,即一般只给select权限,最好不要给update、insert等编辑权限。
- 密码设置合理。
- 定期清理不使用的账户,将其收回权限或删除。
-
常见的用户权限
-
查看权限
mysql
mysql> exit
Bye
# 返回到root用户
PS C:\Users\Administrator> mysql -u root -p
# 查看当前账户权限
mysql> show grants;
# 查看其它账户权限
mysql> show grants for 'test1'@'localhost';
+----------------------------------+
| Grants for test1@% |
+----------------------------------+
| GRANT USAGE ON *.* TO `test1`@`localhost` |
+----------------------------------+
1 row in set (0.00 sec)
# 上例显示test账户只有usage默认权限即连接登录的权限
- 赋权语法
mysql
grant 权限列表 on 数据库名.表名 to '用户名'@'来源地址' [identified by '密码'];
- 分析
- 权限列表: 用户的操作权限,如 SELECT , INSERT , UPDATE ,CREATE 等,如果要授予所有的权限则使用 ALL
- 数据库名: 数据库名,如果 * 代表所有数据库
- 表名:如果 * 代表所有数据表
- localhost: 指定该用户在哪个主机上可以登陆,如果是本地用户可用 localhost ,如果想让该用户可以从任意远程主机登陆,可以使用通配符 %
- 示例1:创建test1账户,赋权
mysql
# 使用root账户登录并赋予mysql库的查询权限
mysql> grant select on *.* to 'test1'@'localhost';
Query OK, 0 rows affected (0.01 sec)
mysql> show grants for 'test1'@'localhost';
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb1_test |
| mydb2_stuinfo |
| mydb3_employee |
| mydb4_product |
| mydb5_sales |
| mysql |
| performance_schema |
| student |
| sys |
+--------------------+
10 rows in set (0.00 sec)
# 查看user表的权限信息
mysql> select * from mysql.user where user='test1'\G
mysql> \q
Bye
PS C:\Users\Administrator> mysql -u test1 -p # 重新登录
Enter password: ******
mysql> show databases;
mysql> exit
Bye
- 示例2:创建test2账户,设置密码,赋权select和create权限,仅通过某个网段登录
mysql
PS C:\Users\Administrator> mysql -u root -p
Enter password: ******
# 需要查本机的IP网段
mysql> create user 'test2'@'10.100.170.%' identified by '123456';
mysql> select user, host, plugin from mysql.user;
mysql> show grants for 'test2'@'10.100.170.%';
mysql> grant select,create on *.* to 'test2'@'10.100.170.%';
mysql> show grants for 'test2'@'10.100.170.%';
mysql> exit
Bye
PS C:\Users\Administrator> mysql -u test2 -p123456 -h 10.100.170.198
mysql> exit
Bye
10.100.170.198
- 示例3:创建test3账户,设置密码,赋与所有权限,仅通过%登录,登录后创建test4账户并赋权
mysql
PS C:\Users\Administrator> mysql -u root -p
mysql> create user 'test3'@'%' identified by '123456';
mysql> select user, host, plugin from mysql.user;
mysql> show grants for 'test3'@'%';
mysql> grant all on *.* to 'test3'@'%';
mysql> show grants for 'test3'@'%';
mysql> exit
Bye
PS C:\Users\Administrator> mysql -u test3 -p123456
mysql> create database mydbx_temp1;
mysql> create user 'test4'@'%' identified by '123456';
mysql> select user, host, plugin from mysql.user;
mysql> show grants for 'test4'@'%'; # 查看test4账户权限
mysql> select user(); # 查看当前登录的账户
mysql> grant select on *.* to 'test4'@'%'; # 被拒绝,无权给test4账户赋权
ERROR 1045 (28000): Access denied for user 'test3'@'%' (using password: YES)
# 注意:all所有权限中不包含给账户赋权的权限grant
mysql> exit
Bye
# 登录root账户给test3账户赋与给别的账户赋权的权限
PS C:\Users\Administrator> mysql -u root -p
mysql> grant all on *.* to 'test3'@'%' with grant option; # 给test3添加赋权的权限
mysql> exit
Bye
PS C:\Users\Administrator> mysql -u test3 -p123456 # 登录test3账户
mysql> grant select on *.* to 'test4'@'%'; # 给test4赋权
Query OK, 0 rows affected (0.01 sec)
- 注意:若赋权不成功则先给root账户增加system_user权限
mysql
# 给root赋权system_user权限
mysql> grant system_user on *.* to 'root'@'localhost';
# 注意:登录主机是%还是localhost
回收权限
- 格式:
bash
revoke 权限列表/all on 库名.表名 from '用户名'@'来源地址';
# revoke跟grant 的语法差不多,只需要把关键字 "to" 换成 "from" 即可
- 示例4:回收所有权限
mysql
mysql> select user();
+-----------------+
| user() |
+-----------------+
| test3@localhost |
+-----------------+
mysql> exit
Bye
PS C:\Users\Administrator> mysql -u root -p
mysql> select user, host, plugin , select_priv from mysql.user;
# select_priv查询权限
mysql> show grants for 'test4'@'%'; # 查看test4账户的权限
mysql> revoke select on *.* from 'test4'@'%'; # 回收select权限
mysql> show grants for 'test4'@'%';
mysql> revoke all on *.* from 'test3'@'%'; # 回收所有权限
mysql> show grants for 'test3'@'%';
mysql> revoke all on *.* from 'test2'@'10.100.170.%'; # 同上
mysql> show grants for 'test2'@'10.100.170.%';
mysql> revoke all on *.* from 'test1'@'localhost';
mysql> show grants for 'test1'@'localhost';
删除账户
- 格式:
bash
drop user '用户名'@'访问主机名';
- 示例5:删除所有账户
mysql
mysql> select user, host from mysql.user;
mysql> drop user 'test1'@'localhost';
Query OK, 0 rows affected (0.01 sec)
mysql> drop user 'test2'@'10.100.170.%';
Query OK, 0 rows affected (0.01 sec)
mysql> drop user test3; # 注意:主机为%可以不写
Query OK, 0 rows affected (0.01 sec)
mysql> drop user test4;
Query OK, 0 rows affected (0.00 sec)
mysql> select user, host from mysql.user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
4 rows in set (0.00 sec)
建表
mysql
# 登录root用户
C:\Users\13573>mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.37 MySQL Community Server - GPL
# 创建数据库
mysql> create database mydb6_product;
Query OK, 1 row affected (0.01 sec)
mysql> use mydb6_product;
Database changed
# 创建三张表
mysql> create table employees(
-> id int primary key,
-> name varchar(50) not null,
-> age int not null,
-> gender varchar(10) not null default 'unknown',
-> salary float
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> create table orders(
-> id int primary key,
-> name varchar(100) not null,
-> price float not null,
-> quantity int not null,
-> category varchar(50)
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> create table invoices(
-> number int primary key auto_increment,
-> order_id int not null,
-> in_date date,
-> total_amount float, check(total_amount>0),
-> foreign key(order_id) references orders(id)
-> );
Query OK, 0 rows affected (0.02 sec)