当前位置: 首页 > news >正文

MySQL 库表与约束

MySQL库表与约束

  • 一、基础命令操作
    • 1.1 登录进入 MySQL
    • 1.2 SQL语句概述
    • 1.3 MySQL字符集
      • 1.3.1 字符集
      • 1.3.2 字符序
  • 二、数据库操作
    • 2.1 数据库常用操作命令
    • 2.2 创建库 (create database 数据库名)
    • 2.3 查看库 (show databases)
    • 2.4 删除库 (drop database 数据库名)
    • 2.5 切换库(use 数据库名)
    • 2.6 数据库对象
    • 2.7 数据库字典
  • 三、表的基本操作
    • 3.1 数据类型
    • 3.2 创建表 (create table 表名 (表选项))
    • 3.3 查看表(show/desc)
    • 3.4 删除表(drop table [if exists] 表名;)
    • 3.5 修改表
      • 3.5.1 修改表名(alter/rename;)
      • 3.5.2 添加新列(alter talble 表名 add 新列名 列类型;)
      • 3.5.3 删除列(alter table 表名 drop 列名;)
      • 3.5.4 修改列名(alter table 表名 change 旧列名 新列名 列类型;)
      • 3.5.5 修改列类型(alter table 表名 modify 列名 列类型;)
      • 3.5.6 修改列位置(alter table 表名 modify 列名 列类型 after 某列;)
    • 3.6 复制表的结构(create/insert into)
  • 四、表的约束
    • 4.1 概念与语法
    • 4.2 非空约束 not null
    • 4.3 默认值约束 default' '
    • 4.4 列描述 comment ' '
    • 4.5 主键约束 primary key
      • 4.5.1 复合主键 primary key (字段1,字段2)
      • 4.5.2 主键自增长 auto_increment
    • 4.6 外键约束 foreign key references
    • 4.7 唯一性约束 unique
    • 4.8 检查约束 check
    • 4.9 删除约束
  • 五、MySQL库表设计(范式)
    • 5.1 范式概念与三范式小结
    • 5.2 第一范式(1NF)
    • 5.3 第二范式(2NF)
    • 5.4 第三范式(3NF)
    • 5.5 巴斯-科德范式(BCNF)
    • 5.6 第四范式(4NF)- 消除表中的多值依赖关系
    • 5.7 第五范式(5NF)/完美范式
    • 5.9 第六范式(6NF)/域键范式
    • 5.9 反范式 - 不遵循数据库范式设计
  • 六、MySQL数据库账户及授权
    • 6.1 密码策略
    • 6.2 登录账户管理
    • 6.3 新建登录账户(create user ''@'' identified by '')
    • 6.4 账户授权(grant)
    • 6.5 回收权限(revoke)
    • 6.6 删除账户(drop user ''@'')
    • 练习

一、基础命令操作

1.1 登录进入 MySQL

  • 登录MySQL:
# 以root用户登录,-p代表输入密码
mysql -u root -p
# 安全起见,一般情况不会直接在-p后面直接输入密码
mysql -u 用户名 -h 服务器的主机地址 -p密码 -A
#带有密码登录,会有警告,提示不安全
  • -u 后面跟登录数据库的用户名,这里使用 root
  • -h 后面的参数是服务器的主机地址,如果客户端和服务器在同一台机器上,则输入 localhost 或者 IP 地址
  • -p 后面是用户登录密码,注意:-p 和密码之间没有空格。如果出现空格,系统将不会把后面的字符串当成密码来对待,没有密码时不写
  • -A参数:不预读数据库信息,加上该参数则不预读数据库中的表等信息,不会有表名及列名的补全,但读取速度会加快

1.2 SQL语句概述

SQL:结构化查询语言(Structured Query Language),在关系型数据库上执行数据操作数据检索以及数据维护的标准语言。

数据库系统中,SQL语句不区分大小写(建议用大写) ,但字符串常量区分大小写

MySQL致力于支持全套ANSI/ISO SQL标准。在MySQL数据库中,SQL 语句分为五大类:

  • DCL(Data Control Language):数据控制语言,定义对数据库、表、字段、用户的访问权限和安全级别,如grant、revoke、transaction、control、commit、rollback、savepoint
  • DDL(Data Definition Language):数据定义语言,定义对数据库对象(库、表、列、索引)的操作,如:create、drop、alter、rename、 truncate
  • DML(Data Manipulation Language): 数据操作语言,定义对数据库记录的操作,如:insert、delete、update、select
  • DQL(Data Query Language):数据查询语言,用来查询记录(数据)
  • TCL:事务控制语句,例如 commit、rollback、setpoint 等语句属于这个分类
SQL语句可单行或多行书写,以“;”结尾
/* */ 和// 为多行注释
-- 和 # 为 单行注释

带有通配符的条件:

%:匹配任意零个或多个字符
_ :匹配任意单个字符

MySQL中 sql 语句的反引号,可以避免一些与SQL语法冲突的问题,同时可以使代码更加规范化和易读性更强

eg.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| testdb             |
+--------------------+
mysql> select name, address from `table`;
# table若当做表名但其为关键字回报错,加上反引号可以避免与SQL关键字的冲突

命令:

  • 退出:
退出:exit quit \q
  • 清屏:
清屏:\! cls

常用命令:

\G:表示将查询结果进行按列打印,即将查到的结构旋转90度变成纵向显示,不需要分号
\g: #相当于分号
\! 、cls :#清屏
exit、quit、\q :#退出

1.3 MySQL字符集

MySQL字符集包括字符集(CHARACTER)和排序规则(校对规则)(COLLATION)两个概念

1.3.1 字符集

Character Set(字符集):是字符的编码规则,规定了字符在数据库中的存储格式,比如占多少空间,支持哪些字符等

latin1 支持西欧字符、希腊字符等
gbk 支持中文简体字符,但是不是国际通用字符集
big5 支持中文繁体字符
utf8 几乎支持世界所有国家的字符。
utf8mb4 完全兼容 UTF-8,用四个字节存储更多的字符

查看所有支持的字符集

