MySQL 8 库表操作学习笔记:SQL 基础、库表管理、约束与用户授权全流程

目录

  • 一、SQL 语句基础
  • 二、数据库操作
  • 三、字符集与字符序
  • 四、数据库对象与命名规范
  • 五、表的基本操作
  • 六、表的约束
  • 七、存储引擎与完整建表语句
  • 八、数据库账户与权限管理
  • 九、综合练习
  • 十、常见报错与命令速查

一、SQL 语句基础

1.1 什么是 SQL

SQL(Structured Query Language,结构化查询语言)是在关系型数据库上执行数据操作、数据检索、数据维护的标准语言。使用 SQL,程序员和数据库管理员可以完成:

  • 改变数据库的结构;
  • 更改系统的安全设置;
  • 增加用户对数据库或表的许可权限;
  • 在数据库中检索需要的信息;
  • 对数据库的信息进行更新。

1.2 SQL 语句分类

MySQL 致力于支持全套 ANSI/ISO 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

记忆技巧:DDL 改结构、DML 改数据、DCL 管权限、TCL 管事务。

1.3 SQL 语句的书写规范

  1. SQL 关键字不区分大小写 (建议统一大写),但字符串常量区分大小写;
  2. SQL 语句可单行或多行书写,以英文分号 ; 结尾;
  3. 关键字不能跨多行书写,也不能简写;
  4. 用空格和缩进来提高语句的可读性;
  5. 注释写法:
    • 多行注释:/* 注释内容 */
    • 单行注释:-- 注释内容(-- 后必须有空格)或 # 注释内容
sql 复制代码
-- 这是一个单行注释
/* 这是
   多行注释 */
SELECT NOW();   # 查看当前时间

二、数据库操作

2.1 数据库的登录与退出

MySQL 服务需要先启动,否则客户端连接会报 ERROR 2002:

