• MySQL(五)


    关系

    • 创建成绩表scores,结构如下
      • id
      • 学生
      • 科目
      • 成绩
    • 思考:学生列应该存什么信息呢?
    • 答:学生列的数据不是在这里新建的,而应该从学生表引用过来,关系也是一条数据;根据范式要求应该存储学生的编号,而不是学生的姓名等其它信息
    • 同理,科目表也是关系列,引用科目表中的数据

    • 创建表的语句如下
      create table scores(
      id int primary key auto_increment,
      stuid int,
      subid int,
      score decimal(5,2)
      );

      外键

      • 思考:怎么保证关系列数据的有效性呢?任何整数都可以吗?
      • 答:必须是学生表中id列存在的数据,可以通过外键约束进行数据的有效性验证
      • 为stuid添加外键约束
      alter table scores add constraint stu_sco foreign key(stuid) references students(id);
      
      • 此时插入或者修改数据时,如果stuid的值在students表中不存在则会报错
      • 在创建表时可以直接创建约束
    create table scores(
    id int primary key auto_increment,
    stuid int,
    subid int,
    score decimal(5,2),
    foreign key(stuid) references students(id),
    foreign key(subid) references subjects(id)
    );

    外键的级联操作

    • 在删除students表的数据时,如果这个id值在scores中已经存在,则会抛异常
    • 推荐使用逻辑删除,还可以解决这个问题
    • 可以创建表时指定级联操作,也可以在创建表后再修改外键的级联操作
    • 语法
    alter table scores add constraint stu_sco foreign key(stuid) references students(id) on delete cascade;

    级联操作的类型包括:

    • restrict(限制):默认值,抛异常
    • cascade(级联):如果主表的记录删掉,则从表中相关联的记录都将被删除
    • set null:将外键设置为空
    • no action:什么都不做

    先看个问题

    • 问:查询每个学生每个科目的分数
    • 分析:学生姓名来源于students表,科目名称来源于subjects,分数来源于scores表,怎么将3个表放到一起查询,并将结果显示在同一个结果集中呢?
    • 答:当查询结果来源于多张表时,需要使用连接查询
    • 关键:找到表间的关系,当前的关系是
      • students表的id---scores表的stuid
      • subjects表的id---scores表的subid
    • 则上面问题的答案是:
      select students.sname,subjects.stitle,scores.score
      from scores
      inner join students on scores.stuid=students.id
      inner join subjects on scores.subid=subjects.id;
    • 结论:当需要对有关系的多张表进行查询时,需要使用连接join

    连接查询

      • 连接查询分类如下:
        • 表A inner join 表B:表A与表B匹配的行会出现在结果中
        • 表A left join 表B:表A与表B匹配的行会出现在结果中,外加表A中独有的数据,未对应的数据使用null填充
        • 表A right join 表B:表A与表B匹配的行会出现在结果中,外加表B中独有的数据,未对应的数据使用null填充
      • 在查询或条件中推荐使用“表名.列名”的语法
      • 如果多个表中列名不重复可以省略“表名.”部分
      • 如果表的名称太长,可以在表名后面使用' as 简写名'或' 简写名',为表起个临时的简写名称

    练习

    • 查询学生的姓名、平均分
    select students.sname,avg(scores.score)
    from scores
    inner join students on scores.stuid=students.id
    group by students.sname;
    • 查询男生的姓名、总分
    select students.sname,avg(scores.score)
    from scores
    inner join students on scores.stuid=students.id
    where students.gender=1
    group by students.sname;
    • 查询科目的名称、平均分
    select subjects.stitle,avg(scores.score)
    from scores
    inner join subjects on scores.subid=subjects.id
    group by subjects.stitle;
    • 查询未删除科目的名称、最高分、平均分
    select subjects.stitle,avg(scores.score),max(scores.score)
    from scores
    inner join subjects on scores.subid=subjects.id
    where subjects.isdelete=0
    group by subjects.stitle;
  • 相关阅读:
    CCF-CSP201703-3 Markdown
    HDU1008 Elevator
    Java使用Preconditions.checkNotNull(.....)优雅地判空对象, 并处理可能的NullPointerException异常
    StringUtils的isBlank()方法
    java.math.RoundingMode 几个参数详解
    把String集合数据去"[ ]" 转成list和把String集合数据去除[ "" ,""] 转成list 工具类
    BeanUtils.copyProperties(复制对象属性方法)
    关于 mybatis 中 in 写法,<foreach collection="xxx" item="xxx" index="index" open="(" separator="," close=")"> 参数详解
    JAVA_collection_集合相关知识点(二、获取集合对象中某个属性的集合——CollectionUtils.collect()方法)
    @AllArgsConstructor @NoArgsConstructor
  • 原文地址:https://www.cnblogs.com/leecoffee/p/9038330.html
Copyright © 2020-2023  润新知