# 格式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:该字符集中字符最大存储长度
# 格式2:
# \G表示将查询结果进行按列打印,即将查到的结构旋转90度变成纵向显示,不需要分号
mysql> show character set\G
*************************** 1. row ***************************Charset: armscii8Description: ARMSCII-8 Armenian
Default collation: armscii8_general_ciMaxlen: 1
*************************** 2. row ***************************Charset: asciiDescription: US ASCII
Default collation: ascii_general_ciMaxlen: 1
*************************** 3. row ***************************Charset: big5Description: Big5 Traditional Chinese
Default collation: big5_chinese_ciMaxlen: 2
*************************** 4. row ***************************Charset: binaryDescription: Binary pseudo charset
Default collation: binaryMaxlen: 1
……

MySQL数据库在开发运维中,字符集选用规则如下:

  • 如果系统开发面向国外业务,需要处理不同国家、不同语言,则应该选择utf-8或者utf8mb4
  • 如果只需要支持中文,没有国外业务,则为了性能考虑,可以采用GBK

查看指定字符集

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

1.3.2 字符序

字符序就是字符排序的规则集合

  • MySQL字符序命名规则:
    • 以字符序对应的字符集名称开头
    • 以国家名居中(或以general居中)
    • 后缀:
      • bin:二进制;
      • ci:大小写不敏感;
      • cs:大小写敏感;
      • ai:口音(Accent)不敏感;
      • as:口音敏感;
      • ks:假名(Kanatype)敏感
# 查看支持的字符序
mysql> show collation;# 字段含义# Collation:字符序名称# Charset:该字符序关联的字符集# Id:字符序ID# Default:该字符序是否是所关联的字符集的默认字符序armscii8_general_ci就是armscii8的默	认字符序,而armscii8_bin就不是;# Compiled:字符集是否已编译到服务器中# Sortlen:这与对以字符集表示的字符串进行排序所需的内存量有关# Pad_attribute:这表明了字符序在比较字符串时对末尾padding的处理。NO PAD表明在比较字符串	时,末尾的padding也会考虑进去,否则不考虑

指定条件查询

mysql> show collation where charset = "utf8mb4";

查看当前字符集的设置:

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

二、数据库操作

# 新建数据库
create database 数据库名# 设为当前数据库
use  数据库名# 查看当前使用的数据库
select  database();# 显示所有数据库
show  databases;# 删除数据库
drop database 数据库名# 查看当前登录的用户及主机名
select user();

2.1 数据库常用操作命令

数据库的登录及退出

mysql -uroot -p #登录
exit quit \q #退出

查看当前数据库

select database();
mysql> select database();
+------------+
| database() |
+------------+
| NULL |
+------------+

切换数据库

use 数据库名
mysql> use testdb;
Database changed
mysql> select database(); # 再次查看
+------------+
| database() |
+------------+
| testdb |
+------------+

显示时间

mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2023-02-10 09:39:14 |
+---------------------+
1 row in set (0.00 sec)

显示数据库版本

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.37 |
+-----------+
1 row in set (0.00 sec)

2.2 创建库 (create database 数据库名)

  • 数据库命名尽量不超过30个字符
  • 数据库命名一般为项目名称+代表库含义的简写,比如 IM 项目的工作流数据库,可以是 im_flow
  • 命名应使用小写
  • 在创建数据库或查看创建数据库语句时,database没有s
mysql> create database mydb1_test;
Query OK, 1 row affected (0.04 sec)

若数据库已存在,则报错

2.3 查看库 (show databases)

show databases [like 条件];

注意有 s

mysql> show databases; 		#注意有 s
+--------------------+
| Database           |
+--------------------+
| information_schema |		#主要存储了系统中的一些数据库对象信息
| mysql              |		#系统的用户权限信息及帮助信息
| performance_schema |		#主要存储数据库服务器的性能参数
| sys                |		#通过视图的形式把information_schema 和performance_schema结合起来
+--------------------+
4 rows in set (0.26 sec)mysql> select database(); 	#查看当前库
+------------+
| database() |
+------------+
| NULL       |
+------------+
1 row in set (0.01 sec)# 使用条件查看
mysql> show databases  like  'sys';
+----------------+
| Database (sys) |
+----------------+
| sys            |
+----------------+
1 row in set (0.00 sec)

Information_schema: 主要存储了系统中的一些数据库对象信息,如:用户表信息、列信息、权限信息、字符集信息、分区信息等。(数据字典表)
performance_schema:主要存储数据库服务器的性能参数
mysql: 存储了系统的用户权限信息帮助信息
sys: 5.7新增,之前版本需要手工导入。这个库是通过视图的形式把information_schema 和performance_schema结合起来,查询出更加令人容易理解的数据

2.4 删除库 (drop database 数据库名)

mysql> drop database testdb;
Query OK, 0 rows affected (0.01 sec)mysql> show  databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

2.5 切换库(use 数据库名)

mysql> use mydb1_test;
Database changed
# 查看当前用户
mysql> select database();
+------------+
| database() |
+------------+
| mydb1_test |
+------------+
1 row in set (0.00 sec)

2.6 数据库对象

组成:

加粗样式

数据库对象的命名规则:

  • 命名使用具有意义的英文词汇,词汇中间以下划线分隔
  • 名称由字母、数字、#、下划线、$组成,必须以英文字母开头
  • 不要使用 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 表视情况而定,也尽量简短为宜,命名应使用小写

2.7 数据库字典

  • 数据字典:类似于系统编目或花名册,它保存数据库服务器上的元数据信息(数据库的整体属性信息)

  • 元数据(meta data):即“data about data” 关于数据的数据,理解为描述数据的数据,内容包括:数据库的属性信息、数据表的属性信息、字段的属性信息、视图的属性信息、用户信息、统计类信息等。

  • information_schema 数据库是MySQL系统自带的数据库,它提供了数据库元数据的访问方式

