【导语】“远子zy”通过精心收集,向本站投稿了4篇关系型数据库表结构的两个设计技巧,以下是小编帮大家整理后的关系型数据库表结构的两个设计技巧,欢迎大家收藏分享。
篇1:关系型数据库表结构的两个设计技巧
关系型数据库表结构的设计,有下面两个设计技巧:
物理主键作为关联的外键
关系型数据库,由多个数据表构成,关系型数据库表结构的两个设计技巧
。每一个数据表的结构是相同的,不同表之间可能存在关联关系。表之间的关联关系,正是关系型数据库得名的原因。一个表由多个字段构成。其中可能有多个字段适合作为主键。主键字段,就是表中每一行都不会有重复数据的字段。
主键,可以分为两种:物理主键和逻辑主键。
每一张数据库的表,都使用自增长的id字段作为物理主键。
多表之间的外键关联,都关联其他表的物理主键,也就是关联其他表的id字段。
逻辑主键,就是除了id字段外的不重复的字段。我们设计数据库的外键关联时,不使用逻辑主键,而是使用物理主键。
这是因为,物理主键肯定是主键,因为它是自增的。(对于不支持自增字段的关系数据库,可以使用uuid保证物理主键的唯一性)
而逻辑主键,则可能随着业务的发展,成为可重复的字段。一旦这种情况发生,关系数据库的外键关系就被破坏了。如,可能你觉得姓名是逻辑主键,但可能后面发现有人重名,那么这个字段就不再是主键了。而如果之前使用这个字段作为外键,那么查询返回的数据就不是一一对应的了。这就是为什么要使用物理主键,以及用物理主键作为关联外键的原因。
使用乐观锁更新依赖之前状态的记录
考虑这样一种数据库的应用场景:
任务单的接管:多个操作人员从一个任务池中接管一个任务。只有第一个获取任务的操作人员才能成功接管该任务,后续操作人员的接管操作都必须失败。
这时,就需要一种数据库记录的锁定机制。只有第一个事务才能更新记录。
数据库可以使用悲观锁和乐观锁来锁定数据库记录。
悲观锁是如下sql语句实现的:
SELECT * FROM t FOR UPDATE
这条语句会在其他修改内容的事务提交后返回最新的数据。
一旦执行这条语句,这些记录就被锁住了,不能被其他sql事务修改。直到本事务提交。
乐观锁,是应用程序实现的,不是数据库实现的机制。乐观锁,对于数据库来说,就是没有上锁。事务可以select其他事务已经提交的数据,
更新数据时,数据库保证多个事务的更新是原子的。
悲观锁,会导致事务等待其他事务完成。乐观锁,只会等待其他事务的更新语句的完成,不会等待整个事务完成,因此效率较高。
实现乐观锁的方法:
给数据库表添加一个version字段。version是一个数字类型的字段,每次更新都加1。每次更新时都要检测version字段是否和当前事务的值相同。如果version字段不同,那么就表明在查询数据之后,有其他事务已经更新了该记录,就会导致此次更新失败。应用必须重新载入最新的数据,然后重新更新数据。
如果使用乐观锁,那么如果数据库中version和应用中version相同,则用version+1的版本值更新version字段。
SQL语句如下:
update studentVersion set ver=?, name=? where id=? and ver=?
不使用锁更新独立状态的记录
考虑这样一种数据库的应用场景:
需要更新虚拟机的状态。多个事务可能会同时更新虚拟机的状态为start或者stop。这种状态的更新和前一个阶段的状态是无关的,因此不需要锁定记录。直接更新即可。此时不需要使用悲观锁或者乐观锁。
如果这个表添加了version字段,直接忽略对version字段的比较和更新即可。
SQL语句如下:
update studentVersion set name=? where id=?
总结
设计关系型数据库的表时,需要给表添加一个ID字段(自增字段,或者uuid字段)和一个version字段(数值类型)。ID字段作为物理主键,用于保证记录的不可重复性和用作外键关联。
version字段用于实现乐观锁,提供比悲观锁更好的性能。特别是对于UI显示并可能出现并发更新的数据,更需要使用乐观锁来提升数据库访问性能。
对于后台自动更新的任务,可以使用乐观锁实现。但需要在冲突发生时实现自动退让。也可以使用悲观锁在数据库上对事务进行排队来解决更新冲突问题。
对于不关心记录的状态之间关系的场景,可以直接更新记录,忽略掉version字段的检测和更新。
篇2:关系型数据库基础之:数据库设计(附加)
,
E-R模型:
E-R (Entity-Relationship)实体关系。
三大范式理论:
(1)行不重复(定义主键),某些情况下列不可再分;
(2)表中的所有主键列必须依赖于所有主键列(非主依主);
(3)非主键列之间必须相互独立(非主独立)。
第一范式必须遵守,二和三是可以违反的。
篇3:关于树型结构的表,及排序的问题数据库教程
排序|树型结构|问题
刚才一同事碰到一个树型结构表的排序的问题,让我想到一个隐藏很深的BUG,我通常对树型结构的表都是这样设计的:在表中与排序相关的有三个列,ID,ParentID, TreeKey
ID:本条记录的唯一主键
ParentID:父记录的编号
TreeKey:表示层级结构,形如xx.xxx.xxxx
关键是TreeKey,我以前都要求存入父ID的编号,像这样
ID ParentID TreeKey
---------------------------------------------------------------------
1 NULL1
2 11.2
3 11.3
...
10 11.10
11 11.11
像这样的话,按照TreeKey进行排序就会出现问题,因为TreeKey是个字符串,而1.10会排到1.2, 1.3之前,很显然,这不是我们要的结果,
要解决其实也很简单,在编号前面补0,比如,1.10就写成0001.0010,1.2就写成0001.0002,这样排序就不会有问题了。
这让我想起很早前看的微软的一个有关树的软件代码,就看到他们是以000x.000x这种方式进行处理的,当时我还感觉他们怎么这么麻烦,现在想来,才发现是自己无知了,呵呵。
篇4:我对关系型数据库设计范式的理解
我对关系型数据库设计范式的理解
所谓范式,是关系型数据库关系模式规范化的标准,从规范化的宽松到严格,分别为不同的范式,通常使用的有第一范式、第二范式、第三范式及BC范式等,范式是建立在函数依赖基础上的。
函数依赖
定义:设有关系模式R(U),X和Y是属性集U的子集,函数依赖是形为X→Y的一个命题,对任意R中两个元组t和s,都有t[X]=s[X]蕴t[Y]=s[Y],那么FD X→Y在关系模式R(U)中成立。X→Y读作‘X函数决定Y’,或‘Y函数依赖于X’。
通俗的讲,如果一个表中某一个字段Y的值是由另外一个字段或一组字段X的值来确定的,就称为Y函数依赖于X。
函数依赖应该是通过理解数据项和企业的规则来决定的,根据表的内容得出的函数依赖可能是不正确的。
第一范式(1NF)
定义:果关系模式R的每个关系r的属性都是不可分的数据项,那么就称R是第一范式的模式。简单的说,每一个属性都是原子项,不可分割。 1NF是关系模式应具备的最起码的条件,如果数据库设计不能满足第一范式,就不称为关系型数据库。关系数据库设计研究的关系规范化是在1NF之上进行的。
第二范式(2NF)
定义:如果关系模式R是1NF,且每个非主属性完全函数依赖于候选键,那么就称R是第二范式。简单的说,第二范式要满足以下的条件:首先要满足第一范式,其次每个非主属性要完全函数依赖与候选键,或者是主键。也就是说,每个非主属性是由整个主键函数决定的,而不能由主键的一部分来决定,
举个例子:
有股票日行情表的主键是股票代码和交易日期组成。非主属性中有收盘价和成交量等,都是由主键,即股票代码和交易日期函数决定的,单独的股票代码或者交易日期都不能函数决定这些非主属性。如果这个表中有非主属性股票简称,则股票简称是可以由股票代码来函数决定的,这样股票简称这个非主属性就不是完全函数依赖于候选键,这样的设计就不满足第二范式。
第三范式(3NF)
定义:如果关系模式R是2NF,且关系模式R(U,F)中的所有非主属性对任何候选关键字都不存在传递依赖,则称关系R是属于第三范式。简单的说,第三范式要满足以下的条件:首先要满足第二范式,其次非主属性之间不存在函数依赖。由于满足了第二范式,表示每个非主属性都函数依赖于主键。如果非主属性之间存在了函数依赖,就会存在传递依赖,这样就不满足第三范式。
举个例子:
在股票基本情况表中,主键是股票代码,有非主属性所属一级行业和所属二级行业。根据业务规则,所属二级行业能够函数决定所属一级行业,这就表示存在这样一种关系:股票代码函数决定所属二级行业,所属二级行业函数决定所属一级行业,这就形成了传递依赖,这样的设计就不符合第三范式。
不过在实际运用中,为查询和使用的方便,有时也会违反第三范式。如上例,如果没有所属一级行业的属性,需要查询所属一级行业的相关股票,需要查询时使用函数来从二级行业中函数生成所属一级行业,使用性能上会受影响。所以通常会加上所属一级行业的属性。
BC范式(BCNF)
BC范式是第三范式的增强版,不过也有人说是直接从1NF发展过来的,即每个属性,包括主属性或非主属性,都完全依赖于候选键,并且不存在传递依赖情况。
★ 古典概型教学设计
关系型数据库表结构的两个设计技巧(精选4篇)




