数据库表与表之间的关系

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库表与表之间的关系相关的知识,希望对你有一定的参考价值。

参考技术A 表与表之间一般存在三种关系,即一对一,一对多,多对多关系。

例如:一个人可以拥有多辆汽车,要求查询某个人拥有的所有车辆。
分析:这种情况其实也可以采用 一张表,但因为一个人可以拥有多辆汽车,如果采用一张表,会造成冗余信息过多。好的设计方式是,人和车辆分别单独建表,那么如何将两个表关联呢?有个巧妙的方法,在车辆的表中加个外键字段(人的编号)即可。

例如:学生选课,一个学生可以选修多门课程,每门课程可供多个学生选择。
分析:这种方式可以按照类似一对多方式建表,但冗余信息太多,好的方式是实体和关系分离并单独建表,实体表为学生表和课程表,关系表为选修表,其中关系表采用联合主键的方式(由学生表主键和课程表主键组成)建表。

什么是视图?

在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表。

第一点:
使用视图,可以定制用户数据,聚焦特定的数据。

解释:
在实际过程中,公司有不同角色的工作人员,我们以销售公司为例的话,
采购人员,可以需要一些与其有关的数据,而与他无关的数据,对他没
有任何意义,我们可以根据这一实际情况,专门为采购人员创建一个视
图,以后他在查询数据时,只需select * from view_caigou 就可以啦。

第二点:使用视图,可以简化数据操作。

解释:我们在使用查询时,在很多时候我们要使用聚合函数,同时还要
显示其它字段的信息,可能还会需要关联到其它表,这时写的语句可能
会很长,如果这个动作频繁发生的话,我们可以创建视图,这以后,我
们只需要select * from view1就可以啦~,是不是很方便呀~

第三点:使用视图,基表中的数据就有了一定的安全性

因为视图是虚拟的,物理上是不存在的,只是存储了数据的集合,我们可以
将基表中重要的字段信息,可以不通过视图给用户,视图是动态的数据的集
合,数据是随着基表的更新而更新。同时,用户对视图,不可以随意的更改
和删除,可以保证数据的安全性。

第四点:可以合并分离的数据,创建分区视图

随着社会的发展,公司的业务量的不断的扩大,一个大公司,下属都设有很
多的分公司,为了管理方便,我们需要统一表的结构,定期查看各公司业务
情况,而分别看各个公司的数据很不方便,没有很好的可比性,如果将这些
数据合并为一个表格里,就方便多啦,这时我们就可以使用union关键字,
将各分公司的数据合并为一个视图。

以上,就是我认为视图的作用,实际上很多公司都使用视图来查询数据的。

内连接: 只连接匹配的行
SELECT * from gradeclass gc inner join grade g on gc.grade_id=g.Id,
左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行
select * from grade g rigth OUTER JOIN gradeclass g on g.grade_id=gc.Id(这里的outer可以省略)
右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行
select * from grade g rigth OUTER JOIN gradeclass g on g.grade_id=gc.Id(这里的outer可以省略)
全外连接: 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。
交叉连接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配

-------------------------------用MyBatis处理表与表之间的关联关系----------------------------------

1. 表与表的关联关系分为“一对多”,“多对一”,“自联查”,“多对多”,“一对一”。

2.(1)第一种“一对多”的实例,就是一个国家有多个城市

先看下数据库一个country(国家) 和provincial(城市)

---------------------------

 

(2)建好表之后,我们都知道一个国家有多个城市,所以在country实体类里加一个泛型集合list<provincial>

接口中写一个通过国家id查询一个它的对象(包含它下面的城市)的方法

 

在mappe.xml文件里,下面是通过两句sql语句查询的,这样可以使用慢加载,在config.xml中配置一个settings标签

<settings>
    + <!--开启延迟加载 默认值是 false-->
    + <setting name="lazyLoadingEnabled" value="true"/>
    + <!--
    + 我们的一个实体类中可以有多个延迟加载属性不?? 肯定可以!
    + 当启用后,一个有延迟加载属性的对象的任何一个延迟属性被加载时,该对象的所有的属性都会被加载。
    + 否则,所有属性都是按需加载。默认值是true
    + -->
    + <setting name="aggressiveLazyLoading" value="false"/>
 </settings>    
   

