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

MySQL基础(四)

目录

一. 数据库的“约束”

1.1 NOT NULL

1.2 UNIQUE

1.3 DEFAULT 

1.4 PRIMARY KEY (主键)

1.5 FOREIGN KEY(外键)

注意事项1: 父表 "制约" 子表

注意事项2: 子表 "制约" 父表

注意事项3: 存在主键/unique约束

注意事项4:  逻辑删除

1.6 CHECK (了解)

二. 表的设计

2.1 明确实体

2.2 明确实体间的关系

1) 一对一关系

2) 一对多关系

3) 多对多关系


一. 数据库的“约束”

    数据库中的数据是如此重要,我们希望数据库存储的数据,不要存在“错误”数据,因此要做出一些 “限制” “要求”,对数据库中的数据进行校验检查。

    数据库的约束 是数据库管理系统(DBMS)用来保证数据库数据完整性和正确性的一套规则。它们确保了插入、更新或删除数据库中的数据时,数据满足特定的业务规则或条件。

约束类型

1.1 NOT NULL

指示某列不能存储 NULL

1.2 UNIQUE

保证某列的每行必须有唯一的值

 * unique 如何知道数据存在重复呢?  —— 插入 / 修改 之前先进行查询

duplicate --> 重复的    entry --> 条目 ( 与Map遍历的 entrySet 中的 entry 一个意思)

1.3 DEFAULT 

规定没有给列赋值时的默认值

1.4 PRIMARY KEY (主键)

NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识( “身份标识”),有助于更容易更快速地找到表中的一个特定的记录。(主键 同样也会在修改 / 插入的时候触发查询)

一个表中 不允许同时存在多个主键(多个“身份标识”)假设有多个主键,主键1相同但主键2不相同,就不是唯一的“身份标识”了。 但数据库允许把多个列共同作为一个主键(“联合主键”),暂时不过多讨论。

 * 主键需要分配一个唯一的值,如何进行分配呢?—— MySQL 提供了 自动分配主键的方式 “自增主键”  auto_increment  插入数据时,可以不指定 id 列的值,让数据库自动分配,就会按照1,2,3,4 .....依次累加。同时也可以手动指定主键数值,与自增主键并不冲突。自增主键只能针对像 int / bigint 的整数。

    大部分情况下都是用数字作为主键,但也有可能使用字符串作为主键,比如 数据量特别大,不是一个 mysql 数据库,而是多个 mysql 构成的 分布式“集群”

    像大公司,每天处理的数据量很大,一台机器是无法存储完成的(即使我们使用的机器配置很高,可以加很多个硬盘),此时就可以引入多个机器,每个机器上只存储一部分数据

    应用程序插入数据的时候,有一个计算规则,来对数据进行区分,判断这个数据是存储在哪个机器上。虽然在多个数据服务器上存储数据,但仍然希望这些数据的 id 这一列,是唯一的,此时 mysql 自增主键就难以胜任了(自增主键 只能在一个机器上的 mysql 生效,不能跨主机生效) 

    此时,就会把 id 指定成字符串类型,然后通过应用程序里面的一系列算法,生成一个 “唯一的字符串 id” (生成方式有很多,比如 uuid/雪花算法....)

“分布式系统唯一id生成算法” —— 引入各种信息,综合这些信息,最终得到一个唯一的值(这些信息包括不限于时间戳,主机的机房编号,主机的编号,随机因子....)

当删除插入的数据,再次插入新的数据,默认分配的主键会从曾经指定过的最大数值开始自增  (在 MySQL 中,给每个表都记录了一个 “自增主键的最大值”,后续想插入数据,无论之前的最大值是否存在,都是根据之前保存的最大值,继续往后分配的)

1.5 FOREIGN KEY(外键)

两个表之间的关联关系,保证一个表中的数据匹配另一个表中的数据。(例如,有 商品表( 商品id, 商品名字....) 和 订单表( 订单id, 商品id...) , 订单表中的商品 id 必须在商品表中的商品 id 存在 )


注意事项1: 父表 "制约" 子表

    学生表的 classId 列 引用自 班级表的 classId 列,即 班级表(制约的一方)中的数据,约束/制约 了学生表(被制约的一方)的数据,称 制约的一方 为父表,被制约的一方 为子表再次往 student 中插入数据,就务必要确保插入的数据的 classld 值,得在 class 表中存在。