mysql> use information_schema;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> show tables;
+---------------------------------------+
| Tables_in_information_schema          |
+---------------------------------------+
| ADMINISTRABLE_ROLE_AUTHORIZATIONS     |
| APPLICABLE_ROLES                      |
| CHARACTER_SETS                        |
| CHECK_CONSTRAINTS                     |
| COLLATIONS                            |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS                               |	#存放数据库里所有的列信息
| COLUMNS_EXTENSIONS                    |
| COLUMN_PRIVILEGES                     |
| COLUMN_STATISTICS                     |
| ENABLED_ROLES                         |
| ENGINES                               |
| EVENTS                                |
| FILES                                 |
| INNODB_BUFFER_PAGE                    |
| INNODB_BUFFER_PAGE_LRU                |
| INNODB_BUFFER_POOL_STATS              |
| INNODB_CACHED_INDEXES                 |
| INNODB_CMP                            |
| INNODB_CMPMEM                         |
| INNODB_CMPMEM_RESET                   |
| INNODB_CMP_PER_INDEX                  |
| INNODB_CMP_PER_INDEX_RESET            |
| INNODB_CMP_RESET                      |
| INNODB_COLUMNS                        |
| INNODB_DATAFILES                      |
| INNODB_FIELDS                         |
| INNODB_FOREIGN                        |
| INNODB_FOREIGN_COLS                   |
| INNODB_FT_BEING_DELETED               |
| INNODB_FT_CONFIG                      |
| INNODB_FT_DEFAULT_STOPWORD            |
| INNODB_FT_DELETED                     |
| INNODB_FT_INDEX_CACHE                 |
| INNODB_FT_INDEX_TABLE                 |
| INNODB_INDEXES                        |
| INNODB_METRICS                        |
| INNODB_SESSION_TEMP_TABLESPACES       |
| INNODB_TABLES                         |
| INNODB_TABLESPACES                    |
| INNODB_TABLESPACES_BRIEF              |
| INNODB_TABLESTATS                     |
| INNODB_TEMP_TABLE_INFO                |
| INNODB_TRX                            |
| INNODB_VIRTUAL                        |
| JSON_DUALITY_VIEWS                    |
| JSON_DUALITY_VIEW_COLUMNS             |
| JSON_DUALITY_VIEW_LINKS               |
| JSON_DUALITY_VIEW_TABLES              |
| KEYWORDS                              |
| KEY_COLUMN_USAGE                      |	#存放数据库所有的主外键
| LIBRARIES                             |
| OPTIMIZER_TRACE                       |
| PARAMETERS                            |
| PARTITIONS                            |
| PLUGINS                               |
| PROCESSLIST                           |
| PROFILING                             |
| REFERENTIAL_CONSTRAINTS               |
| RESOURCE_GROUPS                       |
| ROLE_COLUMN_GRANTS                    |
| ROLE_ROUTINE_GRANTS                   |
| ROLE_TABLE_GRANTS                     |
| ROUTINES                              |	#存放数据库里所有存储过程和函数
| ROUTINE_LIBRARIES                     |
| SCHEMATA                              |	#存放数据库里所有的数据库信息
| SCHEMATA_EXTENSIONS                   |
| SCHEMA_PRIVILEGES                     |
| STATISTICS                            |	#存放了数据表的索引
| ST_GEOMETRY_COLUMNS                   |
| ST_SPATIAL_REFERENCE_SYSTEMS          |
| ST_UNITS_OF_MEASURE                   |
| TABLES                                |	#存放数据库里所有的数据表、以及每个表所在数据库
| TABLESPACES_EXTENSIONS                |
| TABLES_EXTENSIONS                     |
| TABLE_CONSTRAINTS                     |	#存放数据库全部约束
| TABLE_CONSTRAINTS_EXTENSIONS          |
| TABLE_PRIVILEGES                      |
| TRIGGERS                              |	#存放数据库里所有的触发器
| USER_ATTRIBUTES                       |
| USER_PRIVILEGES                       |
| VIEWS                                 |	#存放数据库里所有的视图信息
| VIEW_ROUTINE_USAGE                    |
| VIEW_TABLE_USAGE                      |
+---------------------------------------+
84 rows in set (0.002 sec)

常用表解释:
tables-存放数据库里所有的数据表、以及每个表所在数据库
schemata-存放数据库里所有的数据库信息
views-存放数据库里所有的视图信息
columns-存放数据库里所有的列信息
triggers-存放数据库里所有的触发器
routines-存放数据库里所有存储过程和函数
key_column_usage-存放数据库所有的主外键
table_constraints-存放数据库全部约束
statistics-存放了数据表的索引
……

三、表的基本操作

# 新建表
create tables  表名(列名1 类型  , 列名2  类型 ……);# 查看表各列信息
{describe|desc}表名[列名];
# or
show columns from 表名称;
# 查看所有表
show tables [from 数据库名][like wild]; # 删除表
drop table  if  exists  表名;  # 修改表名
alter  table  旧表名  rename  新表名;
# or
rename table 表名 to 新表名;# 表中添加新列
alter table 表名 add  新列名 列类型  [after|first] 列名;after为之后)# 删除列
alter table 表名 drop 列名;# 修改列名
alter  table  表名 change  旧列名  新列名 列类型;# 修改列类型
alter  table  表名  modify  列名  列类型;# 修改列位置
alter table 表名 modify  列名  列类型 after 某列;

3.1 数据类型

类型组成:数字、文本、日期/时间类型

数据类型字节数e备注
int4整型 [-2147483648,2147483647]
float4单精度浮点型
double8双精度浮点型
char文本型 保存固定长度的字符串
varchar保存可变长度的字符串
text存放最大长度为 65,535 个字符的字符串
date3存储日期值(yyyy-MM-dd)
time3存储时分秒(HH:mm:ss)
year1存储年(yyyy)
datetime8存储日期+时间(yyyy-MM-dd HH:mm:ss )
timestamp4存储日期+时间,可作时间戳(yyyy-MM-dd HH:mm:ss)
varchar保存可变长度的字符串

可以使用float(M,D)、double(M,D)格式限制宽度按(M)和精度(D),如float(3,2),不指定M、D的时,会按照实际的精度来处理

3.2 创建表 (create table 表名 (表选项))

create table 表名 (表选项)

表定义选项格式为:

列名1 列类型1 约束, 列名2 列类型2 约束,……

表的名称命名规范:

  • 常规表:以 t_ 开头,t 代表 table 的意思,命名规则即 t + 模块(包含模块含义的简写)+ 表(包含表含义的简写),比如用户模块的教育信息表:t_user_eduinfo
  • 临时表:temp 前缀 + 模块 + 表 + 日期后缀:temp_user_eduinfo_20240520
  • 备份表(用于保存和归档历史数据或者作为灾备恢复的数据)命名规则,bak 前缀 + 模块 + 表 + 日期后缀:bak_user_eduinfo_20231219
  • 同一个模块的表尽可能使用相同的前缀,表名称尽可能表达含义
  • 多个单词以下划线 _ 分隔
  • 常规表表名尽量不超过30个字符,temp 表和 bak 表视情况而定,也尽量简短为宜,命名应使用小写
