MySQL 大师之路**数据库约束,表设计,CRUD**

文章目录

  • [*1. 前言*](#1. 前言)
  • [*2. 正文*](#2. 正文)
    • [1. CRUD Update(修改)](#1. CRUD Update(修改))
      • [1.1 语法](#1.1 语法)
      • [1.2 示例](#1.2 示例)
    • [2. CRUD Delete(删除)](#2. CRUD Delete(删除))
      • [2.1 语法](#2.1 语法)
      • [2.2 示例](#2.2 示例)
      • [2.3 注意事项](#2.3 注意事项)
    • [3. 数据库约束](#3. 数据库约束)
      • [3.1 约束类型](#3.1 约束类型)
      • [3.2 特殊的约束 -主键约束](#3.2 特殊的约束 -主键约束)
      • [3.3 外键约束](#3.3 外键约束)
      • [3.4 CHECK约束](#3.4 CHECK约束)
    • [4. 表设计(范式)](#4. 表设计(范式))
      • [4.1 范式的定义](#4.1 范式的定义)
      • [4.2 第一范式 1NF](#4.2 第一范式 1NF)
      • [4.3 第二范式 2NF](#4.3 第二范式 2NF)
      • [4.3 第三范式 3NF](#4.3 第三范式 3NF)
    • [5. 表设计(数据关系)](#5. 表设计(数据关系))
      • [5.1 一对一关系](#5.1 一对一关系)
      • [5.2 一对多关系](#5.2 一对多关系)
      • [5.3 多对多关系](#5.3 多对多关系)
  • [*3. 结语*](#3. 结语)

Everything will get better, what you should do to beleve that !

1. 前言

通过前面的学习,我们已经掌握建立数据库,建立数据表,并在此基础上学习了'CRUD'中新增和查询,下面我们要继续学习CRUD剩余部分,并且讲解数据库约束的知识


2. 正文

1. CRUD Update(修改)

1.1 语法

语法:update 表名 set column =exper where... order by ... limt...

我们注意这里的 column=exper是将表中一个列的值修改成另一个值,后面必须跟着where 条件,否则将会全部修改,是一个非常危险的操作!

1.2 示例

1. 将孙悟空同学的数学成绩变更为80分

先分析问题,要把数学成绩改为80分,则math = 80,而条件是名字为孙悟空的同学,所以要加where条件!!

这里要是省略where条件,所有的同学的数学成绩都将改成80分


2. 再插入一条名字为孙悟空的同学,再次修改数学成绩为85分

这里我们看到两条语句生效,说明新插入的孙悟空同学由于名字重复,符合where条件都进行了修改


3. 将曹孟德同学的数学成绩修改成60分,语文成绩修改成70分

要修改多个字段时,仅需要用逗号隔开即可


4. 将总成绩倒数前三的同学的数学成绩减 30 分

首先以上三位同学是总成绩倒数前三的同学

由于孙大圣的英语成绩为 NULL,NULL 参与运算的结果还是为 NULL,这里注意一点:在 update 加 order by 再加 limit 语句时,limit 不需要指定起始点 start 为多少!! 这是 Mysql 的官方规定,UPDATE 语句中 LIMIT 只支持单参数写法!

这点非常重要也是多数人忽略的一点!


5. 把所有语文成绩低于 50 分的同学的语文成绩更新为原来的两倍

我们先插入三条新的数据,里面包含语文成绩小于50 分的同学

武松的语文成绩还是为 0,但是确实执行了操作,Mysql 是根据结果判断是否对数据行产生影响

这里我们总结一点:Update 的操作是在原表的基础上进行的修改,而不是在临时表中修改!


2. CRUD Delete(删除)

2.1 语法

语法: delete from 表名 where 条件 order by ... limit ...

删除这个操作也是在原表的基础上删除!

2.2 示例

1. 删除孙悟空同学的成绩

删除后表中孙悟空同学的数据就不存在了


2. 删除英语成绩倒数前三的同学所有的考试成绩

首先我们先查看一下英语成绩倒数前三的同学

这样孙大圣,马超,武松同学的成绩就被成功删除了


2.3 注意事项

delete删除操作如果不加where条件,也会将全表的所有数据全部删除! 是个非常危险的操作,在生产环境中一般不是用这个操作,而是加一个deleteState字段,用来标记是否删除

delete跟着limit分页操作,也不允许添加起始条件!只需要写条数即可!

以上CRUD所有的操作都讲解完毕,其中查询操作难度稍微大一点,剩余操作都非常简单


3. 数据库约束

数据库约束是关系型数据库一个非常重要的功能,保证了数据的完整性,正确性(数据本身是否正确,关联关系是否正确) ,由于人工检查数据完整性的工作量太大,在数据表中定义一些约束,那么数据库写入数据时,数据库(不是数据库服务) 会帮我做检验工作

约束是指定在列(字段)上的!

3.1 约束类型

1). NOT NULL "非空约束",指定某列不能存储NULL值

我们之前panxon123数据库中有一个数据表student,当时建表时只指定了字段和字段的数据类型,并没有为其添加任何约束,所以当用desc语句查看数据表时,就会发现以上内容

如果想要新添加进来的数据指定不可以为空,则要使用到NOT NULL约束

约束的语法直接在数据类型后➕约束即可

新建立一个表student_2 并且约束id不能为空,此时插入一个NULL数据会发生什么呢?

我们会发现会报错,id不能为NULL


2). UNIQUE -唯一键,保证某列的每行必须有唯一的值 (某列的值在表中不能重复)

我们可以看到 student 表中有三个名字为张三且序号都为1 的同学,名字可能会重名但序号不会重复 ,如果序号重复则是不符合逻辑的,所以我们要加唯一约束,确保不会出现序号相同的人

我们新建立一个表 student_3,序号设定为唯一键约束

当再次插入编号相同的同学就会报错!

当然我们也可以查看一下表结构

这里我们用终端显示更加清楚,我们发现 Key 值变成了 UNI,这是 unique 的缩写,代表这一键是唯一键 ,什么是键呢? 键 就是用来快速找到数据、区分数据、关联表的 "标记 / 编号 ,这里注意,键只是一种约束的形式,后面我们会讲索引,索引与键是两个关键词,但经常放在一起说,两个概念要区分!


3). DEFAULT -规定没有列赋值时的默认值

例如当插入一个名字为空的同学我们可以使用默认约束,使名字为我们的指定值

新创建一个数据表 student_4 其中,id 使用了唯一键,name 使用了default 约束

当我们只规定插入的序号不规定插入的名字时,就会用到默认约束!

我们也可以查看一下表结构

这里就有一个问题了,如果我们插入了一个 名字为 NULL 的同学,他是会被当做名字还是空来对待呢?

这里我们发现插入的值依然是 NULL,因为这个 NULL 是我们手动指定的,也可以理解为我们想要的值,用户指定的优先级是要高于默认约束的!!

最后我们总结一点,当查看表结构时有六列,这六列是有=当 Key 中有约束才会被叫做键,其余只能叫做约束!


3.2 特殊的约束 -主键约束

PRIMARY KEY:主键约束的表示,是NOT NULL和UNIQUE的结合 ,确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定记录

1 ) 主键约束主要的作用就是把表中的某列设置为非空且唯一!

我们创建一个新的学生表,并且把id列设置为非空且唯一,这时我们查看一下表结构

当我们查看表结构时,我们会发现Key值变成了PRI,这就是主键约束的缩写!id列就是一个主键!

我们经常使用的是primary key关键字来作为约束而非使用not null加unique

我们新创建了一个 student_6 学生表,里面包含三个字段,并且 id 为主键约束,name 为非空约束,sn 学号为唯一键约束

当插入编号相同的同学时,就会报错,这是唯一键约束的作用

非空约束也是同样适用的!

总结一下 :主键约束帮助我们校验了非空和唯一,这两个校验在写入数据是对效率是有一定影响的但是比起不做校验来说,这个性能消耗是可以承担的,而且主键对索引有非常重要的作用,所以我们在定义一张表时最好都加入主键,且主键尽量都为 id 列


2 ) 主键自增约束

在我们创建一张表时,每次都需要自己设置主键的值是非常麻烦的,所以我们可以把主键设置为自增主键,主要是用 auto_increment关键字

我们再查看一下 student 的表结构

这里 Extra 列中标识了 id 为 auto_increment 自增列

插入两条数据时,并没有指定 id 值,Mysql 根据id 的主键自增生成了 id 的值

下面问题来了,如果插入的同学 id是 NULL,Mysql 会如何处理呢?

这里的 NULL 被 Mysql 直接处理了,可上面的default 约束却把 NULL 当成名字直接使用,这里为何会被处理?因为这里不是把 NULL 写入数据库,而是让数据库去帮我们处理这个值

那么可不可以指定一个主键值呢?

可以的,但是下一次新插入的数据编号是从 100 起还是 3 起呢

结果是从 100 起继续递增的,所以主键自增都是在最大值的基础上+1,并且主键值在数据表有可能是不连续的

下面我们看一下 Mysql 是如何处理不同的多个主键值区间的

Mysql会为每台服务器都预先分配一区段的主键值,添加的主键值是自定义主键值会根据不同的服务器提供的主键值区间去匹配

此外自增主键这块有一个非常容易令人忽视的一点! ! !

现在我们的 student 表中 id 字段是一个自增主键

以上是表中的数据,我们知道如果再添加一个数据并指定 id 字段为 NULL,Mysql 会自动填充其为 102,但是!!如果把王二麻同学的数据删了,再次添加一个同学信息并且不指定 id,那么 Mysql 会填充它为多少?

我们发现新添加的测试用户 id 竟然还是 102 ,这是因为当进行 insert 操作时,都会先生成一个主键值,不论记录写入成功与否,这个主键值都会被视为已使用!如果删掉其中一条数据在写入数据时,就会发现主键值不连续!


3 )复合主键

首先一个表中是不允许有两个主键的

但是 Mysql 允许一个主键包含多个列

这样 id 和 name 就组成了一个复合主键,当一个表中有复合主键并想要插入数据时,只要复合主键的其中一个字段的值不同即可插入成功

插入序号相同但名字不同,或者序号不同名字相同的数据都是可以的!


3.3 外键约束

FOREIGN KEY ... references...:外键约束的表示

1)外键的作用

外键用于关联其他表的主键或唯一键,下面我们看如何创建一个外键

首先创建一个主表班级表

其次创建一个学生表其中标有class_id用来与主表做关联

以上是大致的描述图,我们查看一下student_1表结构

Key 中的 MUL代表了表中当前字段存在外键关系,下面我们为两张表插入数据,观察如何体现外键关系

先在 class 表中创建三个班级

成功插入四条学生的基本信息,且包含 class_id,如果插入class 表中不存在的班级序号会发生什么呢?

发现报错了,报错信息写class_id 与 id 字段有着主外键关系,所以不能插入主表中没有的数据

通过外键的约束,保证数据的完整性和关系的正确性!!


2)外键约束时,删除表中数据

当子表对主表有依赖时,能否删除主表相应的记录呢

答案肯定是不可以的,如果要删除主表的记录,那么子表中不能有对该条记录的依赖,也就意味着要先删除子表的记录,再去删除主表的记录

这里小编就不拿删除记录来演示了


3.4 CHECK约束

CHECK约束是从Mysql8.0.16开始全面支持的,之前的版本会忽略CHECK的定义,所以这里我们只做一个简单的了解即可!

CHECK约束保证列中的值符合指定的条件,对于MySQL数据库,对CHECK语句进行分析,但是忽略CHECK子句 (在Mysql大版本8.0之前你写的CHECK语句,Mysql不会真正验证数据是否符合条件的,8.0版本之后都会检验)

下面我们演示CHECK约束的使用

gender用来存放性别,只可以为男或女

也是没有任何问题的,但是当我们插入一个性别为无会发生什么呢?

会报错,也就是Mysql 检验了 check 约束,如果小伙伴们有时间可以把大版本改成 5.3 试试同样的语句,Mysql会不会报错呢


4. 表设计(范式)

在数据库建立前,我们要设计数据库,设计数据表,这其中就包括重要的三点步骤

1)从需求中获取的类(Java定义的类),类对应数据库中的实体,实体在数据库中就表现为一张一张的表,类中的属性就对应着表中的字段

2)确定类与类之间的关系

3)使用SQL去创建具体的表

当然设计表时还要遵守一些特定的规则,我们称之为三大范式! 切记,只有关系型数据库才有三大范式这一规范,非关系型数据库不讲究范式


4.1 范式的定义

范式是描述数据关系的模型,数据关系又分为一对一关系,一对多关系(多对一关系),多对多关系,描述以上三种关系就要遵守三大范式的要求

三大范式分别为: 第一范式1NF,第二范式2NF,第三范式3NF

但是范式不仅仅是以上三种范式,甚至有第四范式,第五范式,BC范式等,满足越高的范式会使数据库的冗余更小,然而普遍认为范式越高虽然对数据关系有更好的约束性,但是会导致数据库IO更繁忙,所以满足三大范式即可


4.2 第一范式 1NF

第一范式是关系型数据库的一个最基本的要求,不满足第一范式就不可以被称之为关系型数据库

第一范式的规则 : 表里的字段不可再进行拆分

小编举一个例子来帮助更好的理解,下面有两个设计出来的学生表,哪一个满足第一范式的规则呢?

通过学生表1和学生表2的对比,学生表1中学校这一字段是可以拆分为学校名和学校地址等,而学生表2无法再次将其中的字段进行拆分,所以学生表1不满足第一范式规则,学生表2是满足第一范式规则的。

这里注意,在定义表时,要对照到数据中的数据类型,如果每个字段都能用一个数据类型表示,那么当前这个表是天然满足第一范式的


4.3 第二范式 2NF

第二范式规则是在满足第一范式的基础上,不存在非关键字段对任意候选键的部分函数依赖( 存在复合主键的情况下)

这里的非关键字段代表非主键字段 ,候选键代表主键,外键,和没有主键外键时的唯一键统称为候选键

1) 满足第二范式规则的表

示例:设计一张或多张数据表,内容有学生可以选修课程,课程有对应的学分,学生考试后会针对每一门选修课生成相应的成绩,用数据库中的表记录学生的成绩

第一种方案:

直接使用一张表包含学生信息,课程信息,分数信息,但是这种方案是有很大的问题的!

学生相关的信息可以通过学号绑定,学分可以通过课程确定,成绩是通过学生和课程共同区分的,一个学生选修的课程经过考试才会生成成绩!

也就是这个表中可以用学生和课程作为复合主键来确定同学当前选修课的成绩

但是学生的姓名,年龄与课程无关;学生的姓名,年龄只依赖于学号,不依赖于课程;

学分也不依赖于学生,只依赖于课程

对于以上这种情况 有两个或多个关键字段决定一条记录的情况,如果一行数据中有些字段只与关键字段中的一个有关系,那么就称之为部分函数依赖,即不满足第二范式


第二种方案:

设计三张表分别表示学生,课程,成绩信息,这样设计每张表都有非主键字段,且强依赖于主键,并满足第二范式

也就是说一个表中如果没有复合主键(主键只有一列),那么这个表天然满足第二范式


2)不满足第二范式会出现的问题

以上是一张不满足第二范式的数据表,那么它会出现什么问题呢?

1 数据冗余

学生姓名,年龄,学分都重复出现,造成了大量的数据冗余

2 更新异常

如果要调整 MySQL 课程的学分,那么就需要更新所有记录中关于 MySQL 学分的记录,如果一旦出现某些记录更新成功,某些记录更新失败,就会造成数据表中同一门课程不同学分的情况,呈现出数据不一致

3 插入异常

目前的设计,每一门课与同学进行考试是对应关系,只有同学进行考试才会生成这门课的成绩记录,这条记录中保存了课程的学分,也就是说如果有一门新课开展,开展之前在数据库中是没有相应记录的,因为学生成绩为空时的记录没有意义,这样就造成了插入的异常

4 删除异常

如果把已经毕业的同学成绩全部删除后,删除记录的同时有可能把课程对应的学分全部删除了,导致一段时间内,数据库中没有对应课程和学分的相应信息(例如 选修 MySQL 的同学今年全部毕业了,就要删除这些同学的数据,那么可能就会导致 MySQL 课程信息一并删除,明年选修 MySQL 的同学就找不到这门课了)


4.3 第三范式 3NF

第三范式规则 :需要在满足第二范式的基础上,并且不存在非关键字段对任一候选键的传递依赖

什么是传递依赖? 下面看示例

示例: 设计一个描述学生就读哪个学院的数据表

方案一:

因为需要描述的是学生,所以明显的判断出学号是这个表的主键!不存在复合主键,所以满足第一第二范式的

在这个表的设计中,姓名和年龄与学号强相关;学院地址,学院电话与学院强相关,在这两种强相关关系,判断是否出现了传递性质的依赖

确实出现了传递现象,通过学号能判断出所在学院,所在学院可以判断出地址和电话,所以存在了非关键字段对候选键的传递依赖,即不满足第三范式


方案二:

根据学生与学院的关系,拆分为两张表,这样设计两张表都依赖于自己表中的主键,学生表可以通过外键建立关系,并且满足第三范式!

第三范式可以更好解决数据冗余,插入异常,更新异常,删除异常的问题


5. 表设计(数据关系)

5.1 一对一关系

一对一关系一般对应两个实体,例如用户登录csdn账号,用户是一个实体,账号是一个实体;用户中记录个人信息,姓名... ;账号中记录登录名,密码 并且一个用户只能有一个账号,一个账号也只能给一个用户使用,不能共享!在我们设计表前要先把实体之间的关系列出来,针对一对一关系设计表有两种方式:

1)把两个实体的所有信息全部放在一张表里 (不推荐)

user(user_id, name, age, phone_number,mail //用户信息 usename, password//账号信息);

2)创建两张表,分别记录用户信息和账号信息,再把两张表做关联 (推荐)

也就是用户和账号分别有各自的主键,并建立了外键的联系


5.2 一对多关系

例如学生和班级之间的关系,一个班级可以有很多个学生,一个学生只存在于一个班级,那么学生和班级就是一个一对多关系;这里一对多关系和多对一关系是相同的,站在学生的角度,学生与班级之间是多对一关系;站在班级的角度,班级与学生之间是一对多关系

针对一对多关系设计表要 注意主表和子表的区分

例如创建一个学生表

所以我们要把班级作为主表,学生表作为子表来建表

首先我们建立班级表,并且指定id列为主键

之后建立子表学生表并建立外键关系,这样就是一个学生和班级就是一个一对多关系


5.3 多对多关系

一个学生可以选修多门课程,一门课程也可以被多名学生选修,这样的关系我们称之为多对多关系

这个图很清晰的说明了,多对多关系一般都有一个中间表,这里的中间表也可以是成绩表,与学生表和课程表都有一定关系的表

下面我们看设计上图的三个表

学生表

课程表

中间表

以上就是学生与课程多对多关系的设计表


3. 结语

以上就是本文主要的内容,我们学习了数据库CRUD中剩余的两个部分,以及数据库约束,范式,表设计,下面小编会讲解联合查询,聚合函数也是数据库中比较难的部分,有不明白的地方可以留言小编会回复,希望读者们多提建议,小编会改正,共同进步!谢谢大家。 🌹🌹🌹

相关推荐
HealthScience2 小时前
clinvar数据集说明
数据库·oracle
Indoraptor2 小时前
SurfaceFinger FrameTimeline 分析
android·源码阅读
王的宝库2 小时前
【MySQL】主从复制原理详解:从 Binlog 到数据一致性
数据库·mysql
Vect__2 小时前
MySQL基本认知、库和表的操作
数据库·mysql
cyber_两只龙宝2 小时前
【Oracle】Oracle之DQL中SELECT的基础使用
linux·运维·服务器·数据库·云原生·oracle
老苏畅谈运维2 小时前
Oracle 在线表重定义:将非分区表转换为分区表的最佳实践
数据库·oracle
treacle田2 小时前
达梦数据库-达梦数据库中link链接访问oracle 19c/11g-记录总结
数据库·oracle·达梦 link访问oracle
zh_xuan2 小时前
Android 待办事项增加事项统计
android
萌兰三太子2 小时前
RAG 向量数据库设计指南:从入门到生产
数据库·oracle