bash 复制代码
[root@server ~]# systemctl start mysqld
[root@server ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.0.37 MySQL Community Server - GPL
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

登录格式:

bash 复制代码
mysql -u用户名 -h服务器主机地址 -p密码
参数 含义 说明
-u 登录用户名 例如 root
-h 服务器主机地址 本机可省略,或写 localhost / IP
-p 用户密码 -p 与密码之间不能有空格 ,否则密码会被当成数据库名;不写密码时只写 -p,回车后再输入

登录成功后的提示信息含义:

  • Commands end with ; or \g:命令以 ; 或 \g 结束,遇到结束符才开始执行;
  • Your MySQL connection id is 16:当前是第几次连接;
  • Server version: 8.0.37 ...:MySQL 服务器版本;
  • Type 'help;' or '\h' for help:输入 help; 或 \h 查看帮助;
  • Type '\c' to clear the current input statement:输入 \c 清除当前正在输入的命令(注意不是清屏)。

若服务未启动,会出现:

text 复制代码
ERROR 2002 (HY000): Can't connect to local MySQL server through socket
'/var/lib/mysql/mysql.sock' (2)

退出 MySQL 有三种方式:

sql 复制代码
exit
quit
\q

小提示:命令行直接写密码 mysql -uroot -p123456 会提示 Using a password on the command line interface can be insecure,生产环境不建议这样做。

2.2 查看数据库

sql 复制代码
SHOW DATABASES;
SHOW DATABASES [LIKE '条件'];

MySQL 安装后自带的 4 个系统库:

数据库 作用
information_schema 数据字典,存储用户表信息、列信息、权限信息、字符集信息、分区信息等
performance_schema 存储数据库服务器的性能参数
mysql 存储系统的用户权限信息及帮助信息
sys MySQL 5.7 新增,通过视图把 information_schema 与 performance_schema 整合,查询更直观

LIKE 支持通配符:

  • %:匹配任意零个或多个字符;
  • _:匹配任意单个字符。
sql 复制代码
mysql> SHOW DATABASES LIKE 'sys';
mysql> SHOW DATABASES LIKE 's%';
mysql> SHOW DATABASES LIKE '__sql';   # 匹配 mysql

常用系统函数:

sql 复制代码
mysql> SELECT NOW();       # 当前时间
mysql> SELECT VERSION();   # 数据库版本
mysql> SELECT USER();      # 当前登录用户及主机
+----------------+
| user()         |
+----------------+
| root@localhost |
+----------------+

2.3 创建数据库

sql 复制代码
CREATE DATABASE 数据库名;
CREATE DATABASE IF NOT EXISTS 数据库名;   -- 推荐写法

示例:

sql 复制代码
mysql> CREATE DATABASE testdb;
Query OK, 1 row affected (0.00 sec)

mysql> CREATE DATABASE testdb;
ERROR 1007 (HY000): Can't create database 'testdb'; database exists

查看建库语句:

sql 复制代码
mysql> SHOW CREATE DATABASE testdb \G
*************************** 1. row ***************************
       Database: testdb
Create Database: CREATE DATABASE `testdb` /*!40100 DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */

这条语句可以分为 3 段理解:

  1. CREATE DATABASE \testdb``:创建数据库 testdb;
  2. /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */:字符集使用 utf8mb4(1~4 字节,可存 emoji),比较规则 utf8mb4_0900_ai_ci 中 ai 表示不区分重音、ci 表示不区分大小写;
  3. /*!80016 DEFAULT ENCRYPTION='N' */:数据库未加密。

关于反引号:

  • 只有保留关键字和特殊字符才必须用反引号;
  • 普通表名、列名可加可不加,但为了代码规范建议统一;
  • 反引号可以避免与 SQL 关键字冲突:
sql 复制代码
mysql> CREATE DATABASE database;
ERROR 1064 (42000): You have an error in your SQL syntax; ... near 'database' at line 1

mysql> CREATE DATABASE `database`;
Query OK, 1 row affected (0.01 sec)

注意:创建数据库、查看建库语句时用的是 DATABASE(没有 s),而查看所有库时是 SHOW DATABASES(有 s)。

2.4 切换数据库

sql 复制代码
USE 数据库名;
SELECT DATABASE();   -- 查看当前使用的数据库

示例:

sql 复制代码
mysql> USE testdb;
Database changed

mysql> SELECT DATABASE();
+------------+
| database() |
+------------+
| testdb     |
+------------+

未选择任何数据库时,SELECT DATABASE() 返回 NULL。

2.5 删除数据库

sql 复制代码
DROP DATABASE 数据库名;
DROP DATABASE IF EXISTS 数据库名;   -- 推荐
sql 复制代码
mysql> DROP DATABASE testdb;
Query OK, 0 rows affected (0.01 sec)

删除数据库会同时删除库中所有表和数据,生产环境务必先备份、并确认不在使用。

2.6 数据库操作小结

操作 命令
创建数据库 CREATE DATABASE 数据库名;
设为当前数据库 USE 数据库名;
查看当前数据库 SELECT DATABASE();
显示所有数据库 SHOW DATABASES;
删除数据库 DROP DATABASE 数据库名;

三、字符集与字符序

3.1 字符集(Character Set)

字符集是字符的编码规则,规定了字符在数据库中的存储格式,例如占用多少空间、支持哪些字符。字符集选错,轻则影响性能,重则导致数据存储乱码。

  • MySQL 5.7 默认字符集是 latin1;
  • MySQL 8.0 默认字符集是 utf8mb4;
  • 8.0 中建库建表、应用程序连接尽可能统一使用 utf8mb4(支持 emoji)。

字符集选型建议:

  • 面向国外业务、需要处理多国语言:选 utf8mb4(或 utf8);
  • 只需要支持中文、对性能敏感:可选 GBK;
  • MySQL 中的 utf8 实际是 utf8mb3 的别名,不推荐使用。

常见字符集对比:

字符集 说明
latin1 支持西欧字符、希腊字符等
gbk 支持中文简体,但不是国际通用字符集
big5 支持中文繁体
utf8 几乎支持世界所有国家字符,最多 3 字节
utf8mb4 完全兼容 UTF-8,用 4 字节存储更多字符(含 emoji)

3.2 字符序(Collation)

字符序是字符排序的规则集合 ,主要影响字符串比较与排序结果。例如 A > B > a > b 和 a > b > A > B 就是两种不同的排序规则。

MySQL 字符序的命名规则:

  • 以对应字符集名称开头;
  • 中间是国家名(或以 general 表示通用);
  • 后缀含义:
后缀 含义
bin 二进制比较
ci 大小写不敏感(case insensitive)
cs 大小写敏感(case sensitive)
ai 口音不敏感(accent insensitive)
as 口音敏感(accent sensitive)
ks 假名敏感(kanatype sensitive)

例如 utf8mb4_0900_ai_ci:字符集 utf8mb4、Unicode 9.0 规则、不区分重音、不区分大小写。

3.3 查看字符集与字符序

sql 复制代码
SHOW CHARACTER SET;                 -- 查看所有支持的字符集
SHOW CHARACTER SET LIKE 'gbk';      -- 查看指定字符集
SHOW CHARACTER SET LIKE 'utf%';

SHOW COLLATION;                     -- 查看所有字符序
SHOW COLLATION LIKE 'utf8mb4%';

SHOW CHARACTER SET 字段含义:

字段 含义
Charset 字符集名称
Description 简单描述
Default collation 该字符集的默认字符序
Maxlen 该字符集中字符的最大存储长度(字节)

SHOW COLLATION 字段含义:

字段 含义
Collation 字符序名称
Charset 关联的字符集
Id 字符序 ID
Default 是否为该字符集的默认字符序
Compiled 是否已编译进服务器
Sortlen 排序所需内存量相关
Pad_attribute 比较时是否考虑末尾 padding

3.4 查看当前字符集设置

sql 复制代码
SHOW VARIABLES LIKE 'character_set%';
变量 含义
character_set_client 客户端字符集
character_set_connection 通信链路字符集,客户端请求以此编码
character_set_database 数据库默认字符集(重要)
character_set_filesystem 文件系统字符集,固定为 binary
character_set_results 服务器返回结果使用的字符集
character_set_server 服务器默认字符集(重要)
character_set_system 存储元数据使用的字符集

3.5 utf8 与 utf8mb4 的区别

MySQL 5.5.3 之后新增 utf8mb4,mb4 即 most bytes 4 ,专门兼容 4 字节 Unicode。utf8mb4 是 utf8 的超集。

  • MySQL 的 utf8 最大只支持 3 字节 ,三个字节最多编码到 0xFFFF,即 Unicode 的基本多文种平面(BMP);
  • 不在 BMP 中的字符(如 emoji、部分生僻汉字)无法用 utf8 存储,插入会报错或乱码;
  • 只改编码为 utf8mb4 即可,无需做其他转换;一般情况下用 utf8 也够,但 8.0 之后建议直接使用 utf8mb4。

四、数据库对象与命名规范

4.1 数据库对象的组成

MySQL 数据库对象包括:数据库(database)、表(table)、视图(view)、索引(index)、存储过程/函数(procedure/function)、触发器(trigger)、事件(event)等。

4.2 命名规则

  1. 使用有意义的英文词汇,单词之间用下划线分隔;
  2. 名称由字母、数字、#、下划线、$ 组成,必须以英文字母开头;
  3. 不要使用 MySQL 保留字;
  4. 所有数据库对象统一小写(MySQL 可设置大小写敏感,统一小写最稳妥);
  5. 同一个对象集合内不能重名;
  6. 命名尽量简短且能表达含义。

4.3 生产环境命名规范

数据库:

  • 命名尽量不超过 30 个字符;
  • 一般为「项目名称 + 库含义简写」,例如 IM 项目的工作流库:im_flow;
  • 统一小写。

表:

类型 规则 示例
常规表 t_ + 模块简写 + 表含义简写 用户模块教育信息表:t_user_eduinfo
临时表 temp_ + 模块 + 表 + 日期后缀 temp_user_eduinfo_20240520
备份表 bak_ + 模块 + 表 + 日期后缀 bak_user_eduinfo_20231219
  • 同一模块的表尽量使用相同前缀;
  • 多个单词用下划线分隔;
  • 常规表名尽量不超过 30 个字符,临时表/备份表视情况尽量简短;
  • 统一小写。

五、表的基本操作

5.1 MySQL 数据类型

数据类型是建表的基础,选型是否合理直接影响存储空间和查询性能。MySQL 数据类型分为:数字、文本、日期/时间三大类。

5.1.1 整型
类型 字节数 有符号范围(默认) 无符号范围(UNSIGNED)
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 ~ 18446744073709551615

选型建议:为合适的列选择合适的数据类型 。例如一个只有 0/1 的枚举字段,用 TINYINT 就够,若用 BIGINT 就浪费了 7 字节;按 100 万行计算,约浪费 7MB,表多了浪费更可观。

关于 INT(N):

  • N 只是显示宽度 ,与存储无关,INT 永远占 4 字节;
  • 不足宽度补 0,超过宽度则完整显示;
  • MySQL 8.0.17 之后已不推荐这种写法。
5.1.2 浮点型
类型 字节数 说明
FLOAT 4 单精度浮点型
DOUBLE 8 双精度浮点型

可以写成 FLOAT(M,D) / DOUBLE(M,D) 限制总位数 M 和小数位数 D(例如 FLOAT(3,2));不指定时按实际精度处理。

5.1.3 定点型

DECIMAL(size,d) 以字符串形式存储,不会出现精度丢失 。FLOAT/DOUBLE 存储的是近似值,可能出现「写入的值」和「查出来的值」不一致:

sql 复制代码
mysql> CREATE TABLE t1(float_num FLOAT(10,2), double_num DOUBLE(20,2), decimal_num DECIMAL(20,2));
mysql> INSERT INTO t1 VALUES (1234567.66, 1234567899000000.66, 123456789000000.66);
mysql> SELECT * FROM t1;
+------------+---------------------+--------------------+
| float_num  | double_num          | decimal_num        |
+------------+---------------------+--------------------+
| 1234567.62 | 1234567899000000.80 | 123456789000000.66 |
+------------+---------------------+--------------------+

可以看到 FLOAT/DOUBLE 发生了精度丢失,而 DECIMAL 没有。因此银行、互联网金融等对小数敏感的系统应使用 DECIMAL。

5.1.4 字符串类型
类型 说明
CHAR(size) 固定长度字符串,0 ~ 255 个字符,不足补空格,取出时去掉尾部空格
VARCHAR(size) 可变长度字符串,最大 65535 字节(受行长度和字符集限制)
TINYTEXT 最大 255 字节的文本
TEXT 最大 65535 字节的文本
MEDIUMTEXT 最大 16777215 字节的文本
LONGTEXT 最大 4294967295 字节的文本
TINYBLOB / BLOB / MEDIUMBLOB / LONGBLOB 二进制大对象,容量与对应 TEXT 相同
ENUM(x,y,z,...) 枚举,最多 65535 个值,只能取列表中的一个
SET(x,y,z,...) 集合,最多 64 个列表项,可存多个值

CHAR 与 VARCHAR 的选择:

  • CHAR 适合固定长度内容:手机号、身份证号、性别等,查询效率高;
  • VARCHAR 适合长度不固定内容:姓名、地址、备注等,更节省空间;
  • 简单记忆:CHAR 定长、VARCHAR 变长;名字、地址用 VARCHAR,编码类用 CHAR。

TEXT 与 BLOB 的区别:

  • TEXT 以字符形式存储,有字符集和排序规则,适合存文章内容、评论等;
  • BLOB 以二进制形式存储,没有字符集和排序规则,适合存图片、文件等二进制数据。
5.1.5 日期/时间类型
类型 字节数 格式 说明
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 日期 + 时间,可作时间戳(受时区影响)

常用结论:

  • 只需要日期用 DATE,需要精确到秒用 DATETIME;
  • TIMESTAMP 占 4 字节、受时区影响,适合记录「最后更新时间」;
  • 金额、数量等精确数值不要用浮点型。

5.2 创建表

语法:

sql 复制代码
CREATE TABLE [IF NOT EXISTS] 表名 (
    列名1 列类型1 [约束],
    列名2 列类型2 [约束],
    ...
    [表级约束]
) [ENGINE=存储引擎] [DEFAULT CHARSET=字符集];

注意事项:

  • 表默认创建在当前数据库中,建表前必须先用 USE 数据库名; 选择数据库,否则报 No database selected;
  • 表名不区分大小写,但不能使用 SQL 关键字(如 DROP、ALTER、INSERT);
  • 必须为每一列指定名称和数据类型,多列之间用逗号分隔。

示例:创建学生表

sql 复制代码
mysql> CREATE DATABASE mydb2_stuinfo;
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> 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)