# 如果没有选择数据库,就会抛出 No database selected 的错误
mysql> select  database();  # 查看当前数据库mysql> create database mydb2_stuinfo;  # 创建数据库
Query OK, 1 row affected (0.02 sec)mysql> use mydb2_stuinfo;  # 使用数据库
Database changedmysql> 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.11 sec)mysql> show tables;
+----------------------+
| Tables_in_mydb1_test |
+----------------------+
| t1                   |
+----------------------+
1 row in set (0.07 sec)mysql> desc t1; #或者 show columns from 表名称;
+-------------+---------------+------+-----+---------+-------+
| Field       | Type          | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| float_num   | float(10,2)   | YES  |     | NULL    |       |
| double_num  | double(20,2)  | YES  |     | NULL    |       |
| decimal_num | decimal(20,2) | YES  |     | NULL    |       |
+-------------+---------------+------+-----+---------+-------+
3 rows in set (0.10 sec)

字段意义分析:

Field :字段名称
type:字段类型
null:是否允许为空
key:索引类型
default:默认值
extra:填充

3.3 查看表(show/desc)

  • show 语句:显示当前数据库中已有的数据表
show tables [from 数据库名][like wild];
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 语句:查看数据表中各列的信息
{describe|desc}表名[列名];
# or
show columns from 表名称;
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> 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)

3.4 删除表(drop table [if exists] 表名;)

用户必须拥有执行 drop table 命令的权限,否则数据表不会被删除

drop table [if exists] 表名;

推荐使用 if exists 字句,即先判断是否存在,存在则删除

mysql> drop table if exists tb1;
Query OK, 0 rows affected (0.01 sec)

删除的注意事项:

  1. 删除数据库表之前,一定要备份数据,以免数据丢失
  2. 在删除数据库表之前,要确保该表没有被其他的表所引用,否则可能会破坏外键约束
  3. 在删除数据库表之前,要确保该表的数据已经被清空,否则会破坏外键约束
  4. 在删除数据库表之前,要确保该表的所有索引都已经被删除。如果还存在索引,可能会导致删除失败
  5. 在删除数据库表之前,要确保该表的所有相关程序已经停止运行,以免影响其他程序的正常运行。

3.5 修改表

3.5.1 修改表名(alter/rename;)

  • 更改表名(重命名):
# 法1:
alter table 表名 rename 新表名;
# 法2:
rename table 表名 to 新表名;

3.5.2 添加新列(alter talble 表名 add 新列名 列类型;)

  • 添加新列
alter table 表名 add 新列名 列类型 [after|first] 列名;# after:在指定列之后插入新列
# first:在第一列插入新列
# 注意:无 before关键字
# 例:增加一列 password
mysql> alter table student1 add password char(8);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0# 注意:数据库操作后得到的反馈,表明操作的结果。这个信息表示:# Records: 0: 表示成功导入或处理的记录总数是0条# Duplicates: 0: 表示在操作过程中没有发现重复的记录# Warnings: 0: 表示在操作过程中没有产生任何警告

3.5.3 删除列(alter table 表名 drop 列名;)

删除列

alter table 表名 DROP 列名;
# 例:删除上例的notes列
mysql> alter table student1  drop notes;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

3.5.4 修改列名(alter table 表名 change 旧列名 新列名 列类型;)

修改列名

alter table 表名 change 旧列名 新列名 列类型;
mysql> alter table student1 change password passwd char(8);  # 改名
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

3.5.5 修改列类型(alter table 表名 modify 列名 列类型;)

修改列类型

alter table 表名 modify 列名 列类型;
mysql> alter table student1 modify birthday date; # 修改
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

3.5.6 修改列位置(alter table 表名 modify 列名 列类型 after 某列;)

修改列位置

alter table 表名 modify 列名 列类型 after 某列;
# 例:添加新列
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;

3.6 复制表的结构(create/insert into)

方法一:在 create table 语句的末尾添加 like 子句,可以将源表的表结构复制到新表中

create table 新表名 like 源表

注意:只是复制结构框架

方法二:在 create table 语句的末尾添加一个 select 语句,可以实现表结构的复制,甚至可以将源表的表记录拷贝到新表中

create table 新表名 select * from 源表

方法三:如果已经存在一张结构一致的表复制数据insert into

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

四、表的约束

4.1 概念与语法

约束:约束是 在表上 强制执行 的数据校验规则,本质上是 Mysql 通过 限制用户操作 的方式,来达到 维护数据本身安全及数据完整性 的一套方案

数据的完整性要从以下四个方面考虑:

  • 实体完整性(Entity Integrity):例如,同一个表中,不能存在两条完全相同无法区分的记录
  • 完整性(Domain Integrity):例如,年龄范围 0-120,性别范围“男/女”
  • 引用完整性(Referential Integrity):例如,员工所在部门,在部门表中要能找到这个部门
  • 用户自定义完整性(User-defined Integrity):例如,用户名唯一、密码不能为空等,本部门经理的工资不得高于本部门职工的平均工资的5倍。

常见的约束:

  • 非空约束 not null
  • 默认值约束 default
  • 主键约束 primary key
  • 外键约束
  • 唯一约束
  • 检查约束

列级约束:在定义列的同时定义约束

create table 表名 (列名 类型 约束 )

表级约束:在定义了所有列之后定义的约束

create table 表名 constraint 约束名 约束类型 (列信息)

创建表之后添加约束:

alter table 表名 add constraint 约束名 约束类型(要约束的列名)

创建表之后修改约束:

mysql> alter table <数据表名> change column <字段名> <字段名> <数据类型> not null;# 也可以通过modify修改
mysql> alter table <数据表名> modify  <字段名> <数据类型> not null;

4.2 非空约束 not null

作用:限定 某个字段/某列的值 不允许为空
如果不写约束,默认为 null

若需要某些字段必须写入,应该怎么处理,如:创建一个班级表,包含班级名和班级所在的教室,站在正常的业务逻辑中:如果班级没有名字,你不知道你在哪个班级,如果教室名字可以为空,就不知道在哪上课,所以我们在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中,这就是“约束

  • 删除非空约束 not null
