主键和外键

主键(主关键字,primary key)

关系型数据库中的一条记录中有若干个属性,若其中某一个属性能唯一标识一条记录,该属性就可以成为一个主键 。
之所以强调“组”,是因为表的主键可以由一个或多个关键字共同组成。主键用于唯一标识表中的一条记录,所以表只能有一个主键,并且主键涉及的属性不能包含空值。

有博客强调
①主键应该是单列的(即主键不应由多个关键字共同组成)
,以便提高连接和筛选操作的效率,正确与否待进一步研究。
永远不要更新主键。因为主键唯一的作用就是“惟一标识”表中的每条记录,除此以外,再无其他用途。所以,没有理由去对主键进行更新。反过来说,如果主键需要更新,则说明在设计主键时违反了“主键应对用户无意义,仅用来唯一标识记录”的原则。
注:这项原则对于那些经常需要在数据转换或多数据库合并时进行数据整理的数据并不适用。
要注意,主键不应包含动态变化的数据,如时间戳、创建时间列、修改时间列等。原因还是在于设立主键的目的——仅是用来唯一识别记录。
主键应当由计算机自动生成。如果由人来对主键的创建进行干预,就难免使它带有除了惟一标识以外的含义。从而产生了需要修改主键的动机的可能。

外键(外关键字,foreign key,公共关键字的其中一个)

表A和B中有一公共关键字,其中该公共关键字是A表主键,则B表的该属性被称为A表的?外键。

外键:即A在外的主键,自认

比如,学生表(学号,姓名,性别,班级) ,其中每个学生的学号是唯一的,学号就是一个主键;课程表(课程编号,课程名,学分),其中课程编号是唯一的,课程编号就是一个主键;成绩表(学号,课程号,成绩) ,成绩表中单一 一个属性无法唯一标识一条记录,学号和课程号的组合才可以唯一标识一条记录,所以学号和课程号的属性组是一个主键。

成绩表中的学号不是成绩表的主键,但它和学生表中的学号相对应,并且学生表中的学号是学生表的主键,则称成绩表中的学号是学生表的外键 。

存在的目的与意义

  1. 主键和外键是把多个表组织为一个有效的关系数据库的粘合剂。用于建立两表记录之间链接的效果。通过将主表中的主键值(一列或多列)添加到另一个表中,构成另一个表中的外键,从而将两表间的记录进行关联。比如,A表中拥有主键的一条记录与B表中拥有相同外键的一条记录,就可通过此相同的主键属性进行查询。这(一列或多列)就组成B表中的外键。
  2. 拥有外键的记录,可以减少对其关联属性是否存在的检查验证,即只要该记录中还有外键,就说明关联的主表记录还在,自认待确认
    例:录入学生成绩的业务中涉及两张表,一张是学生表(学号、姓名,其中学号为主键) ,另一张是学期成绩表(学期号、学号、分数,此时单独的学号无法唯一标识成绩表中的记录,所以将学期号,学号组合为主键,且学号为外键)。
    为了保证成绩表的数据有效,所以要求录入学号时,保证学生表中有这个学号,否则就不能录入。 如果用程序控制,有很多缺点:①录入成绩单时为了保证学号有效,首先要搜索档案,当档案很大时会影响效率②程序控制并不能保证百分之百引用完整性,尤其是并发操作,比如在查询学号是否存在时,学生还未退学,查询学号存在;在查询到学号,添加成绩表时,学生退学。

主键、外键与索引的区别

主键外键索引
定义唯一标识表中的记录另一表的主键
作用保证数据完整性?用于与其他表建立关联提高查询排序的速度
性质同一表内的主键不可重复、不能为空同一表内的外键可以重复, 可以为空同一表内的索引不可重复值,但可为空

主表和从表

主表:在数据库中建立的表,其中存在主键(primary key)用于与其它表相关联。主键作为主表中不同记录间的唯一标识。

从表:以主表的主键(primary key)值为外键 (Foreign Key)的表,可以通过外键与主表进行关联查询。从表与主表通过外键进行关联查询。

主从表的区别与联系

