【问题标题】:SQL - Foreign key referencing different tables' primary key (Postgres)SQL - 引用不同表的主键的外键(Postgres)
【发布时间】:2026-02-13 16:55:02
【问题描述】:

这是一个项目。我正在为办公室的不同类型的记录建立一个数据库。有一个表收集了这些记录表的所有主键。所以,我需要一个引用这些表的外键。我迷路了。我问了我非常忠实的朋友谷歌,但我不明白一些可能的答案。

这是我想出的(表的名称不是他们的真实姓名,只是希望它在这里是通用的)。

编辑:我正在使用 Postgres

记录表:

recordId -> references record1 id,record2 id,record2 id
docId -> identifies what kind of record it is
filingDate

记录1:

id
attribute2
attribute3

记录2:

id
attribute2
attribute3

记录3:

attribute2
attribute3

实际上,Record1、Record2 和 Record3 各有 30 多列(想象一下出生证明,例如)

RecordsTable 将显示给用户。只有当用户需要编辑某些内容时才会显示record1-3。

我想,我会让记录 1-3 引用记录表,但这对用户来说会很麻烦,因为他/她需要先在记录表中输入,而这不是记录表的用途。只是为了显示在办公室归档的所有记录的摘要,因为一次显示所有这些是不好的。

如果有任何不清楚的地方,请告诉我,以便我进行更多解释。 提前致谢

【问题讨论】:

  • RecordsTable 是否需要存在。在单个记录表(和任何公共列)之间执行UNION ALL 的视图不会更好地服务于目的吗?
  • +1 @Damien_The_Unbeliever;在所有记录表中都有一个唯一的 ID,它会很快并且查询起来更简单。
  • @Ben - 假设您添加一列,例如TableName,那么TableNameId 的组合应该是唯一的,无需进一步努力。
  • @Damien_The_Unbeliever,我没有考虑过。它假设您在查询时知道记录应该来自哪个表,但是实现起来要简单得多...
  • 所以,我真的必须合并所有。它是否对运行时有影响,因为正如我所说,它将包含 30 或更多列和每个表的数千条记录,然后我将按归档日期排序?编辑:我没有看到短语“common columns”。好的,是的,那真的很容易

标签: sql postgresql foreign-keys multiple-tables


【解决方案1】:

好吧,我会删除 docId 列。您可以通过记录在其他表中的存在来判断记录的类型。 It's good practice not to repeat yourself.

要在三个表中保持id 的唯一性,您需要一个identity 列。 (除非您使用 Oracle 或 Postgres,如果是,请编辑您的问题。)因此,用户必须先从 Records 表中获取记录 ID,然后才能填写详细信息。也许您可以为他们创建一个用户界面。

RecordsTable: id int identity, filingDate
Record1: id int foreign key references RecordsTable(id), ...
Record2: id int foreign key references RecordsTable(id), ...

您将检索文档类型,例如:

select  case
        when record1.id is not null then 'Type1'
        when record2.id is not null then 'Type2'
        ...
        else 'Unknown'
        end
from    RecordsTable rt
left join
        Record1 r1
on      rt.id = r1.id
left join
        Record2 r2
on      rt.id = r2.id

【讨论】:

  • 在 Postgres 中,您可以使用 sequence 创建唯一 ID。这允许您将 RecordTable 条目设为可选,但我不推荐它。
【解决方案2】:

用户不必担心哪个表中的内容,这是您的应用程序的工作。

如果您需要您的主表引用三个不同表中的任何一个(并且它们具有不同的列,您无法将它们统一到一个表中),请像这样设置您的主表:

RecordsTable:
Id -> primary key for the table
docType -> identifies what kind of record it is: 1, 2, or 3
docID1 -> Foreign key to table1, if docType = 1; NULL otherwise
docID2 -> Foreign key to table2, if docType = 2; NULL otherwise
docID3 -> you get the idea
filingDate

但是如果你有三种内容非常不同的实体,你真的需要把它们都列出来吗?也许你真的没有,在这种情况下,你可以将它们作为单独的表来维护。如果将它们一起列出确实有意义,那么您在概念上就拥有一个具有三个子类型的实体(“文档”,顾名思义)。让您自己轻松并将它们存储在一个包含许多空列的表中可能是有意义的(VARCHAR 列在为空时不会占用空间)。这有点浪费,但今天的计算机有多余的空间和动力,你的时间很宝贵。但是,你反对,

这只是显示在办公室归档的所有记录的摘要,因为一次显示所有这些是不好的。

这不是问题!仅使用您要为摘要显示的列执行 SELECT 查询。如果用户选择一条记录,则执行 SELECT * 并显示完整结果。

如果您确实想麻烦拆分非常用字段,请按上述方法进行。

基本上,您需要进行一些编程。不要将数据库设计视为整个程序:数据库的工作是存储数据,应用程序的工作是处理数据。

【讨论】:

  • @Jinnean 这可能会起作用,但恕我直言,这不是一个非常微妙的解决方案。维护 RecordsTable 会很痛苦。通过重新设计,您可以将 RecordsTable 从数据库中剔除。
  • @alexis 是的,我知道用户不应该担心这一点,这就是为什么我放弃了这个想法并寻找另一个想法。尽管您的答案是我想到的答案之一,但是外键不能为空,对吗?如果这真的是我需要做的,那么我必须加入这三个表
  • @supertopi 我也想过扔掉记录表,只获取所有的 id 并按归档日期排列,然后显示给用户。但这意味着我必须不时加入每个表格并按归档日期对其进行排序。
  • 我想这取决于您的 DBMS,但外键可能为空。主键不能(实际上我认为在某些 DBMS 中可以,但没有意义)
最近更新 更多