mysql> alter table <数据表名> modify  <字段名> <数据类型>  null;
# 或者
mysql> alter table <数据表名> modify <字段名> <数据类型>;

4.3 默认值约束 default’ ’

作用:给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默认值

not null 和 defalut 一般不需要同时出现,因为 default 本身有默认值,不会为空

eg.

mysql> create table teacher1(id int not null, name varchar(30) not null, sex char(2) default '女', age int);
Query OK, 0 rows affected (0.03 sec)mysql> desc test;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int          | NO   |     | NULL    |       |
| name  | varchar(30)  | NO   |     | NULL    |       |
| sex   | char(2)      | NO   |     ||       |
| age   | int unsigned | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

4.4 列描述 comment ’ ’

列描述没有实际含义,专门用来描述字段,会根据表创建语句保存,供操作者来查看该列的含义

mysql> create table myclass2( class_name varchar(20) not null comment '教室',class_room  varchar(20)  default  '计科2');
Query OK, 0 rows affected (0.065 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.003 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'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.001 sec)

4.5 主键约束 primary key

作用:数据库存储数据不是唯一的目的,还要考虑到提取数据,一般要求 数据库表中的记录要有一个特定的唯一标识 ,来表示唯一性,这个唯一的特定标识就是主键,类似于序号学号这样的唯一标识,可以根据主键来唯一地筛选出一条记录

主键:primary key,用来唯一的约束该字段里面的数据

特点:

  • 主键字段不能为空,不能重复
  • 一张表中最多只能有一个主键
  • 主键所在的通常是整数类型
  • 主键约束是最频繁的约束

不要修改主键字段的值。因为主键是数据记录的唯一标识,如果修改了主键的 值,就有可能会破坏数据的完整性

  • 创建时添加主键
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(30)  | NO   |     | NULL    |       |
| sex   | char(2)      | YES  |     ||       |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.00 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 row in set (0.00 sec)
mysql> insert into t1(id,name) values(1,'黎明'); 	#再次插入出错,因为需要保持唯一性
ERROR 1062 (23000): Duplicate entry '1' for key 't1.PRIMARY'

再次插入出错,因为需要保持唯一性

  • 修改表,追加主键
mysql> alter table teacher1 add primary key(id);
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> desc teacher1;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int          | NO   | PRI | NULL    |       |
| name  | varchar(80)  | NO   |     | NULL    |       |
| sex   | char(2)      | YES  |     ||       |
| age   | int          | NO   |     | 18      |       |
+-------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

如果该字段内有重复值,则不能以该字段新增为主键,必须先把重复的数据去掉然后才能添加该列为主键

  • 删除主键:
alter table 表名 drop primary key;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.002 sec)mysql> alter table t5 drop primary key;
Query OK, 1 row affected (0.076 sec)
Records: 1  Duplicates: 0  Warnings: 0mysql> desc t5;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id     | int         | NO   |     | NULL    |       |
| name   | varchar(20) | YES  |     | NULL    |       |
| salary | float       | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.001 sec)

4.5.1 复合主键 primary key (字段1,字段2)

复合主键:如果有多个字段作为主键,可以使用复合主键,这些字段合在一起是一个主键,也就是让多个字段联合在一起作为唯一标识单个字段主键重复是没有问题的,只要不是成为复合主键的字段一起冲突就行

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.023 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    |       |		#将ip字段和port字段复合起来
| port     | int unsigned | NO   | PRI | NULL    |       |
+----------+--------------+------+-----+---------+-------+
4 rows in set (0.002 sec)mysql> insert into t2 values(1,'node1','192,168,48,2',120);
Query OK, 1 row affected (0.005 sec)mysql> select * from t2;
+------+----------+--------------+------+
| id   | hostname | ip           | port |
+------+----------+--------------+------+
|    1 | node1    | 192,168,48,2 |  120 |
+------+----------+--------------+------+
1 row in set (0.001 sec)mysql> insert into t2 values(2,'node2','192,168,48,3',120);
Query OK, 1 row affected (0.002 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'	 

4.5.2 主键自增长 auto_increment

作用:给主键添加自增长的数值

注意:

  • 自增长字段必须是整数,自增长字段可以 不设置初始值,默认从1开始递增.
  • 自增长字段也可以插入数据,只要不与已有数据重复即可,之后新增数据会从最大值开始递增
  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 一张表当中最多只能有一个自增长的列
  • 约束的字段必须具备 NOT NULL 属性
mysql> select * from t5;
+----+------+--------+
| id | name | salary |
+----+------+--------+
|  1 | Li   |   5984 |
+----+------+--------+
1 row in set (0.000 sec)# 先增加主键
mysql> alter table t5 modify id int primary key;
Query OK, 0 rows affected (0.092 sec)
Records: 0  Duplicates: 0  Warnings: 0# 设置自增长
mysql> alter table t5 modify id int auto_increment;
Query OK, 1 row affected (0.022 sec)
Records: 1  Duplicates: 0  Warnings: 0mysql> desc t5;
+--------+-------------+------+-----+---------+----------------+
| Field  | Type        | Null | Key | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| id     | int         | NO   | PRI | NULL    | auto_increment |
| name   | varchar(20) | YES  |     | NULL    |                |
| salary | float       | YES  |     | NULL    |                |
+--------+-------------+------+-----+---------+----------------+
3 rows in set (0.002 sec)mysql>  insert into t5(name) values('关六');
Query OK, 1 row affected (0.003 sec)mysql> select * from t5;
+----+--------+--------+
| id | name   | salary |
+----+--------+--------+
|  1 | Li     |   5984 |
|  2 | 关六   |   NULL |
+----+--------+--------+
2 rows in set (0.001 sec)

指定自增长的起始值:如果第一条记录设置了该字段的初始值,那么新增加的记录就从这个初始值开始自增

例如,如果表中插入的第一条记录的 id 值设置为 5,那么再插入记录时,id 值就会从 5 开始往上增加

4.6 外键约束 foreign key references

作用:限定某个表的某个字段的引用完整性(Referential Integrity:例如:员工所在部门,在部门表中要能找到这个部门)

  • 主表(父表):被引用的表、被参考的表
  • 从表(子表):引用别人的表,参考别人的表
  • 外键:从表中的某个字段引用自主表的某个字段或多个字段
  • 引用键:主表被引用的字段

外键约束主要定义在从表上,主表则必须是有主键约束或唯一键约束当定义外键后,要求外键列数据必须在主表的主键列存在或为 NULL

格式:

foreign key (从表的字段名称) references 主表名字(主表的字段名称) # 建立外键关联
  • 主表必须已经存在于数据库中,或者是当前正在创建的表。如果是后一种情况,则主表与从表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性
  • 必须为主表定义主键
  • 主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这个外键的内容就是正确的
  • 主表的表名后面指定列名或列名的组合。这个列或列的组合必须是主表的主键或候选键
  • 外键中列的数目必须和主表的主键中列的数目相同
  • 外键中列的数据类型必须和主表主键中对应列的数据类型相同

定义从表的时候,设置外键其实就是设置了一个关系,在从表当中插入数据的时候,会对插入数据进行校验,校验插入的数据是否存在于主表字段当中,外键就是增加了表和表之间的约束关系

# 定义主表
mysql> create table myclass3(id int primary key, name varchar(20) not null comment '班级名');
Query OK, 0 rows affected (0.026 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.002 sec)# 定义从表: 外键:foreign key      references 
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.015 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.002 sec)# 主表中插入数据
mysql> insert into myclass3 values(10,'C++'),(20,'Java');
Query OK, 2 rows affected (0.003 sec)
Records: 2  Duplicates: 0  Warnings: 0mysql> select * from myclass3;
+----+------+
| id | name |
+----+------+
| 10 | C++  |
| 20 | Java |
+----+------+
2 rows in set (0.000 sec)# 从表中正常插入数据:
mysql> insert into myclass3_stu values(1,'Li',10),(2,'Sun',20);
Query OK, 2 rows affected (0.004 sec)
Records: 2  Duplicates: 0  Warnings: 0mysql> select * from myclass3_stu;
+----+------+----------+
| id | name | class_id |
+----+------+----------+
|  1 | Li   |       10 |
|  2 | Sun  |       20 |
+----+------+----------+
2 rows in set (0.001 sec)# 从表中插入没有班级的记录,受外键控制,报错
mysql> insert into myclass3_stu values(3,'wang',30);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`d1`.`myclass3_stu`, CONSTRAINT `myclass3_stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass3` (`id`))# 从表中,收到外键控制,可以使用NULL替代,表示没有分配班级
mysql> insert into myclass3_stu values(3,'wang',null);
Query OK, 1 row affected (0.004 sec)mysql> select * from myclass3_stu;
+----+------+----------+
| id | name | class_id |
+----+------+----------+
|  1 | Li   |       10 |
|  2 | Sun  |       20 |
|  3 | wang |     NULL |
+----+------+----------+
3 rows in set (0.000 sec)
在这里插入代码片

4.7 唯一性约束 unique

产生原因:一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键,唯一键就可以解决表中有多个字段需要唯一性约束的问题

作用:限制某个字段/某列的值不能重复

唯一键(unique)和主键(primary key)的关系:

  • 主键只能有一个,唯一键能设置多个
  • 主键用来查找,唯一键用来保证数据的完整性

创建表时实现:

mysql> create database d1;
Query OK, 1 row affected (0.007 sec)mysql> use d1;
Database changed
mysql> create table t4( id int primary key, name varchar(20) unique comment '名子不能重名,可以为空' );
Query OK, 0 rows affected (0.012 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.002 sec)mysql> insert into t4  values(1,'刘文');
Query OK, 1 row affected (0.007 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.003 sec)mysql> select * from t4;
+----+--------+
| id | name   |
+----+--------+
|  1 | 刘文   |
|  2 | 张磊   |
+----+--------+
2 rows in set (0.000 sec
  • 唯一键冲突,自增涨字段值不连续
# 设置id列为自增长
mysql> alter table t4 modify id int auto_increment;
Query OK, 2 rows affected (0.071 sec)
Records: 2  Duplicates: 0  Warnings: 0mysql> insert into t4(name)  values('张磊磊');
Query OK, 1 row affected (0.004 sec)mysql>  select * from t4;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 刘文      |
|  2 | 张磊      |
|  3 | 张磊磊    |
+----+-----------+
3 rows in set (0.001 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.004 sec)mysql> select * from t4;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 刘文      |
|  2 | 张磊      |
|  3 | 张磊磊    |
|  5 | 钱明      |
+----+-----------+
4 rows in set (0.001 sec)

4.8 检查约束 check

作用:检查约束(check)是用来检查数据表中字段值有效性的一种手段,一般用于设置值的范围

  • 创建表时设置检查约束:
# 设置约束:check(salary>0 and salary<10000)
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.023 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.002 sec)mysql> insert into t5 values(1,'Li',5984);
Query OK, 1 row affected (0.005 sec)mysql> insert into t5 values(1,'Li',5984);
ERROR 1062 (23000): Duplicate entry '1' for key 't5.PRIMARY'
  • 修改表时添加检查约束(add constraint)
# 格式:
alter table 表名 add constraint <检查约束名> check(检查约束);mysql> alter table t5 add constraint check_id check(id>0);
Query OK, 1 row affected (0.023 sec)
Records: 1  Duplicates: 0  Warnings: 0

4.9 删除约束

# 删除 not null约束
alter table 表名 modify 列名 类型;# 删除 unique约束
alter table 表名 drop index 惟一约束名;# 删除 primary key约束
alter table 表名 drop primary key;# 删除 foreign key约束
alter table 表名 drop foreign key 外键名;

五、MySQL库表设计(范式)

5.1 范式概念与三范式小结

范式( Normal Form )是指设计数据库时要遵守的一些原则

三范式小结:

  • 1NF:确保原子性,表中每一个数据都必须是不可再分的字段
  • 2NF:确保唯一性,每张表都只描述一种业务属性一张表只描述一件事
  • 3NF:确保独立性,表中除主键外,每个字段之间不存在任何依赖,都是独立的

三大范式之间,是递进的关系,后续的范式都基于前一个范式的基础上推行

5.2 第一范式(1NF)

原则:库表设计时为了确保原子性,其存储数据具备不可再分性

eg.