示例:创建员工表

sql 复制代码
mysql> CREATE DATABASE mydb3_employee;
mysql> USE mydb3_employee;
mysql> CREATE TABLE tb1(id INT, name VARCHAR(25), salary FLOAT);
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> SHOW TABLES;
+--------------------------+
| Tables_in_mydb3_employee |
+--------------------------+
| tb1                      |
+--------------------------+

5.3 查看表

sql 复制代码
SHOW TABLES;                                    -- 查看当前库的所有表
SHOW TABLES FROM 数据库名;                       -- 查看指定库的表
SHOW TABLES LIKE 'student%';                    -- 按条件过滤

DESC 表名;                                       -- 查看表结构(推荐)
DESCRIBE 表名;
SHOW COLUMNS FROM 表名;                          -- 等价写法

SHOW CREATE TABLE 表名 \G                        -- 查看完整建表语句

DESC 输出字段含义:

字段 含义
Field 字段名称
Type 字段类型
Null 是否允许为空(YES/NO)
Key 索引类型(PRI 主键、UNI 唯一、MUL 普通索引)
Default 默认值
Extra 附加信息,如 auto_increment

SHOW CREATE TABLE 可以看到存储引擎、字符集、注释等完整定义:

sql 复制代码
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

5.4 删除表

sql 复制代码
DROP TABLE [IF EXISTS] 表名;
sql 复制代码
mysql> DROP TABLE tb1;
Query OK, 0 rows affected (0.01 sec)

mysql> DROP TABLE IF EXISTS tb1;    -- 推荐写法,表不存在也不报错
Query OK, 0 rows affected (0.01 sec)

删除表前务必确认:

  1. 数据已备份,避免误删丢失;
  2. 表没有被其他表通过外键引用;
  3. 表数据确实不再需要;
  4. 相关程序已停止使用该表,避免影响业务。

5.5 修改表(ALTER TABLE)

5.5.1 修改表名
sql 复制代码
-- 方式一
ALTER TABLE 旧表名 RENAME 新表名;
-- 方式二
RENAME TABLE 旧表名 TO 新表名;
sql 复制代码
mysql> ALTER TABLE student2 RENAME student3;
Query OK, 0 rows affected (0.01 sec)

mysql> RENAME TABLE student3 TO teacher1;
Query OK, 0 rows affected (0.01 sec)
5.5.2 新增列
sql 复制代码
ALTER TABLE 表名 ADD 新列名 列类型 [AFTER 列名 | FIRST];
  • AFTER 列名:在指定列之后插入(没有 BEFORE 关键字);
  • FIRST:插入到第一列;
  • 不写位置时默认追加到最后一列。
sql 复制代码
mysql> ALTER TABLE student1 ADD password CHAR(8);
Query OK, 0 rows affected (0.01 sec)

mysql> ALTER TABLE student1 ADD notes VARCHAR(30) AFTER age;
mysql> ALTER TABLE student1 ADD aa INT FIRST;
5.5.3 删除列
sql 复制代码
ALTER TABLE 表名 DROP 列名;

mysql> ALTER TABLE student1 DROP notes;
mysql> ALTER TABLE student1 DROP aa;
5.5.4 修改列名
sql 复制代码
ALTER TABLE 表名 CHANGE 旧列名 新列名 列类型;

注意 CHANGE 必须同时写上列类型,否则会语法报错;它也可以同时修改列名和类型。

sql 复制代码
mysql> ALTER TABLE student1 CHANGE password passwd CHAR(8);
5.5.5 修改列类型
sql 复制代码
ALTER TABLE 表名 MODIFY 列名 新列类型;
sql 复制代码
mysql> ALTER TABLE student1 ADD birthday CHAR(10);
mysql> ALTER TABLE student1 MODIFY birthday DATE;    -- 字符型改为日期型
5.5.6 修改列位置
sql 复制代码
ALTER TABLE 表名 MODIFY 列名 列类型 AFTER 某列;
ALTER TABLE 表名 MODIFY 列名 列类型 FIRST;

小结:ADD 加列、DROP 删列、CHANGE 改列名、MODIFY 改类型/位置。

5.6 复制表

方式 语法 结果
只复制结构 CREATE TABLE 新表 LIKE 源表; 结构完全一致,不含数据
结构 + 数据 CREATE TABLE 新表 SELECT * FROM 源表; 有数据,但主键、自增、索引等可能丢失
只复制数据 INSERT INTO 新表 SELECT * FROM 源表; 需先建好结构相同的表
sql 复制代码
-- 1. 只复制表结构
mysql> CREATE TABLE student2 LIKE student1;
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT * FROM student2;
Empty set (0.00 sec)          # 只有结构,没有数据

-- 2. 复制表结构 + 数据
mysql> CREATE TABLE student3 SELECT * FROM student1;
Query OK, 0 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

-- 3. 只复制数据(先建好同结构表)
mysql> INSERT INTO student2 SELECT * FROM student1;
Query OK, 2 rows affected (0.00 sec)

5.7 数据字典 information_schema

数据字典类似于「系统编目 / 花名册」,保存数据库服务器的元数据(meta data,即「关于数据的数据」),包括库、表、字段、视图、用户、统计等属性信息。

information_schema 是 MySQL 自带库,提供访问元数据的方式,常用表:

表 说明
TABLES 所有数据表及所属数据库
SCHEMATA 所有数据库信息
COLUMNS 所有列信息
VIEWS 所有视图信息
TRIGGERS 所有触发器
ROUTINES 所有存储过程和函数
KEY_COLUMN_USAGE 主外键信息
TABLE_CONSTRAINTS 所有约束
STATISTICS 索引信息
sql 复制代码
mysql> USE information_schema;
mysql> SHOW TABLES;
mysql> SELECT TABLE_NAME, TABLE_COMMENT FROM TABLES WHERE TABLE_SCHEMA='mydb2_stuinfo';

通过 information_schema 可以了解整个 MySQL 实例的运行情况,用于查询元数据、优化调优、维护数据库。

5.8 建表练习

创建商品数据库 mydb4_product,建商品表 pro_tb1:

  1. 字段:编号 num INT、商品名 trade_name VARCHAR(30)、数量 number INT、单价 price FLOAT(5,2);
  2. 显示建表字段内容;
  3. 新增一列备注 notes VARCHAR(30) 放在最后一列;
  4. 将编号 num 类型改为 CHAR(4);
  5. 删除该表(先判断是否存在)。
sql 复制代码
mysql> CREATE DATABASE mydb4_product;
mysql> USE mydb4_product;
mysql> CREATE TABLE pro_tb1(num INT, trade_name VARCHAR(30), number INT, price FLOAT(5,2));
mysql> DESC pro_tb1;

mysql> ALTER TABLE pro_tb1 ADD notes VARCHAR(30);
mysql> DESC pro_tb1;

mysql> ALTER TABLE pro_tb1 MODIFY num CHAR(4);
mysql> DESC pro_tb1;

mysql> DROP TABLE IF EXISTS pro_tb1;

六、表的约束

6.1 为什么需要约束

数据类型本身对字段的约束很单一,很多业务规则无法表达:

  • 字段是否可以为 NULL、有没有默认值;
  • 字段能否重复(如身份证号、学号必须唯一);
  • 数值的取值范围(如年龄 0~120)。

约束(Constraint) 是在表上强制执行的数据校验规则,本质是 MySQL 通过限制用户操作来维护数据安全与完整性的一套方案。约束作为数据库对象存放在系统表中,也有自己的名字。

数据完整性主要从四个方面考虑:

完整性 含义 示例
实体完整性 不能存在两条完全相同的记录 主键
域完整性 字段取值在合理范围内 年龄 0~120、性别「男/女」
引用完整性 外键引用的数据必须存在 学生所在班级必须在班级表中存在
用户自定义完整性 业务规则 用户名唯一、密码不能为空

常见约束:非空(NOT NULL)、默认值(DEFAULT)、主键(PRIMARY KEY)、外键(FOREIGN KEY)、唯一(UNIQUE)、检查(CHECK)。

创建时机:建表时创建、建表后通过 ALTER TABLE 追加。约束可定义在列级 或表级。

6.2 约束语法

列级约束(定义列的同时定义约束):

sql 复制代码
CREATE TABLE 表名 (列名 类型 约束);
ALTER TABLE 表名 MODIFY 列名 列类型 列约束;          -- 添加
ALTER TABLE 表名 MODIFY 列名 列类型;                 -- 不加约束即删除

表级约束(所有列定义完之后定义):

sql 复制代码
CREATE TABLE 表名 (列信息..., CONSTRAINT 约束名 约束类型(要约束的列));
ALTER TABLE 表名 ADD [CONSTRAINT 约束名] 约束类型(要约束的列);   -- 添加
ALTER TABLE 表名 DROP 约束类型 约束名;                             -- 删除

约束命名推荐:表名_列名_约束类型简介,例如 t_user_id_pk。

6.3 非空约束(NOT NULL)

作用:限定某列的值不允许为空。取值只有 NULL(默认)和 NOT NULL。

  • 所有数据类型的值都可以是 NULL;
  • 空字符串 '' 不等于 NULL,数字 0 也不等于 NULL;
  • 实际开发中尽量保证字段非空,因为 NULL 无法参与运算。
sql 复制代码
mysql> CREATE TABLE myclass1(
    -> class_name VARCHAR(20) NOT NULL,
    -> class_room VARCHAR(20) NOT NULL,
    -> class_id INT);

mysql> INSERT INTO myclass1 (class_room) VALUES ('计科1');
ERROR 1364 (HY000): Field 'class_name' does not have a default value

mysql> INSERT INTO myclass1 (class_name, class_room) VALUES ('A104', '计科1');
Query OK, 1 row affected (0.00 sec)

已有表添加/删除非空约束:

sql 复制代码
mysql> ALTER TABLE student1 MODIFY id INT NOT NULL;        -- 添加
mysql> ALTER TABLE student1 MODIFY id INT NULL;           -- 删除(NULL 可省略)

6.4 默认值约束(DEFAULT)

作用:给字段指定默认值,插入数据时若该字段没有显式赋值,则自动填充默认值。

sql 复制代码
mysql> CREATE TABLE teacher1(
    -> id INT NOT NULL,
    -> name VARCHAR(30) NOT NULL,
    -> sex CHAR(2) DEFAULT '女');

mysql> INSERT INTO teacher1(id, name) VALUES (1001, '林雪');
mysql> SELECT * FROM teacher1;
+------+--------+------+
| id   | name   | sex  |
+------+--------+------+
| 1001 | 林雪   | 女   |
+------+--------+------+

表已存在时添加默认值:

sql 复制代码
mysql> ALTER TABLE student1 MODIFY sex CHAR(2) DEFAULT '女';

注意:如果一个字段同时设置了 NOT NULL 和 DEFAULT,插入时不赋值会使用默认值,此时 NOT NULL 实际不会生效(因为永远有值)。

6.5 列描述(COMMENT)

列描述只起说明作用,会被保存在建表语句中,相当于 C/C++ 的注释,方便查看字段含义。

sql 复制代码
mysql> CREATE TABLE myclass2(
    -> class_name VARCHAR(20) NOT NULL COMMENT '教室',
    -> class_room VARCHAR(20) DEFAULT '计科2');

mysql> SHOW CREATE TABLE myclass2 \G
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

6.6 主键约束(PRIMARY KEY)

作用:唯一标识表中的一行记录。主键是最常用的约束。

特点:

  • 主键字段不能为空、不能重复;
  • 一张表最多只能有一个主键;
  • 主键列通常是整数类型;
  • 创建主键时,MySQL 会在该列上自动建立主键索引,删除主键约束时对应索引自动删除;
  • 不要修改主键字段的值,否则可能破坏数据完整性。

建表时创建主键:

sql 复制代码
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  |     | 男      |       |
+-------+--------------+------+-----+---------+-------+

mysql> INSERT INTO t1 VALUES (1, '孙文', '女');
mysql> INSERT INTO t1(id, name) VALUES (1, '黎明');
ERROR 1062 (23000): Duplicate entry '1' for key 't1.PRIMARY'

建表后追加主键(该列有重复值时会失败,需先去重):

sql 复制代码
mysql> ALTER TABLE teacher1 ADD PRIMARY KEY(id);

删除主键:

sql 复制代码
ALTER TABLE 表名 DROP PRIMARY KEY;

复合主键:多个字段联合起来作为唯一标识,单个字段可以重复,只要组合不冲突即可。

sql 复制代码
mysql> CREATE TABLE t2 (
    -> id INT,
    -> hostname VARCHAR(10),
    -> ip VARCHAR(20),
    -> port INT UNSIGNED,
    -> PRIMARY KEY(ip, port));

mysql> INSERT INTO t2 VALUES (1, 'node1', '192.168.48.2', 120);
mysql> INSERT INTO t2 VALUES (2, 'node2', '192.168.48.3', 120);   -- 单个字段重复,OK
mysql> INSERT INTO t2 VALUES (3, 'node3', '192.168.48.2', 120);   -- 组合冲突
ERROR 1062 (23000): Duplicate entry '192.168.48.2-120' for key 't2.PRIMARY'

6.7 主键自增长(AUTO_INCREMENT)

作用:给主键自动生成递增的数值,通常与主键搭配作为逻辑主键。

规则:

  • 自增长字段必须是整数;
  • 可以不设置初始值,默认从 1 开始递增;
  • 被自增长的字段必须作为主键或唯一键(索引);
  • 一张表最多只能有一个自增长列;
  • 也可以手动插入不自增的值,之后从当前最大值继续递增。
sql 复制代码
mysql> ALTER TABLE student1 ADD PRIMARY KEY(id);
mysql> ALTER TABLE student1 MODIFY id INT AUTO_INCREMENT;
Query OK, 3 rows affected (0.05 sec)

mysql> DESC student1;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int          | NO   | PRI | NULL    | auto_increment |
+----------+--------------+------+-----+---------+----------------+

mysql> INSERT INTO student1(name) VALUES ('关六');   -- 不写 id,自动生成

指定自增起始值:

sql 复制代码
mysql> CREATE TABLE t3 (
    -> id INT PRIMARY KEY AUTO_INCREMENT,
    -> systemname VARCHAR(10) NOT NULL
    -> ) AUTO_INCREMENT = 100;

mysql> INSERT INTO t3(systemname) VALUES ('windows'), ('linux');
mysql> SELECT * FROM t3;
+-----+------------+
| id  | systemname |
+-----+------------+
| 100 | windows    |
| 101 | linux      |
+-----+------------+

6.8 唯一性约束(UNIQUE)

作用:保证某列的值不能重复。一张表只能有一个主键,但可以设置多个唯一键。

主键与唯一键的关系:

  • 主键更多用于标识 一行数据,唯一键更多用于业务唯一性;
  • 主键只能有一个,唯一键可以有多个;
  • 主键不能为空,唯一键可以为空(且允许多个 NULL);
  • 二者是补充关系,可以同时存在;
  • 例如学生表:身份证号做主键,学号做唯一键。
sql 复制代码
mysql> CREATE TABLE t4(
    -> id INT PRIMARY KEY,
    -> name VARCHAR(20) UNIQUE COMMENT '名字不能重名,可以为空');

mysql> INSERT INTO t4 VALUES (1, '刘文');
mysql> INSERT INTO t4 VALUES (2, '刘文');
ERROR 1062 (23000): Duplicate entry '刘文' for key 't4.name'

唯一键冲突会导致自增字段不连续:

sql 复制代码
mysql> ALTER TABLE t4 MODIFY id INT AUTO_INCREMENT;
mysql> INSERT INTO t4(name) VALUES ('张磊磊');
mysql> INSERT INTO t4(name) VALUES ('张磊磊');   -- 冲突失败,但自增值已消耗
ERROR 1062 (23000): Duplicate entry '张磊磊' for key 't4.name'

mysql> INSERT INTO t4(name) VALUES ('钱明');
mysql> SELECT * FROM t4;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 刘文      |
|  2 | 张磊      |
|  3 | 张磊磊    |
|  5 | 钱明      |     # 4 被失败的那次占用,故不连续
+----+-----------+

6.9 外键约束(FOREIGN KEY)

作用:限定某表的某字段引用另一张表的字段,保证引用完整性。

概念:

  • 主表(父表):被引用的表;
  • 从表(子表):引用别人的表;
  • 外键:从表中的字段引用主表的主键或唯一键;
  • 引用键:主表被引用的字段。

要求:

  • 主表必须已存在(或自参照);
  • 主表被引用列必须有主键或唯一键约束;
  • 外键列的数据类型必须与主表对应列一致;
  • 外键列可以为 NULL(表示暂未关联);
  • 外键列数据必须在主表中存在,或为 NULL。

语法:

sql 复制代码
FOREIGN KEY (从表字段) REFERENCES 主表名(主表字段)

示例:

sql 复制代码
-- 主表:班级表
mysql> CREATE TABLE myclass3(id INT PRIMARY KEY, name VARCHAR(20) NOT NULL);

-- 从表:学生表,class_id 引用 myclass3.id
mysql> CREATE TABLE myclass3_stu(
    -> id INT PRIMARY KEY,
    -> name VARCHAR(30) NOT NULL,
    -> class_id INT,
    -> FOREIGN KEY (class_id) REFERENCES myclass3(id));

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    |       |
+----------+-------------+------+-----+---------+-------+