mysql 是如何 判断插入的 classId 数据是否在 class 表中的 classId 中呢?—— 往 student 插入的时候,会触发针对 class 表的查询。 


注意事项2: 子表 "制约" 父表

    父表是约束了子表,同时 子表 也会对父表 反向进行约束,必须保证 子表与父表 的关联关系始终存在。如果父表中的某个记录被子表引用了,就不可以随便删除父表中对应的记录。

     删表时,要确保先删除子表,再删除父表,确保依赖顺序正确。


注意事项3: 存在主键/unique约束

    指定外键的时候,后续往子表中插入数据,就要查询父表。因此,插入成功 是建立在 查询成功 的基础之上,为了加快查询速度,就要对查询的列指定 主键

    主键本身也是有 “唯一性要求” 的,频繁触发查询,数据库就会对主键约束,给出特殊的处理(数据库会针对 主键 列,创建索引)加快了查询速度。

    如果不指定主键,是一个 unique 也能达成类似的效果。因为 unique 与 主键都是要自动建立索引,以便于后续的快速查询。 


注意事项4:  逻辑删除

考虑以下场景: 

商品表(goodId, goodName, price....)

订单表(orderId, goodId....)

如果过了一段时间,店铺不卖铅笔,改卖圆珠笔了,把铅笔下架了~~
 

下架操作该如何完成呢??

  • 直接删除,不行的(因为 order 子表中存在 good 中的值,无法直接删除父表good的值)
  • 如果不用外键,就可以删除了;但针对其他插入的数据,缺少了校验过程,不合适

此处真正的解决方案——逻辑删除!!

在商品表中添加额外的一列

商品表(goodId, goodName, price,isOk int....):

  • isOk 设为 0 表示无效商品
  • isOk 设为 1 表示有效商品

后续如果查询商品列表 --> select * from good where isOk = 1; (添加查询条件,确保用户看到的商品都是在线的商品)

同时,用户也可以看到之前的订单信息

和顺序表尾删是类似的效果,尾删直接 size--

    采取逻辑删除,硬盘空间并没用真正释放,随着数据越来越多,硬盘是不是就被用完了?—— 如果用完了,就继续加硬盘,如果加了硬盘还不够,加机器就好。因为硬盘成本低,如果因为为了节省硬盘空间,写了一堆复杂代码,出了问题,造成的损失比硬盘成本要大得多!!

    逻辑删除 在很多地方都会涉及到,比如 电脑删除文件 本身就是一个逻辑删除。执行这个删除,对应文件中的内容其实在硬盘上仍然存在,只不过把对应的硬盘空间,标记成“未使用”,直到后续有其他文件 写入硬盘的时候,恰好用到了这块空间,才会把这里的数据覆盖掉

    彻底删除文件 --> "物理删除",销毁硬盘。

1.6 CHECK (了解)

    可以指定一个详细的条件, 保证列中的值符合指定的条件。( 例如 有一列 "性别" varchar(1), 此时要求填入的性别只能是 '男' 或者 '女' , check 可以写一个条件( name = '男' or name = '女'), 此时进行插入 / 修改操作, 就能够带入到上述条件中, 检查是否成立 ) 

    MySQL数据库不支持check,检查条件不会生效,但是写了 check 不会报错;Oracle 对于 check 有很好的支持。实际开发中,如果也想进行类似的校验,MySQL 只能通过搭配 C++ / Java 这样的代码,在插入数据之前,先进行判断。


 * 每次修改一个约束,都需要重新创建表吗?    alter table .... 可以修改表的结构,但是不建 议使用 alter 。表规模比较小就好办,直接 alter 就行 ;表规模比较大 (百万级别),alter 操作很容易把数据库搞挂了的~~


    在数据库管理中,arter 语句是用来修改数据库中已存在表(table)的结构的一个SQL命令。它可以用来添加、删除或修改表中的列(字段),也可以用来添加或删除各种约束,如主键、外键、唯一性约束等。


    虽然一般是尽可能在最初的时候,就把表结构设计好,但也无法避免可能需要调整。对于服务器系统来说,稳定性可用性是非常重要的,对数据库进行修改表结构操作,就相当于给一个正在飞的飞机 更换发动机一样。