这个lazyLoadingEnabled默认value=false
aggressiveLazyLoading默认value=true

 

 

最后就是测试

 

 3   多对一 相反多个城市可以是一个国家 看下面实体类,在实体类Provincial里面加载一个Country 属性就好

 

 

 接口中定义一个方法

 

 在mapper.xml 中

 

然后就是测试

 

 4 。自连接先建一个这样的库

 

 实体类

接口

mapper.xml中

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xdf.dao.TeacherDao"> <!--必须是对应的dao接口的全类名-->
<!--
id     name     tid
1      导师1     0
2      导师2     0
3      老师1     1
4      老师2     1
5      老师3     3
id: 老师的编号
name:老师姓名
tid:导师的编号
需求 : 根据导师的编号查询出所有的老师信息
比如说:现在查询导师编号为1的所有老师信息
步骤:
  01.select  *  from  teacher  where  tid=1
     这时候会有 3  4 两条信息
  02. 把这两条信息的id 当成 tid 再次查询
  03.tid 为3的 又有一名老师  5
  04.结果应该是  3 4 5 三名老师
  05.不断的把查询结果的id当成 tid 再次查询, 直到没有值结束查询
-->
<!-- 01.根据导师的编号查询导师信息   我们是根据tid查询的  tid是导师编号
  然后我们再把查询结果id当成tid再次查询-->
<select id="selectTeachersByTid" resultMap="teacherMap">
        SELECT  id,tname  from teacher where tid=#{xxx}
    </select>

    <resultMap id="teacherMap" type="Teacher">
        <id property="id" column="id"/>
        <result property="name" column="tname"/>
        <!--导师对应的老师集合 把查询结果id当成tid再次查询 -->
        <collection property="teachers" ofType="Teacher" select="selectTeachersByTid" column="id"/>
    </resultMap>

    <!--  01.根据老师的编号查询自身信息
      如果这个老师是导师,那么再把id当成tid再次查询下面的老师信息-->
    <select id="selectByTeacherId" resultMap="teacherIdMap">
      select  id,tname  from teacher where id=#{xxx}
    </select>

    <resultMap id="teacherIdMap" type="Teacher">
        <id property="id" column="id"/>
        <result property="name" column="tname"/>
        <!-- 如果这个老师是导师,那么再把id当成tid再次查询下面的老师信息 -->
        <collection property="teachers" ofType="Teacher" select="selectTeachersByTid" column="id"/>
    </resultMap>




</mapper>

实现类

 自连接的多对一查询 延迟加载


public class TeacherTest {

    TeacherDao dao=null;
    SqlSession session=null;
    Logger log=Logger.getLogger(TeacherTest.class);

    /**
     * 在所有的test测试方法执行之前 都要执行的操作
     */
    @Before
    public void before(){
        //获取session
        session= SessionFactoryUtil.getSession();
        dao=session.getMapper(TeacherDao.class); //获取执行的类对象
    }

    @After
    public  void after(){
        if (session!=null){
            session.close();
        }
    }


    @Test
    public  void  testSelectByTid(){
        List<Teacher> teachers = dao.selectTeachersByTid(1);
       log.debug(teachers);  //会把查询结果id当成tid再次查询
      // log.debug(teachers.get(0).getName()); //不会触发 只查询 tid为1的数据
    }

    @Test
    public  void  testSelectById(){
         Teacher teacher= dao.selectByTeacherId(3);
       //  log.debug(teacher.getName()); //1条sql
         log.debug(teacher);
    }




}

 

以上是关于数据库表与表之间的关系的主要内容,如果未能解决你的问题,请参考以下文章

数据库设计表与表之间的关系详细介绍

Mysql 表与表之间的关系

数据库表与表之间的一对多多对多的关系

三十九表与表之间的三种关系

-------------------------------用MyBatis处理表与表之间的关联关系----------------------------------

mysql学习第6篇:数据库之表与表之间的关系