mysql> INSERT INTO myclass3 VALUES (10, 'C++'), (20, 'Java');
mysql> INSERT INTO myclass3_stu VALUES (1, 'Li', 10), (2, 'Sun', 20);   -- 正常

mysql> INSERT INTO myclass3_stu VALUES (3, 'wang', 30);   -- 主表无 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`))

mysql> INSERT INTO myclass3_stu VALUES (3, 'wang', NULL);  -- 外键允许 NULL
Query OK, 1 row affected (0.00 sec)

删除主表被引用的数据时,若从表仍有引用会失败;需要先处理从表数据(或建表时使用 ON DELETE CASCADE 等级联策略,生产环境慎用)。

6.10 检查约束(CHECK)

作用:检查字段值是否满足指定条件,一般用于限定取值范围。

注意:MySQL 8.0.16 之前 CHECK 只是语法上接受但不强制执行;8.0.16 起正式支持。

sql 复制代码
mysql> CREATE TABLE t5(
    -> id INT PRIMARY KEY,
    -> name VARCHAR(20),
    -> salary FLOAT,
    -> CHECK(salary > 0 AND salary < 10000));

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.

-- 建表后追加检查约束
mysql> ALTER TABLE t5 ADD CONSTRAINT check_id CHECK(id > 0);

6.11 删除约束速查

约束 定义级别 删除方式
NOT NULL 仅列级 ALTER TABLE 表名 MODIFY 列名 类型;
DEFAULT 仅列级 ALTER TABLE 表名 MODIFY 列名 类型;
AUTO_INCREMENT 列属性 ALTER TABLE 表名 MODIFY 列名 类型;
PRIMARY KEY 列级 / 表级 ALTER TABLE 表名 DROP PRIMARY KEY;
UNIQUE 列级 / 表级 ALTER TABLE 表名 DROP INDEX 唯一约束名;
FOREIGN KEY 列级 / 表级 ALTER TABLE 表名 DROP FOREIGN KEY 外键名;
CHECK 列级 / 表级 ALTER TABLE 表名 DROP CHECK 约束名;

七、存储引擎与完整建表语句

7.1 什么是存储引擎

存储引擎是数据库底层软件组织,DBMS 使用存储引擎进行创建、查询、更新和删除数据。不同引擎提供不同的存储机制、索引技巧和锁定水平。MySQL 的核心就是插件式存储引擎,可按需选择是否支持事务、使用哪种索引等。

常见存储引擎:

引擎 特点 适用场景
InnoDB 支持 ACID 事务、行级锁、外键,MySQL 5.5 之后的默认引擎 事务完整性、并发一致性要求高的场景
MyISAM 5.5 之前的默认引擎,插入/查询速度快,不支持事务,表级锁 以读写为主、极少更新删除、对事务要求不高的场景
MEMORY 数据全放内存,速度极快,重启后数据丢失 临时表、缓存类数据
Archive 高压缩比,插入快,查询支持差 历史归档数据
CSV 以 CSV 文本存储,不支持索引 数据交换
BlackHole 写入即丢弃,可记录 binlog 复制中继
Federated 联合不同 MySQL 服务器 分布式应用

7.2 引擎对比

功能 MyISAM MEMORY InnoDB
存储限制 256TB RAM 64TB
支持事务 No No Yes
支持全文索引 Yes No No
支持 B 树索引 Yes Yes Yes
支持哈希索引 No Yes No
支持外键 No No Yes
空间使用率 低 N/A 高

7.3 查看与指定存储引擎

sql 复制代码
SHOW ENGINES \G;                                  -- 查看支持的引擎
SHOW VARIABLES LIKE '%storage_engine%';           -- 查看默认引擎
sql 复制代码
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|
+---------------------------------+----------+

创建表时指定引擎与字符集:

sql 复制代码
CREATE TABLE 表名 (...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

不指定时使用 my.cnf 中 default-storage-engine=InnoDB 配置的默认引擎。

7.4 完整建表语句模板

sql 复制代码
CREATE TABLE 表名 (
    列名 列类型 [AUTO_INCREMENT] [DEFAULT 默认值] [列约束] [COMMENT '说明'],
    ...
    [表级约束]
) [ENGINE=存储引擎] [DEFAULT] CHARSET=字符集;

各选项含义:

选项 说明
列类型 该列数据的存储类型
AUTO_INCREMENT 自动增长,只能用于数值类型的列
DEFAULT 该列的默认值
约束 对列的限制(非空、唯一、主键、外键、检查)
ENGINE 表的存储引擎
CHARSET 表的字符集

八、数据库账户与权限管理

8.1 MySQL 8 密码策略

MySQL 8.0 开始,默认身份验证插件由 mysql_native_password 改为 caching_sha2_password。

  • mysql_native_password 依赖 SHA1,而 NIST 已建议停止使用 SHA1(易被破解);
  • caching_sha2_password 使用 SHA-256,更安全,是 8.0 的默认插件。

查看密码相关配置:

sql 复制代码
SHOW VARIABLES LIKE '%password%';

常用参数:

参数 含义
default_password_lifetime 密码过期时间(天),0 表示永不过期
password_history 不允许使用最近 n 次用过的密码
password_reuse_interval 不允许使用最近 n 天内用过的密码
password_require_current 修改密码时是否需要提供当前密码
caching_sha2_password_digest_rounds 哈希回合数

查看密码强度插件策略:

sql 复制代码
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    |        |
| 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      |
+--------------------------------------+--------+

密码强度等级(validate_password.policy):

等级 检查内容
0 / LOW 仅检查长度
1 / MEDIUM 长度、数字、大小写、特殊字符
2 / STRONG 长度、数字、大小写、特殊字符、字典文件

修改策略(临时生效,重启服务后失效):

sql 复制代码
mysql> SET GLOBAL validate_password.policy = LOW;
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> FLUSH PRIVILEGES;

永久生效需写入配置文件 /etc/my.cnf:

ini 复制代码
validate_password.policy=low
validate_password.length=6
validate_password.mixed_case_count=0
validate_password.number_count=6
validate_password.special_char_count=0

修改密码:

sql 复制代码
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
FLUSH PRIVILEGES;

8.2 登录账户管理原则

MySQL 8 的账户权限管理原则:先创建账户,再赋予权限 。用户信息存放在 mysql 库的 user 表中。

sql 复制代码
mysql> USE mysql;
mysql> SELECT user, host, plugin FROM mysql.user;
mysql> DESC user;
mysql> SELECT user, host, authentication_string FROM user;

8.3 新建登录账户

sql 复制代码
CREATE USER '用户名'@'主机' IDENTIFIED BY '密码';
参数 含义
用户名 创建的用户名
主机 允许登录的来源:localhost 表示本机,% 表示任意远程主机
密码 登录密码,需符合密码策略
sql 复制代码
mysql> CREATE USER 'test1'@'localhost' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT user, host, plugin FROM mysql.user;
mysql> exit
Bye

[root@server ~]# mysql -u test1 -p
Enter password:

注意:% 允许任意 IP 登录,生产环境严禁给 root 配置 %。

8.4 账户授权

赋权原则:

  1. root 账号禁止 允许任意 IP 访问(不能用 %);
  2. 应用账号与管理账号分离;
  3. 赋权最小化,一般只给 SELECT,尽量不给 UPDATE、INSERT、DELETE;
  4. 密码设置合理;
  5. 定期清理不使用的账户。

常见权限:

权限 说明 级别
CREATE 创建数据库、表、索引 库/表/索引
DROP 删除数据库、表 库/表
ALTER 修改表 表
INSERT 添加表数据 表
SELECT 查询表数据 表
UPDATE 更新表数据 表
DELETE 删除表数据 表
INDEX 操作索引 表
REFERENCES 引用权限 库/表
GRANT OPTION 赋予权限 库/表
CREATE VIEW / SHOW VIEW 创建/查看视图 视图
CREATE ROUTINE / ALTER ROUTINE / EXECUTE 存储过程相关 存储过程
FILE 访问服务器文件 文件管理
CREATE USER 创建用户 服务器管理
SHUTDOWN 关闭数据库 服务器管理
PROCESS 查看进程 服务器管理
SUPER 超级权限 服务器管理
ALL [PRIVILEGES] 所有权限 ---
USAGE 无任何权限(仅能连接) ---

查看权限:

sql 复制代码
mysql> SHOW GRANTS;                              -- 查看当前账户权限
mysql> SHOW GRANTS FOR 'test1'@'localhost';      -- 查看指定账户权限
+-------------------------------------------+
| Grants for test1@localhost                |
+-------------------------------------------+
| GRANT USAGE ON *.* TO `test1`@`localhost` |
+-------------------------------------------+

赋权语法:

sql 复制代码
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'来源地址' [IDENTIFIED BY '密码'];
  • 权限列表:SELECT、INSERT、UPDATE、CREATE 等,多个用逗号分隔,全部用 ALL;
  • 数据库名:* 代表所有数据库;
  • 表名:* 代表所有表;
  • 来源地址:localhost 本机,% 任意主机。

示例 1:创建 test1 并赋查询权限

sql 复制代码
mysql> GRANT SELECT ON *.* TO 'test1'@'localhost';
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW GRANTS FOR 'test1'@'localhost';
+--------------------------------------------+
| Grants for test1@localhost                 |
+--------------------------------------------+
| GRANT SELECT ON *.* TO `test1`@`localhost` |
+--------------------------------------------+

示例 2:test2 仅允许 172.16.50.0/24 网段登录,赋 SELECT、CREATE

sql 复制代码
mysql> CREATE USER 'test2'@'10.100.170.%' IDENTIFIED BY '123456';
mysql> GRANT SELECT, CREATE ON *.* TO 'test2'@'10.100.170.%';
mysql> SHOW GRANTS FOR 'test2'@'10.100.170.%';

示例 3:test3 拥有所有权限,可创建 test4 并赋权

sql 复制代码
mysql> CREATE USER 'test3'@'%' IDENTIFIED BY '123456';
mysql> GRANT ALL ON *.* TO 'test3'@'%';

-- 注意:ALL 不包含「给其他账户赋权」的权限
mysql> GRANT ALL ON *.* TO 'test3'@'%' WITH GRANT OPTION;

8.5 回收权限

sql 复制代码
REVOKE 权限列表 | ALL ON 库名.表名 FROM '用户名'@'来源地址';

REVOKE 与 GRANT 语法基本一致,只需把 TO 换成 FROM。

sql 复制代码
mysql> REVOKE SELECT ON *.* FROM 'test4'@'%';
mysql> REVOKE ALL ON *.* FROM 'test3'@'%';
mysql> SHOW GRANTS FOR 'test4'@'%';

8.6 删除账户

sql 复制代码
DROP USER '用户名'@'访问主机名';

mysql> DROP USER 'test1'@'localhost';
mysql> DROP USER 'test2'@'10.100.170.%';
mysql> DROP USER test3;    -- 主机为 % 时可省略主机部分
sql 复制代码
mysql> SELECT user, host FROM mysql.user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+

九、综合练习

9.1 数据库基础练习

创建 temp1、temp2 两个数据库,查看所有数据库,使用 temp1,最后删除 temp1、temp2:

sql 复制代码
CREATE DATABASE temp1;
CREATE DATABASE temp2;
SHOW DATABASES;
USE temp1;
SELECT DATABASE();
DROP DATABASE temp1;
DROP DATABASE temp2;

9.2 建表练习:班级表

在 mydb2_stuinfo 中新建班级表 class1:

sql 复制代码
mysql> USE mydb2_stuinfo;
mysql> CREATE TABLE class1(
    -> cla_num INT,
    -> cla_name VARCHAR(10),
    -> number INT,
    -> monitor VARCHAR(20),
    -> creation_date DATE);
Query OK, 0 rows affected (0.02 sec)

mysql> DESC class1;

9.3 约束综合练习:销售系统

创建销售数据库 mydb5_sales,建产品表与订单表:

sql 复制代码
mysql> CREATE DATABASE mydb5_sales;
mysql> USE mydb5_sales;

-- 产品表:编号唯一键、名称非空、单价非空、规格默认「件」
mysql> CREATE TABLE pro_tb(
    -> pro_num INT UNIQUE,
    -> pro_name VARCHAR(30) NOT NULL,
    -> pro_price FLOAT(5,2) NOT NULL,
    -> pro_spe VARCHAR(8) DEFAULT '件');
Query OK, 0 rows affected, 2 warnings (0.01 sec)

-- 订单表:订单号主键自增、金额检查 > 0、产品编号外键
mysql> CREATE TABLE orders(
    -> id INT PRIMARY KEY AUTO_INCREMENT,
    -> customer_id INT NOT NULL,
    -> pro_num INT NOT NULL,
    -> signing_date DATE,
    -> amount FLOAT(5,2),
    -> CHECK(amount > 0),
    -> FOREIGN KEY(pro_num) REFERENCES pro_tb(pro_num));
Query OK, 0 rows affected, 4 warnings (0.02 sec)

mysql> DESC pro_tb;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| pro_num   | int         | YES  | UNI | NULL    |       |
| pro_name  | varchar(30) | NO   |     | NULL    |       |
| pro_price | float(5,2)  | NO   |     | NULL    |       |
| pro_spe   | varchar(8)  | YES  |     | 件      |       |
+-----------+-------------+------+-----+---------+-------+

mysql> DESC orders;
+--------------+------------+------+-----+---------+----------------+
| Field        | Type       | Null | Key | Default | Extra          |
+--------------+------------+------+-----+---------+----------------+
| id           | int        | NO   | PRI | NULL    | auto_increment |
| customer_id  | int        | NO   |     | NULL    |                |
| pro_num      | int        | NO   | MUL | NULL    |                |
| signing_date | date       | YES  |     | NULL    |                |
| amount       | float(5,2) | YES  |     | NULL    |                |
+--------------+------------+------+-----+---------+----------------+

9.4 用户授权练习

  1. 创建 test1@localhost,赋予 SELECT 权限;用 test1 登录验证只能看到部分库;
  2. 创建 test2@10.100.170.%,赋予 SELECT、CREATE,验证可建库;
  3. 创建 test3@%,赋予 ALL + WITH GRANT OPTION,验证可创建 test4 并赋权;
  4. 回收 test1~test4 的权限,最后删除这些账户。
sql 复制代码
-- 回收
REVOKE ALL ON *.* FROM 'test1'@'localhost';
REVOKE ALL ON *.* FROM 'test2'@'10.100.170.%';
REVOKE ALL ON *.* FROM 'test3'@'%';
REVOKE ALL ON *.* FROM 'test4'@'%';

-- 删除
DROP USER 'test1'@'localhost';
DROP USER 'test2'@'10.100.170.%';
DROP USER test3;
DROP USER test4;

十、常见报错与命令速查

10.1 常见报错

报错 原因 解决
ERROR 2002 ... mysql.sock MySQL 服务未启动 systemctl start mysqld
ERROR 1007 ... database exists 数据库已存在 换名字或加 IF NOT EXISTS
ERROR 1064 ... syntax SQL 语法错误,常见于用了关键字 检查语法,关键字加反引号
No database selected 没先 USE 数据库 先 USE 库名;
ERROR 1364 ... doesn't have a default value 非空字段未赋值 插入时补上该字段
ERROR 1062 ... Duplicate entry 主键/唯一键重复 修改重复值
ERROR 1452 ... foreign key constraint fails 外键引用的主键不存在 先插入主表数据
ERROR 3819 ... Check constraint is violated 不满足检查约束 调整数据范围

10.2 命令速查表

sql 复制代码
-- ===== 数据库 =====
SHOW DATABASES [LIKE '条件'];       -- 查看库
CREATE DATABASE 库名;               -- 建库
USE 库名;                           -- 切换库
SELECT DATABASE();                  -- 当前库
DROP DATABASE 库名;                 -- 删库

-- ===== 表 =====
CREATE TABLE 表名(列名 类型 约束, ...);   -- 建表
SHOW TABLES [FROM 库名];                  -- 查看表
DESC 表名;                                -- 查看表结构
SHOW CREATE TABLE 表名\G;                 -- 查看建表语句
ALTER TABLE 表名 RENAME 新表名;           -- 改表名
ALTER TABLE 表名 ADD 列名 类型 [FIRST|AFTER 列];  -- 加列
ALTER TABLE 表名 DROP 列名;               -- 删列
ALTER TABLE 表名 CHANGE 旧列 新列 类型;   -- 改列名
ALTER TABLE 表名 MODIFY 列名 类型;        -- 改列类型
DROP TABLE [IF EXISTS] 表名;              -- 删表

-- ===== 约束 =====
ALTER TABLE 表名 ADD PRIMARY KEY(列);     -- 主键
ALTER TABLE 表名 DROP PRIMARY KEY;        -- 删主键
ALTER TABLE 表名 ADD UNIQUE(列);          -- 唯一
ALTER TABLE 表名 ADD FOREIGN KEY(列) REFERENCES 主表(列);
ALTER TABLE 表名 DROP FOREIGN KEY 外键名;
ALTER TABLE 表名 ADD CHECK(条件);
ALTER TABLE 表名 DROP CHECK 约束名;

-- ===== 字符集 =====
SHOW CHARACTER SET [LIKE 'utf%'];
SHOW COLLATION;
SHOW VARIABLES LIKE 'character_set%';

-- ===== 存储引擎 =====
SHOW ENGINES\G;
SHOW VARIABLES LIKE '%storage_engine%';
CREATE TABLE 表名(...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ===== 用户与权限 =====
CREATE USER '用户'@'主机' IDENTIFIED BY '密码';
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
GRANT 权限 ON 库.表 TO '用户'@'主机';
GRANT ALL ON *.* TO '用户'@'%' WITH GRANT OPTION;
REVOKE 权限 ON 库.表 FROM '用户'@'主机';
SHOW GRANTS [FOR '用户'@'主机'];
DROP USER '用户'@'主机';
FLUSH PRIVILEGES;

10.3 总结

  • SQL 分类:DDL 管结构、DML 管数据、DCL 管权限、TCL 管事务;
  • 数据库操作 :CREATE / SHOW / USE / SELECT DATABASE() / DROP 五板斧;
  • 字符集 :8.0 默认 utf8mb4,utf8 实际是 utf8mb3,新项目统一 utf8mb4 + utf8mb4_0900_ai_ci;
  • 表操作 :CREATE / DESC / ALTER / DROP / RENAME,复制表要区分仅结构、结构+数据、仅数据;
  • 数据类型 :整数选合适宽度、金额用 DECIMAL、定长用 CHAR、变长用 VARCHAR;
  • 六大约束:非空、默认值、主键、唯一、外键、检查------建表时就规划好,比事后补约束更重要;
  • 用户权限 :先建用户再授权、最小权限原则、root 禁用 % 登录、定期回收权限。
相关推荐
猿究院_夏燊1 小时前
MySQL 的四种隔离级别
java·数据库·mysql
say_fall1 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++
共享家95272 小时前
408 操作系统第一章
服务器·数据库·windows
这个DBA有点耶3 小时前
连拿六年第一后宣布出海:国产数据库凭什么敢撕掉“平替”的标签?
数据库·人工智能·架构
云和恩墨3 小时前
数据库监控简史:从会回答到能交付——AI-DBA如何成为真正的数字同事
数据库·人工智能·dba
paopaokaka_luck3 小时前
灾害应急物资管理系统(AI应急助手、Echarts可视化数据看板、捐赠入库联动、 物资全流程管理、库存变动追溯、灾情资讯与互动反馈、物资发放公示)
java·前端·javascript·spring boot·mysql·tomcat·echarts
这个DBA有点耶4 小时前
为什么删掉索引后,查询瞬间变快了?探讨MySQL的随机I/O与顺序I/O博弈
数据库·mysql·代码规范
kingx35 小时前
BugKu 渗透测试 4 实战:文件上传打点,5 Flag 全通
数据库·渗透测试·web·内网渗透
我命由我123455 小时前
Python 实用操作 - 文件操作(打开与关闭文件、读取文件、文件写入)
java·开发语言·前端·javascript·数据库·python·java-ee