【问题标题】:Relational database: indirect reference to a "foreign key"关系数据库:间接引用“外键”
【发布时间】:2014-08-10 19:48:24
【问题描述】:

我有一个类似于以下的数据架构:

用户

id
name
email
phone number
...

照片

id
width
height
filepath
...

我有一个对系统进行任何更改的审核表

日志

id
acting_user
date
record_type (enum: "users", "photos", "...")
record_id
record_field
new_value

此设置是否有一个名称,其中一个字段中的enum 指的是另一个表之一的名称?并且有效地,record_typerecord_id 一起是另一个表中记录的外键?这是反模式吗? (注意:new_value,我们要记录的所有内容都是相同的数据类型,字符串)。

【问题讨论】:

  • 如果您查看像 Hibernate Envers 这样的审计产品,它使用每个表的历史记录表(contacts_history 用于联系人)并且不使用外键。

标签: database database-design foreign-keys relational-database foreign-key-relationship


【解决方案1】:

这是一种反模式吗?

是的。任何让您手动强制执行参照完整性的模式1 都是反模式。

Here 是使用外键如此重要的原因,here 是在像您这样的情况下该怎么做。

此设置是否有一个名称,其中一个字段中的枚举引用另一个表之一的名称?

我知道没有标准术语,但我听说人们称其为“通用”或“多态”FK。


1 与 DBMS 中内置的 FOREIGN KEY 不同。

【讨论】:

    【解决方案2】:

    实际上,我认为“Anti-Pattern”对于这个设置来说是一个很好的名字,但它可能是一个现实的方法——尤其是在这个例子中。

    我将添加一个类似的示例,其中包含一个记录用户照片的 LIKES 等的新表,并说明它为什么不好。然后我将解释为什么它对于您的 LOGS 示例可能不会太糟糕。

    LIKES 表是:

    Id
    LikedByUserId
    RecordType ("users", "photos", "...")
    RecordId
    

    这与 LOGS 表几乎相同。这样做的问题是您不能将 RecordId 作为 USERS 表以及 PHOTOS 表以及任何其他表的外键。如果用户 1234 被点赞,则无法插入它,除非有 ID 为 1234 的 PHOTO 等等。出于这个原因,我所知道的所有 RDBMS 都不会让外键定义为具有多个主键 - 毕竟,Primary 意味着“只有一个”。

    因此,您必须创建没有关系完整性的 LIKES 表。有时这可能不是一件坏事,但在这种情况下,我想我希望像 LIKES 这样的重要表有有效的条目。

    要正确执行 LIKES,我将创建表为:

    Id
    LikedByUserId (allow null)
    PhotoId (allow null)
    OtherThingId (allow null)
    

    ...并创建适当的外键。这实际上将使读取数据的查询更易于阅读和维护,并且可能也更有效。

    但是,对于像 LOGS 这样的表,它可能不是我系统功能的核心,我只是在做一些临时查询以检查发生了什么,那么我可能不想添加额外的努力并增加导致更有效阅读的复杂性。不过,我不确定我是否真的会跳过它。这是一种反模式,但根据使用情况可能没问题。

    为了强调这一点,我只会在系统从不查询表的情况下这样做;如果查看数据的唯一人员是管理员正在针对它运行的临时查询,那么可能没问题。

    干杯-

    【讨论】:

      猜你喜欢
      • 2019-07-13
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 2021-11-23
      • 1970-01-01
      相关资源
      最近更新 更多