在这里插入图片描述

  • 在上述的学生表中,其中有一个student学生列,这一列存储的数据则明显不符合第一范式:原子性的规定,因为这一列的数据还可以再拆分为姓名、性别、身高三项数据,因此为了符合第一范式,应该将表结构更改为:
    image-20240812101624714

  • 如果不去拆分列满足第一范式,会造成什么影响?

    • 客户端语言之间无法很好的生成映射关系
    • 查询到数据后,需要处理数据时,还需要对student字段进行额外拆分
    • 插入数据时,对于第一个字段的值还需要先拼装后才能进行写入

5.3 第二范式(2NF)

原则:表中的所有,其 数据都必须依赖于主键,也就是一张表只存储同一类型的数据不能有任何一列数据与主键没有关系

eg.

image-20240812102001102

  • 虽然此时已经满足了数据库的第一范式,但此刻观察course课程、score分数这两列数据,跟前面的几列数据实际上依赖关系并不大,同时也由于这样的结构,导致前面几列的数据出现了大量冗余,所以此时可以再次拆分一下表结构:
    在这里插入图片描述

  • 经过上述结构优化后,之前的一张表被拆分成学生表、课程表、成绩表三张,每张表中的id字段作为主键其他字段都依赖这个主键。无论在那张表中,都可以通过id主键确定其他字段的信息,每张表的业务属性都具备“唯一性”,也就是每张表都只会描述了“一件事情”,不会存在一张表中会出现两个业务属性

5.4 第三范式(3NF)

原则:表中每一列数据不能与主键之外的字段有直接关系
eg.

image-20240812102313259

  • 比如这张学生表,目前即符合第一范式,也符合第二范式,但看最后的两个字段,department表示当前学生所属的院校,dean则表示这个院系的院长是谁。一般来说,一个学生的院长是谁,首先是取决于学生所在的院系的,因此最后的dean字段明显与department字段存在依赖关系,因此需要进一步调整表结构:
    在这里插入图片描述

经过进一步的结构优化后,又将原本的学生表拆为了院系表、学生表两张,学生表中则是只存储一个院系ID,由院系表存储院系相关的所有数据。至此,学生表中的每个非主键字段其他非主键字段之间,都是相互独立的,之间不会再存在任何依赖性,所有的字段都依赖于主键

5.5 巴斯-科德范式(BCNF)

规定了联合主键(多个列组成的主键)中的某值,不能与联合主键中的其他存在依赖关系

5.6 第四范式(4NF)- 消除表中的多值依赖关系

多值依赖:表中的字段之间存在一对多的关系,也就是一个字段的具体值会由多个字段来决定(一个表中至少需要有三个独立的字段才会出现多值依赖问题)

  • 第四范式就是为了消除表中的多值依赖关系

5.7 第五范式(5NF)/完美范式

建立在4NF的基础上,进一步消除表中的连接依赖,直到表中的连接依赖都是主键所蕴含的

5.9 第六范式(6NF)/域键范式

域键范式,也被称之为终极范式,但目前也仅有学术机构在研究,在生产环境中实际的用途也不

5.9 反范式 - 不遵循数据库范式设计

不遵循数据库范式设计的结构,就被称为反范式结构。

  • 遵循数据库范式设计优点如下:

    • 避免了大量的数据冗余
    • 节省了大量存储空间
    • 表整体结构更为优雅,能让SQL操作更加便捷且减少出错。

在这里插入图片描述

  • 范式概念:

    • 第一范式:原子性,每个字段的值不能再分
    • 第二范式:唯一性,表内每行数据必须描述同一业务属性的数据
    • 第三范式:独立性,表中每个非主键字段之间不能存在依赖性
    • 巴斯范式:主键字段独立性,联合主键字段之间不能存在依赖性
    • 第四范式:表中字段不能存在多值依赖关系
    • 第五范式:表中字段的数据之间不能存在连接依赖关系
    • 域键范式:试图研究出一个库表设计时的终极完美范式

六、MySQL数据库账户及授权

6.1 密码策略

查看数据库当前密码策略 — show variables like “%password%”;

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

查看密码设置策略 — SHOW VARIABLES LIKE ‘validate_password%’;

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检查长度、数字、大小写、特殊字符、字典文件
  • 设置密码强度检查参数set global 参数=值;
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)

修改密码:alter user '用户'@'主机' identified by '密码';

mysql> select user, host, plugin from mysql.user;  # 查看root用户信息mysql> alter user 'root'@'localhost' identified by '123456';
# 注意:主机名为localhost,远程主机为%mysql> flush  privileges;
Query OK, 0 rows affected (0.01 sec)

6.2 登录账户管理

mysql8 的账户权限管理原则:创建账户,再赋予权限

  • 用户信息存放在 mysql 数据库下的 user 表
mysql> select user();   # 查看当前的用户信息mysql> use mysql;mysql> show tables;mysql> desc user;# 查询 MySQL 数据库中 user 系统表中的特定用户信息          
mysql> select user,host,authentication_string from user;
  • user:用户名
  • host:允许该用户连接的主机(% 表示任意主机)
  • authentication_string 字段存储的是用户密码的加密哈希值(不是明文密码)

6.3 新建登录账户(create user ‘’@‘’ identified by ‘’)

create user 'username'@'localhost' identified by 'password';

username: 创建的用户名
localhost: 指定该用户在哪个主机上可以登陆,如果是本地用户可用 localhost ,如果想让该用户可以从任意远程主机登陆,可以使用通配符 %
password: 该用户的登陆密码

eg.

mysql> create user  'test1'@'localhost' identified by '123456';
# 注意:密码要符合密码设置规则mysql> select user, host, plugin from mysql.user;  # 查看信息
# user:用户名
# host:允许该用户连接的主机(% 表示任意主机)
# plugin:该用户使用的身份验证插件mysql> exit
ByePS C:\Users\Administrator> mysql -u test1 -p
Enter password: ******    # test1账户登录mysql> show databases;   # 只能看到有限的库
+--------------------+
| Database           |
+--------------------+
| information_schema |
| performance_schema |
+--------------------+
2 rows in set (0.01 sec)

6.4 账户授权(grant)

作用:通过账户权限限制普通账户的工作范围内容,赋权原则如下:

  • root 账号绝对禁止允许任何IP都可以访问,即登录方式不能用%
  • 应用账号管理账号要分离
  • 赋权最小化,即一般只给 select 权限,最好不要给 update、insert 等编辑权限
  • 密码设置合理
  • 定期清理不使用的账户,将其收回权限或删除