主键表是被引用的表,外键表是引用其他表的表。主从表之间建立关联,一般是通过在从表中添加一个主表的主键字段作为从表的外键,这样主从表之间就可以建立一对多的对应关系了。

从表数据依赖于主表,一般最后查询数据时把主表与从表进行关联查询。主表可用于存储主要信息,如客户资料(客户编号,客户名称,客户公司,客户单位等),从表用来存储客户扩展信息(客户订单信息,客户地址信息,客户联系方式信息等)。

单表

主从表联合查询

内外连接

  • 内连接:仅连接两表中匹配(查询条件paperfile.issuednumber = deliveryrecord.issuednumber)的对应记录,并将其作为检索结果返回用户,代码示例如下所示。

    select * from user u inner join uorder o on u.userid=o.uid
    
  • 外连接:不管能否匹配都将其展示。

  • 左(外)连接:包含left join左侧表名中全部的行(针对左表进行外连接,不管右边的表中是否存在与它们匹配的行),以及右侧表中全部与查询条件匹配的行。

  • 右(外)连接:包含right join右侧表名中全部行(针对右表进行外连接,不管左边的表中是否存在与它们匹配的行),以及左边表中全部与查询条件匹配的行。

详见这篇博客

注:“外”连接中的“外”,应是指“查询条件匹配之外”之意

左/右连接查询

查询两张表,将两表中 “满足检索条件/彼此关联” 的记录 链接生成 一条记录,并以此作为返回给用户作为查询结果的一条完整记录。

  • left join: 从本名词(left join)左侧的表中检索出满足条件的所有记录,并将右表中与左表匹配关联的每一条记录都检索出来(不管右表中检索出来的记录是否为空),最后将这两表中检索出的记录合并为一条新的记录返回给用户
  • right join: 同上,包含右表的所有行,对应的左表行可能为空。
  • full join: 仅检索左右表都匹配并且不为空的行。

left join、right join以及内连接、外连接的内容,可以看这篇博客的示例。一句话概括,即“左/右连接查询中的 ‘左/右’ 是指哪一侧不能为空”,或者理解为“查询哪一侧的表中不空的记录,并将另一侧表中与这些选出记录关联的记录一起组成一条完整记录进行输出”。

//LEFT,则从‘LEFT JOIN’左侧Websites表检索出来的记录不能为空,从该词右侧的表access_log关联出来的数据可以为空
FROM Websites
LEFT JOIN access_log

//同理,

//RIGHT,则从该词右侧的access_log表检索出来的记录不能为空,从该词左侧的表Websites关联出来的数据可以为空
FROM Websites
RIGHT JOIN access_log

代码示例:

网上博客给出的示例

查询两张表(Websites网站表和access_log访问记录表) 满足检索条件的记录,并将两行表中的记录链接为一条作为最终展示结果的一条完整记录,数据库表及下方代码结果详见此文

SELECT Websites.name, access_log.count, access_log.date
FROM Websites
LEFT JOIN access_log//声明谁是右表,即便要查询的数据仅在左表,右表没有,也将该条记录在结果中列出。
ON Websites.id=access_log.site_id
ORDER BY access_log.count DESC;
自己的示例

投递文件中需要使用的文件表和投递记录表,将两表中的关联数据展示给用户。

//定义展示结果的数据类型,即要返回给用户的查询结果应包含哪些数据项。
SELECT paperfile.issuednumber, deliveryrecord.recordstatus, deliveryrecord.boxname, deliveryrecord.update_date
//投递记录不能为空,纸质文件信息可以空
FROM paperfile RIGHT JOIN deliveryrecord
//两表记录间的关联条件
ON paperfile.issuednumber = deliveryrecord.issuednumber
//排列顺序
ORDER BY deliveryrecord.update_date DESC;

在Navicat中查询的结果,如下所示。
在这里插入图片描述

暂时记录,后续梳理好思路后整理入前文

一个从表包含多个主表中的主键后,如果将从表改为单表,则其中包含的多个主表无法录入数据。随后将改为单表的从表删除,包含的主表可以恢复录入数据。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