一般会使用 “偷梁换柱” 的方式来完成:

  1. 申请一个新的机器,搭建好数据库环境,把数据库里面的表结构都创建好(已经添加好新的列)
  2. 把旧的数据库中的数据,导入到新的机器中 (导入的过程中注意,对于旧的数据库,不要读的太快,千万不要把旧数据搞挂)
  3. 当所有数据同步完毕之后,就把应用程序中,访问旧数据库的代码,切换成访问新数据库的代码

二. 表的设计

     表的设计,比较抽象,依赖一定的经验。如何创建表,要根据实际需求场景,梳理清楚应该创建几个表,每个表有哪些列,以及多个表之间存在的关系。 在实际项目的环节,会存在更多的实体,更多的表,以及更复杂的关系....

2.1 明确实体

    基本切入点:梳理清楚需求中的 “实体”(对象) 和 “关系”。

如何“找对象”?

  • 分析需求场景,提取出一些 “关键的名词”
  • 确定对象的属性和方法:对象有哪些信息需要保存,以及需要针对这些信息进行哪些 “加工操作”

    找对象的过程,本身也就是把现实中的东西,使用代码的方式 “抽象” 出来。现实中的东西,通常是非常“具体”的,涉及到的信息量非常多,但编程写代码解决问题的时候,不需要把所有的信息都使用到,只需要关注用到的信息即可(提取关键信息)。信息量越少,就越抽象;信息量越多,就越具体。
    确定 “实体” --> 找到关键名词,提取出一些需要用到的信息。有几个实体,一般就会有几个表,每个实体使用一个表来表示(也不绝对)。梳理实体之间的关系,根据这里关系需要对于表做出一些特殊的设定。

2.2 明确实体间的关系
1) 一对一关系
  • 一个学生,只能有一个账号
  • 一个账号,只能被一个学生持有

设计表的做法:

  • 一个表  同时包含学生和账号的信息:student_account(studentld, name, accountName, password....)
  • 两个表  使用 id 来进行联系:
    student(studentld, name, accountld)     account(accountld, accountName, password)
    或者
    student(studentld, name)    account(accountld, accountName, password, studentld)

具体如何设计表,要根据实际开发的需要,怎么方便简单怎么来。 

2) 一对多关系
  • 一个学生只能属于一个班级
  • 一个班级可以包含多个学生 

 

3) 多对多关系
  • 一个学生,可以选择多门课程学习
  • 一门课程,也可以被多个学生选择

引入关联表,通过关联表把多对多关系表示出来


http://www.mrgr.cn/news/68800.html

相关文章:

  • 股指期货交易中,如何应对震荡行情?
  • 【论文阅读】火星语义分割的半监督学习
  • docker快速安装与配置mongoDB
  • 第N6周:中文文本分类-Pytorch实现
  • Backend - Python 爬取网页数据并保存在Excel文件中
  • OkHttp网络请求框架
  • 复杂度的讲解
  • 五分钟使用 CocosCreator 快速部署 TON 游戏:开发基于 ZKP 的游戏
  • 【java】哈希<两数之和> 理解哈希
  • 常见二极管结构及其应用详解
  • 人员密集场所遇到突发火灾事故该如何应对
  • apk因检测是否使用代理无法抓包绕过方式
  • 代数几何教皇Grothendieck经典著作:代数几何基础FGA法语原版+英文译版
  • ES6标准-Promise对象
  • Vue Element-UI 选择隐藏表格中的局部字段信息
  • 气象监测软件的程序设计
  • 深度学习⑨GANs
  • 【划分型 DP-最优划分】【腾讯笔试压轴】【hard】力扣132. 分割回文串 II
  • 一文学会easyexcel导入数据,多sheet页、字典转换【附带源码】
  • 【动手学电机驱动】 STM32-FOC(2)STM32 导入和创建项目
  • 转发forward与重定redirect
  • SpringCloud框架学习(第一部分:初始项目搭建)
  • 【手撕排序3】归并排序
  • 详解Windows 11 上 CUDA 与 PyTorch 版本的兼容性
  • 谷歌新政,照片和视频访问权限新规?声明表单怎么写更容易通过审核?
  • Linux常用的100个命令