常见的用户权限:

image-20230713173144352
image-20230713173215396

  • 查看权限
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默认权限即连接登录的权限
  • 赋权语法
grant 权限列表 on 数据库名.表名 to '用户名'@'来源地址' [identified  by '密码'];
  • 权限列表: 用户的操作权限,如 SELECT , INSERT , UPDATE ,CREATE 等,如果要授予所有的权限则使用 ALL
  • 数据库名: * 代表所有数据库
  • 表名: * 代表所有数据表
  • 用户名:指定哪个用户进行赋权操作
  • 来源地址: 指定该用户在哪个主机上可以登陆,如果是本地用户可用 localhost ,如果想让该用户可以从任意远程主机登陆,可以使用通配符 %
  • 示例1:赋权 test1 账户 select 查询权限
# 使用root账户登录
mysql -u root -pmysql> grant select on *.* to 'test1'@'localhost';  # 赋予mysql库的查询权限
Query OK, 0 rows affected (0.01 sec)mysql> show  grants for  'test1'@'localhost';mysql> select * from  mysql.user where user='test1'\G   # 查看user表的权限信息mysql> \q
Bye
PS C:\Users\Administrator> mysql -u test1 -p   # 重新登录
Enter password: ******mysql> show  databases;
  • 示例2:创建 test2 账户,设置密码,赋权 select 和 create 权限,仅通过某个网段登录
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.%';
  • 示例3:创建 test3 账户,设置密码,赋与所有权限(all所有权限中不包含给账户赋权的权限grant),仅通过%登录,登录后创建 test4 账户并赋权
PS C:\Users\Administrator> mysql -u root -pmysql> 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
ByePS C:\Users\Administrator> mysql -u test3 -p123456mysql> 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所有权限中不包含给账户赋权的权限grantmysql> exit
ByePS C:\Users\Administrator> mysql -u root -p  # 登录root账户给test3账户赋与给别的账户赋权的权限#### 给test3添加赋权的权限
mysql> grant all  on *.* to 'test3'@'%' with grant option;  # 给test3添加赋权的权限mysql> exit
ByePS 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> grant  system_user on *.* to  'root'@'localhost';  # 给root赋权system_user权限
# 注意:登录主机是%还是localhost

6.5 回收权限(revoke)

revoke 跟 grant 的语法差不多,只需要把关键字 “to” 换成 “from” 即可

revoke  权限列表/all  on  库名.表名  from  '用户名'@'来源地址';
# revoke跟grant 的语法差不多,只需要把关键字 “to” 换成 “from” 即可
  • 回收所有权限:
PS C:\Users\Administrator> mysql -u root -pmysql> 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'@'%';

6.6 删除账户(drop user ‘’@‘’)

drop user '用户名'@'访问主机名';
  • 删除所有账户
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> 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)

练习

# 查
show databases; #查看所有库
select database(); #查看当前库(使用的是函数)
show tables; #查看当前库的所有表
show #查看指定库的所有表#查看表结构
desc 表名; #查看表结构
show columns from 表名; #查看表结构select * from 表名; #查看此表的具体内容(字段、类型、约束)
select user(); #查看当前登录的用户和主机名
show databases; #查看所有库
create database 表名;#创建库
drop 表名; #删除、修改库
select database(); #查看当前正在使用的库
use 库名; #切换当前库
show tables; #查看当前库的所有表
create table 表名(字段[列名] 类型 约束,字段 类型 约束);#创建表#删除、修改表
drop table if exists 表名;
alter table 表名1 rename 表名2;
rename table 表名1 to 表名2#查看指定表的结构
desc 表名;
show columns from 表名;
select * from 表名; #查看指定表的内容alter table 表名 drop 列名 ;	#删除表的内容#增加表的内容
alter table 表名 change 列名1 列名2 类型; #修改列名#修改表的内容的列的位置
alter table 表名 add 列名 类型;
alter table 表名 add 列名 类型 after 列名;#指定位置,...之后
alter table 表名 add 列名 类型 first;第一列alter table 表名 modify 列名 新类型;#修改表的内容的列的类型#复制表结构
create table2 like1; #将表1的结构复制给表2
create table2 select * from1; #复制表1的结构和内容给表2
insert into2 select * from1;  #复制表1的结构和内容给表2(前提:两个表的结构必须一样)
http://www.dtcms.com/a/602992.html

相关文章:

  • 新西兰签证网站开发镇江网站建设费用
  • 网站搜索引擎优化公司vue手机网站开发
  • FunRec-Task2
  • 怎么把qq空间做成企业网站技术培训学校机构
  • Elasticsearch的快照生命周期管理(SLM)与索引生命周期管理(ILM)功能
  • 中国建设银行人才招聘官方网站电商网站建设思路
  • XRecorder 2.4.6.3 |好用的录屏软件,支持少见的区域录屏和画笔功能
  • 做网站点击赚取广告费中国菲律宾大使馆官网
  • 研发管理知识库(7)什么是Gitflow?
  • 优秀品牌策划方案ppt网站建站前seo注意
  • 重庆网站排名优化教程在线制作条形码免费生成器
  • 松江做网站公司wordpress app模板
  • 免费asp主机网站东营聊城网站建设
  • ubuntu 升级nginx的详细步骤(解决高危漏洞,执行补丁脚本太多,容易出错不如升级到高版本)
  • 做网站方法网站服务是什么
  • 箭头函数
  • 微算法科技(NASDAQ MLGO)开发基于优先级的区块链交易打包算法,提高云边协同计算环境下的交易效率
  • C语言编译单元:深入解析编译原理与优化技巧
  • 如何注册网站域名网站建设应具备的技能
  • 2025卷【模考】
  • 11.12(要学会提问)
  • 景观设计案例网站wordpress 游客访问
  • 【用户心得】SCANeR™Studio学习笔记(二):深挖AD/ADAS Pack——从传感器到场景的闭环验证
  • 可以做淘宝联盟的免费网站小企业网站建设收费
  • TB62262FTAG芯片应用和设计电路图
  • 网站app充值记账凭证怎么做织梦系统网站
  • 带后台自适应网站模版做公司网站的流程
  • 微信小程序app.eventBus.on发布-订阅模式(Publish-Subscribe)的实现
  • 数据科学每日总结--Day17--区块链
  • ERP系统性价比厂家