数据库设计实例---学习数据库最重要的应用之一
一、引言【可忽略】
在学习“数据库系统概述”这门课程时,我一直很好奇,这样一门必修课,究竟教会了我什么呢?
由于下课后,,没有拓展自己的眼界,上课时又局限于课堂上老师的讲课水平,我一直不理解这门课的意义。
我在其中学会了什么呢?坦言,有不少新名词:
比如范式、事务、码、集合运算等等。
可是,在实际应用中,我发现课堂上讲到的,只有我早就学过的SQL语句会真正使用。
也就是增删改查,SELECT、DELETE、UPDATE和INSERT四个语句。
后来从需求文档开始开发一个项目,我也是懵懵懂懂,由于队友提前把数据库建好了,我并没有学到建立数据库的知识。
也是某次契机,面试时面试官询问:你如何设计这个数据库的?
于是回去我恶补了一下,花了半个星期,终于把我学过的知识联系起来。
数据库设计:是比使用SQL语句更重要的知识,因为使用SQL语句的基础,先是有一个数据库,有一些表。
二、数据库建立的六个步骤和笼统的对应目标
正如解数学题一样,数据库的建立也有其流程,如下:
第一步,需求分析。
该步骤从实际出发,成果物是一份需求文档【专业名词叫“用户需求规格说明书”】。
重点在于,拿到用户的数据需求和数据处理需求。【简单地说,就是你要存什么数据(比如一个学生类),以及你要对这些数据做什么处理?(比如增删改查)】
在更实际的开发中,我们可能会涉及性能需求、安全需求,在此不赘述。
第二步,概念结构设计
这个词语很难理解,我认为可以叫做“模型设计”。
因为这一步的目标是,设计出一个“模型”,什么样的模型呢?
E-R实体联系模型。
这个模型,定义了这个数据库中,包含的实体、实体拥有的属性和实体之间的联系,有一些特殊实体,可能还会在联系中,加入一些特殊的约束。
第三步,逻辑结构设计
这个词语也不太好理解,你可以认为,这里的“逻辑”是指,从实体模型,转化为关系模型,抽象了一个层面,所以叫做“逻辑”设计。
这一步的目标,是得到可以作为数据库的关系模型。【关系模型的意思后面再讲】
我们拿到E-R模型后,根据一些转换原则,很容易拿到关系模型,但是不是所有关系模型,都能当数据库使用。
至少经过3步范式,才能设计出不容易出问题、面对异常处理比较好用的关系模型。
第四步,物理结构设计
这一步不是我们考虑的,更多是操作系统开发商和数据库开发商考虑的。
第五步,数据库的部署和测试
没什么好说的。
第六步,数据库的运维
无。
我们可以发现,从0到1的数据库开发,重点在于前3步。下面,我用一个实例来讲解如何进行。
三、客户需求【从0开始,可忽略本节,直接看末尾】
小明是个游戏开发人员,一直苦于如何将内购模式,加入自己的游戏。
有一天,他发现某团外卖平台的订单结构非常好,但是自己不熟悉如何设计,花钱请你帮忙开发。
你询问需求。
小明说:“我们的客户,每一个都是独一无二的,有属于自己的游戏ID、游戏名字、密码和手机号、邮箱等等。”
他又说:“某团的结构,也是这样,所以我们应该能互相转换。”
好,我们有了第一个实体,这是一份客户表。
你继续询问。
小明说:“内购模式,最大的问题是如何处理订单,因为游戏的装备很多,如果玩家A,一次性购买20个超级戒指、20瓶恢复药水。”
他顿了顿,说道:“我也学过一点数据库。对于上述要求,如果在一张表里存储,要不就用一个集合存储这些装备信息,要不就得在一张表,存储40个信息,可是玩家ID是主键,一张表里不可能有40个相同ID,更何况,这么做信息冗余很多,查找起来也麻烦。”
“所以,我想要一个独立的订单,它关联着用户。”
好,我们有了第二个实体,这是个订单表,也许它和客户表有联系,不过没有关系,目前不在乎。
游戏里有什么戒指、恢复药水的装备,以后可能还会增加一些装备,如果在订单表里,把所有装备都定义上,并且用另一列,管理它们的购买个数。【类似于HashMap的key、value思想】
可行,不过冗余较大。
你继续询问。
“没了。”
就此,你大概能知道需要那些东西。
------从这里开始看。
我们的问题是,如何将用户、订单和装备联系起来。
考虑这样的场景:玩家A,买了3个戒指、4瓶药水、100个卷轴,如何存储起来。
第一,一个用户表应该是必要的,至少要存储用户信息。
第二,订单表好像也需要,不过订单表里的内容,也许需要斟酌。
四、需求分析【真正分析】
由上面的场景,我们对每个实体分析一下数据需求和数据处理需求。
用户表基本没什么问题,为了一个订单表,把用户表全改了,是没必要的。
玩家A,可能昨天买了一单,今天买了3单,A与订单之间,明显是1对多的关系。
一个玩家,可以拥有n个订单。一个订单,只能属于一个玩家。
订单和装备呢?
用一张装备表,存储装备是个不错的想法,可是订单可能有n个装备,干脆用订单表存储所有的装备?
问题是:这样想要拓展装备,很麻烦。
当我们为这样的问题犹豫时,记住2个原则:
1.订单涉及的装备明显是个变量,一个变量作为表里的一个属性,是非常危险的。
2.从关系的角度考虑。
也许我们可以用什么东西,表示订单涉及的装备。
订单和装备,明显是多对多的关系,一个订单,可能有n种装备,一种装备,可能属于m个订单。
所以,必须独立出来。
第一,用户表
数据需求:用户ID、用户名、密码、邮箱、手机。【也许还有订单?或者一些描述信息?随便】
数据操作需求:注册(增加)、修改密码(修改)、登录时查看表(查找)、用户注销(也许不会实际删除,但起码要表示一下,提供一个接口)
第二,订单表
数据需求:可能有订单号ID、订单名字、订单描述、订单价格。
数据操作需求:增删改查。
第三,装备表
数据需求:装备号ID、装备名、装备描述、装备价格?【我不确定】
数据操作需求:增删改查。
五、概念结构设计
由上面的需求文档,画E-R实体联系模型。
这一步,主要体现了实体之间不是孤立存在的,而是有联系的。
这一步,有3个知识点:
1.有几张表,就画几个实体。
2.实体中的属性,就按数据需求画,如有增加,可临时增加。【当然,多人开发需要请示】
3.实体间的联系要画出来。(即1对n、n对m)
E-R图如下:
疑问:
有的同学可能说了:奇怪,需求文档没有用户和装备之间的联系啊?你演我?
确实,我刚分析的时候也没有,也是刚知道。
六、逻辑结构设计
将E-R图转化为关系模型,其实就是把实体转成表,只需遵守3个原则。
【注:这是在只有2元联系的E-R图适用,3元模型大差不差,不过尽量把3元模型转化为2元,否则不好用】
第一,1对1的联系,如A:B=1:1,则随意在一张表里,加入另一张表的主键,作为外键【比如在A表中,加入B的主键BID,此时,A表中的BID就是A表的外键】
第二,1对n的联系,如A:B=1:n,在n端表,加入1端表的主键,使该主键成为表外键。【即B表中,加入A表主键AID,则B表的外键是AID】
第三,n对m的联系,如A:B=n:m,则要把这个联系抽出,独立成一张新表X,使X拥有A、B两表的主键,并且有主外键要求。X的外键是AID或BID,X的主键是AID并BID。
那么,本题转换为:
用户表(ID,用户名,密码,手机号,邮箱)
订单表(ID,订单名,价格,描述,用户ID)
装备表(装备ID,装备名,描述,价格)
用户装备联系表(用户ID,装备ID,其它描述)
订单装备联系表(订单ID,装备ID,其它描述)
有时,可能会灵感一现:用户A可能拥有100个装备aa,用户装备联系表,得有100条重复数据啊!这不符合主键!
所以,用户装备联系表加上属性“装备数量”。
同理,订单装备联系表加上“装备数量”。
至此,初步的表设计完成。
范式规范化
第一范式
1NF要求:在业务层面,要求所有的列都不可分。
显然满足。
第二范式
2NF要求:所有的列,直接或间接依赖主键。
显然满足。
第三范式
3NF要求:所有的列,直接依赖于主键;并且,列与列之间无依赖关系。
虽然这么说不好,但是确实也满足。
所以,这个数据库就设计完成了,我们拥有了一个可以使用的数据库!
我是蚊子码农,如有补充或者疑问,欢迎在评论区留言。个人的知识体系可能没有那么完善,希望各位多多指正,谢谢大家。
相关文章:

数据库设计实例---学习数据库最重要的应用之一
一、引言【可忽略】 在学习“数据库系统概述”这门课程时,我一直很好奇,这样一门必修课,究竟教会了我什么呢? 由于下课后,,没有拓展自己的眼界,上课时又局限于课堂上老师的讲课水平,…...

数据结构算法题day05
数据结构算法题day05 题目算法思想代码运行代码 题目 从有序表中删除所有其值重复的元素,使表中所有元素的值均不同。算法思想 第一个元素(不重复)依次向后扫描,不重复就保留,重复(不保留)就删…...

关于《Java并发编程之线程池十八问》的补充内容
一、写在开头 在上一篇文章我们写《Java并发编程之线程池十八问》的时候,鉴于当时的篇幅已经过长,很多内容就没有扩展了,在这篇文章里对一些关键知识点进行对比补充。 二、Runnable vs Callable 在创建线程的时候,一般会选用 Runnable 和 Callable 两种方式。 【源码对…...

扒出秦L三个槽点,我不考虑买它了
文 | Auto芯球 作者 | 雷慢 比亚迪的有一个王炸“秦L”,再一次吸引了我注意力, 我上一辆车刚卖不久,最近打算买第二辆车, 二手车和新车都有在看, 我又是一个坚定的实用主义者, 特别是现在的经济环境不…...

