AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 163919
Accepted
SQLserving
SQLserving
Asked: 2017-02-11 10:42:27 +0800 CST2017-02-11 10:42:27 +0800 CST 2017-02-11 10:42:27 +0800 CST

两张表,一个外键,两个主键

  • 772

假设有两个表:
Student:
StudentID(Primary Key)
Name

StudentTeams:
StudentID(Primary Key, Foreign Key)
TeamName

StudentTeams 表中的 StudentID 引用 Student 表的主键。就关系完整性而言,这种结构的优缺点是什么?

database-design foreign-key
  • 2 2 个回答
  • 1451 Views

2 个回答

  • Voted
  1. Best Answer
    RDFozz
    2017-02-11T12:23:31+08:002017-02-11T12:23:31+08:00

    澄清一下:使用此设置,每个学生都可以有 0 或 1 个关联的 TeamName 值。

    让没有 StudentID 作为外键的 StudentTeams 将允许具有无效学生 ID 的记录,因此这可能是一个专业人士。同样,如果 StudentID 不是 StudentTeams 的主键,则可以将一个学生附加到多个团队名称,也可能是专业人士(假设这些是您的业务规则)。

    但是,如果这实际上是表结构,那么将 TeamName 作为 Student 表中的一个字段实际上会更好,允许 NULL 值。每个学生可以有 0 或 1 个 TeamName 值,并且不需要单独的关系(或表)。所以,这是一个骗局。

    根据我的经验,我只见过几种情况,让 TableA 具有 A_ID 的主键,然后让 TableB 使用 A_ID 作为主键和外键:

    • 性能:如果 TableA 在很多地方被应用程序的许多部分使用,并且 TableB 中的数据只在应用程序的一个孤立部分中使用(一组只有 2% 的用户群可以访问的命令,或者仅在年末使用),并且TableB 中的每一行都很大(例如,如果 Student.Name 的平均长度为 40 个字符,StudentTeams.TeamName 的平均长度为 4000 个字符),则查询如果它不在 Student 表中,不需要 TeamName 可能会执行得更快。

    • 并行表:如果 TableA 的结构不受您的控制,因此您不能将 TeamName 添加到其中,则将 TableB 维护为“并行表”(我自己的术语;如果 TableA 中有匹配的行,则单独的表将只有一行) 可能是做事的唯一方法。当我需要构建一个使用来自第三方供应商应用程序的数据的应用程序时,我曾经设置了许多这样的表,但我们的应用程序需要提供供应商应用程序中不存在的额外数据。外键是必要的,因为它可以使您的信息正确地与供应商的数据相关联(级联更新和删除),而无需修改供应商的应用程序。

    • 逻辑分离: 如果 TableA 和 TableB 中的数据是相关的,但用途却截然不同,那么将它们存储在单独的表中可能是有意义的。和前面的例子一样,将TableA的主键设为TableB中的主键和外键保证了如果TableA条目存在,您将只有一个TableB条目,并且您必须消除TableB行才能删除TableA行。我使用的系统有一个任务表(包含要完成的工作列表)和一个单独的 TaskHistory 表(包含有关完成任务的条件、任务使用的消耗品等的信息)。这样可以简化业务规则;TaskHistory 中的字段可以不为空,即使在任务完成之前无法填写该字段;如果该字段在任务表中,则必须存在特殊的业务规则,保证一旦任务达到完成状态某些字段不为空。请注意,这通常是逻辑和性能的混合:应用程序中有许多查询只需要访问任务表。

    • 进一步的关系要求:正如 ypercubeᵀᴹ 在评论中所指出的,可以使用它来允许第三个表使用 StudentTeams 表中的 StudentID 作为外键,确保第三个表只链接回团队中的学生。就个人而言,我不确定我是否会以这种方式实现结构。这可能会导致对 StudentID 含义的混淆;它总是会链接回 Student 记录,但不会总是链接回 StudentTeam 记录(尽管不可否认,在第三个表的上下文中,它总是会同时链接回 Student 和 StudentTeam)。我倾向于在 StudentTeams 中创建一个 StudentTeamID 值,并链接到该值,因为它的含义会立即清楚(它只会链接到团队中的学生)。

    • 2
  2. paparazzo
    2017-02-14T07:44:21+08:002017-02-14T07:44:21+08:00

    StudentTeams 是一个坏名字,就像复数一样。
    通过这种设计,学生可以加入 0 或 1 个团队。

    如果多个学生在同一个团队 (TeamName) 重复。两个学生可能在同一个团队中,但有人可能会错误地输入 TeamName,因此您不会知道。

    我要么

    • 将 TeamName 添加到 student 并让它允许 null
      它将完全按照您现在所拥有的 - 0 或 1 TeamName
    • 团队表和连接表

      团队:
      ID(PK)
      名称

      StudentTeam :
      SudentID(PK、FK 到 Student.ID)
      TeamID(FK 到 Team.ID)

    如果您想允许一个学生加入多个团队,那么只需将 TeamID 添加到 PK。

    或者您可以跳过 StudentTeam 并将 TeamID 放在学生表中。至少您只输入一次 TeamName。

    学生:
    ID(PK)
    名称
    TeamID(FK 到 Team.ID)允许为空

    • 1

相关问题

  • 过滤索引是否有助于改进基于输入时间的查询,还是应该避免这种情况?

  • MySQL VARCHAR 和 TEXT 数据类型有什么区别?

  • 存储计算值或根据要求重新计算它们更好吗?[复制]

  • 存储与计算聚合值

  • 在数据仓库中实现多对多关系有哪些方法?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve