持久层设计与实施

持久层设计与实施

系统工程=程序+文档,程序是由逻辑结构+数据构成,那么对于数据的处理就显得格外重要。一个程序中会用到很多数据,然而不是所有的数据都需要存入数据库。我们在设计系统的时候应该如何做出选择呢?

首先,我们可以逐条解析需求说明书,从中提取所有出现的数据,然后将数据按照处理方式分类:部分数据只是在处理逻辑中使用,那么它们只需要赋给变量,部分数据可以写入文档,那么它们可以存放在工程文件夹中,最终可能一起放入服务器中保存,剩下的数据,需要持久保存时,才考虑将其存入数据库。对于有必要存入数据库的数据,我们按照功能逻辑先做一个简单的分组。

为了使数据库更加合理,高效。我们需要用三范式来规范每个数据表的属性。三范式拆分原则如下:

l        第一范式:确保每列属性保持原子性,即不可拆分。原子性是相对的,根据实际需求而定,要考虑是否便于查询,是否用到某属性处理业务逻辑

l        第二范式:主键列与非主键列遵循完全函数依赖关系,即确保表中的每列非主属性都和每个主键属性相关。确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。只要数据列中出现数据重复,就要把表拆分开来。

l        第三范式:非主键列之间没有传递函数依赖关系,确保每列都和主键列直接相关,而不是间接相关

有时候不能死板地套用三范式,还要根据具体情况,考虑需求和性能,做出更合理的取舍。

当用三范式规范了表结构之后,我们该考虑各个数据表之间的关系了,表与表之间本来是没有关系的,为什么要考虑关系呢?因为业务逻辑的需要,因为要查询出不同数据表信息的组合,所以才建立表格之间的关系。那么我们就可以从多表连接查询入手,来探究表之间的关系。新建两张表:student表和course表

          

(实际开发中这两个表会有自己不同的主键。)

1.       外连接

外连接可分为:左连接、右连接、完全外连接。

l        左连接left join或left outer join

SQL语句:select * from student left join course onstudent.ID=course.ID
执行结果:

左外连接包含left join左表所有行,如果左表中某行在右表没有匹配,则结果中对应行右表的部分全部为空(NULL)。【此时我们不能说结果的行数等于左表数据的行数。当然此处查询结果的行数等于左表数据的行数,因为左右两表此时为一对一关系】

l        右连接right join或right outer join

SQL语句:select *from student right join course on student.ID=course.ID
执行结果:

右外连接包含right join右表所有行,如果左表中某行在右表没有匹配,则结果中对应左表的部分全部为空(NULL)。【同样此时我们不能说结果的行数等于右表的行数。当然此处查询结果的行数等于左表数据的行数,因为左右两表此时为一对一关系】。

l        完全外连接full join或full outer join

SQL语句:select * from student full join course onstudent.ID=course.ID
执行结果:

完全外连接包含full join左右两表中所有的行,如果右表中某行在左表中没有匹配,则结果中对应行右表的部分全部为空(NULL),如果左表中某行在右表中没有匹配,则结果中对应行左表的部分全部为空(NULL)。

2.     内连接join或inner join

SQL语句:select * from student inner join courseon student.ID=course.ID
执行结果:

inner join 是比较运算符,只返回符合条件的行。此时相当于:select * from student,course where student.ID=course.ID

3.     交叉连接cross join

没有 WHERE 子句的交叉联接将产生连接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。SQL语句:select * from student cross joincourse执行结果:

如果我们在此时给这条SQL加上WHERE子句的时候比如SQL:select* from student cross join course where student.ID=course.ID此时将返回符合条件的结果集,结果和inner join所示执行结果一样。

4.     两表关系为一对多,多对一或多对多时的连接语句

当然上面两表为一对一关系,那么如果表A和表B为一对多、多对一或多对多的时候,我们又该如何写连接SQL语句呢?其实两表一对多的SQL语句和一对一的SQL语句的写法都差不多,只是查询的结果不一样,当然两表也要略有改动。比如表1的列可以改为:Sno Name Cno。表2的列可以改为:Cno CName。这样两表就可以写一对多和多对一的SQL语句了,写法和上面的一对一SQL语句一样。下面介绍一下当两表为多对多[需要建立中间关系表]的时候我们该如何建表以及些SQL语句。新建三表:student 表,course表,和student_course表

                

一个学生可以选择多门课程,一门课程可以被多个学生选择,因此学生表student和课程表course之间是多对多的关系。当两表为多对多关系的时候,我们需要建立一个中间表student_course,中间表至少要有两表的主键,当然还可以有别的内容。SQL语句:select s.Name,C.Cname from student_course as sc left join student ass on s.Sno=sc.Sno left join course as c on c.Cno=sc.Cno执行结果:

此条SQL执行的结果是学生选课的情况。

通过上面各种表之间的连接的关系,我们就可以根据实际情况,考虑各个表之间的关系了。那么我们明确一下几个问题:

[1]一对一,一对多/多对一还是多对多?

答:根据一条记录实例来考虑这一问题.

[2]外键应该建在哪个表[如何区分主表,从表]?

答:若是一对一关系,那么只要存在相同属性值的属性列,外键甚至可以不建立,如果建立外键,那么外键任意建立在哪个表.根据实际情况,逻辑情况做出选择.

   若是一对多关系,那么外键应该放在多的一方.

[3]单向还是双向?

答:不论外键是如何建立,都可以通过左外链和右外链查询到结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值