【408真题】2009-28
“接”是针对题目进行必要的分析,比较简略; “化”是对题目中所涉及到的知识点进行详细解释; “发”是对此题型的解题套路总结,并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材(2025版&…...

LeetCode---链表
203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 代码示例1:(直接使用原来的链表来进行移除节点操作) //时间复杂度: O(n) //空间复杂度: O(1) class Solu…...

idea 快捷键运用
ctrl d 向下复制一行 shiftalt↑/↓ 向上或者向下移动光标所在行 shiftctrl↑/↓ 向上或者向下移动光标所在行(自动对齐) shift F6 rename包名或者类名或者批量修改变量名(不建议更改项目名,包名也尽量别改) 输入if 然后ctrlshift回车 补全缺失的括号 shift …...

k8s问题
文章目录 本地搭K8s集群 bilibili什么是声明式API?kubectl apply Etcd数据库有什么特性,为什么K8S选用了Etcd数据库?K8S中一个node的生命周期是怎样的?服务发现机制介绍docker的实现原理介绍如果只是使用Linux命名空间进行分离&am…...

串口通信问题排查总结
串口通信问题排查 排查原则: 软件从发送处理到接收处理,核查驱动、控制及发送接收数据是否正常。硬件从发送到接收,针对信号经过的各段,分段核对信号是否正常。示波器、逻辑分析仪。用万用表、示波器、逻辑分析仪等工具…...

【教学类-59-】专注力视觉训练01(圆点百数图)
背景需求: 视觉训练的神奇效果,让你的宝贝成为焦点 - 小红书魔法视觉追踪-视觉训练—— 🔍视觉训练🔍 🔹想要提高宝宝的专注力,视觉训练是个绝佳方法! 🔹让宝宝仔细观察数字的路线&a…...

C 语言实例 - 循环输出26个字母
循环输出 26 个字母。 以下例子我们用变量 letter 来存储当前要输出的字母,然后,使用 for 循环来重复 26 次输出字母,并在每个字母后面加一个空格。 循环内部使用 printf 函数来输出 letter 变量的值,%c 是 printf 的格式控制符…...

qt多语言翻译不生效的原因
假设您有QT语言家的基础知识,假设网上那些所有的问题您都已经排查过了,但依然翻译不生效,那么可以看下这篇帖子,其实就一个问题,变量的生命周期,假设QTranslator是一个函数内的变量,且没有被声明…...

springboot集成达梦数据库8,用springboot+mtbatisplus查询值为空
springboot集成达梦数据库8,用springbootmtbatisplus查询值为空 背景:springboot集成达梦数据库8,用springbootmtbatisplus查询值为空,但是在DB管理工具中是可以查询到数据的。 原因及解决方法:执行添加语句后…...

C语言-----指针数组 \ 数组指针
一 指针数组 用来存放指针的数组 int arr[10]; //整型数组 char ch[5]; //字符数组 int * arr[6]; //存放整型指针的数组 char * arr[5]; //存放字符指针的数组 // 指针数组的应用 int main() {int arr1[] { 1,2,3,4,5 };int arr2[] { 2,3,4,5,6 };int arr3[] { 3,4,…...

Go语言 gRPC 简述
参考文章: 聊聊gRPC的特性和背后设计的原则(一)-腾讯云开发者社区-腾讯云 grpc-我们为什么要用gRpc?gRpc快在哪里?_grpc 优点-CSDN博客 GRPC详解-CSDN博客 1. 什么是gRPC gRPC 是一个高性能 远程调用(RPC)框架&#…...

信息系统项目管理师0136:工具与技术(8项目整合管理—8.9结束项目或阶段—8.9.2工具与技术)
点击查看专栏目录 文章目录 8.9.2 工具与技术 8.9.2 工具与技术 专家判断 结束项目或阶段过程中,应征求具备如下领域相关专业知识或接受过相关培训的个人或小组的意见,涉及领域包括:管理控制;审计;法规与采购…...

appium-driver方法待整理。。
app C:\Users\v-hongweishi\AppData\Local\Programs\Xmind\Xmind.exe deviceName DESKTOP-7NJ1ENB platformName Windows 应用程序ID(AppId)是应用程序用户模型 ID (AppUserModelID),简称 AUMID Outlook …...

Android Ktor 网络请求框架
Ktor 是一个由 JetBrains 开发的用于 Kotlin 编程语言的应用框架,旨在创建高性能的异步服务器和客户端应用程序。由于完全基于 Kotlin 语言,Ktor 能够让开发者编写出简洁、可读性强且功能强大的代码,特别适合那些已经熟悉 Kotlin 的开发人员。…...

交互设计如何助力传统技艺在当代复兴?
背景介绍 榫卯是中国传统木工中一种独特的接合技术,它通过构件间的凸凹部分相互配合来实现两个或多个构件的紧密结合。这种结构方式不依赖于钉子或其他金属连接件,而是利用木材自身的特性,通过精巧的设计和工艺,实现构件间的稳定…...

使用 Django Rest Framework 构建强大的 Web API
文章目录 安装 Django Rest Framework创建序列化器创建视图和 URL 路由配置认证和权限测试 API Django Rest Framework(DRF)是一个强大的工具,用于在 Django Web 框架中构建灵活且功能丰富的 Web API。它提供了许多功能,包括序列化…...

老师如何对付挑事儿的家长?
身为老师,你有没有遇到过这样的家长:孩子在学校里闹点小矛盾,或者作业分数有点争议,他们就气势汹汹地来找你,说你偏心,甚至在其他家长面前说三道四?面对这种爱“挑事”的家长,老师们…...

若安装了Python3且没有删除Python2,那么启动yum命令会报错:
若安装了Python3且没有删除Python2,那么启动yum命令会报错: File "/usr/bin/yum", line 30 except KeyboardInterrupt e: ^ SyntaxError: invalid syntax 情况一报错原因 这种情况的原因是yum配置文件解释器默认是/…...

JVM(四)
在上一篇中,介绍了JVM组件中的运行时数据区域,这一篇主要介绍垃圾回收器 JVM架构图: 1、垃圾回收概述 在第一篇中介绍JVM特点时,有提到过内存管理,即Java语言相对于C,C进行的优化,可以在适当的…...

Leetcode373.查找和最小的 K 对数字
文章目录 题目描述解题思路代码 题目链接 题目描述 给定两个以 非递减顺序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 。 定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。 请找到和最小的 k 个数对 (u1,v1), (u2,v2) … (…...

windows 安装 使用 nginx
windows 安装 使用 nginx nginx官网下载地址:https://nginx.org/en/download.html 下载稳定版本即可 下载压缩包解压到即可 进入文件夹中,打开命令行窗口,执行启动命令 start nginx.exe验证(默认是80端口)&#x…...

【运维】Linux 端口管理实用指南,扫描端口占用
在 Linux 系统中,你可以使用以下几种方法来查看当前被占用的端口,并检查 7860 到 7870 之间的端口: 推荐命令: sudo lsof -i :7860-7870方法一:使用 netstat 命令 sudo netstat -tuln | grep :78[6-7][0-9]这个命令…...

Android笔记--应用安装
这一节了解一下普通应用安装app的方式,主要是唤起系统来安装,直接上代码: 申请权限 <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name"android.permission.WRITE_EXT…...

今日分享站
同志们,字符函数和字符串函数已经全部学习完啦,笔记也已经上传完毕,大家可以去看啦。字符函数和字符串函数and模拟函数 加油!!!!!...

基于python flask的旅游数据大屏实现,有爬虫有数据库
背景 随着旅游行业的快速发展,数据在旅游决策和规划中的重要性日益凸显。基于 Python Flask 的旅游数据大屏实现研究旨在结合爬虫技术和数据库存储,为用户提供全面、实时的旅游信息展示平台。 爬虫技术作为数据采集的重要手段,能够从各种网…...

海尔智家牵手罗兰-加洛斯,看全球创牌再升级
晚春的巴黎西郊,古典建筑群与七叶树林荫交相掩映,坐落于此的罗兰加洛斯球场内座无虚席。 来自全球各地的数万观众,正与场外街道上的驻足者们一起,等待着全世界最美好的网球声响起…… 当地时间5月26日,全球四大职业网…...