一尘不染

数据库表,一个表引用多个不相关的表

sql

在我的搜索中,在各个论坛中都曾多次提出这个问题,但没有一个提供明确的解决方案。

如果我有下表:

User
+- id
+- username
+- password

Article
+- id
+- title
+- content

并且我想加入他们以便确定谁创建了哪些文章,我可以简单地将列 user_id 添加到 Article
以用作参考。另外,我添加一个中间表来显示谁/何时/什么,例如:

User
+- ...

Article
+- ...

ChangeHistory
+- id
+- article_id
+- user_id
+- type [enum(insert, update, delete)]
+- datetime

现在很好,但是我正在处理的系统需要更加动态,因为可以轻松地引入和集成新模块。因此,现在,如果我添加一个 媒体* 表,我需要在具有以下条件的
文章媒体 之间划分 ChangeHistory
***

User
+- ...

Article
+- ...

Media
+- id
+- title
+- path

ArticleChangeHistory
+- id
+- article_id
+- user_id
+- type [enum(insert, update, delete)]
+- datetime

MediaChangeHistory
+- id
+- media_id
+- user_id
+- type [enum(insert, update, delete)]
+- datetime

通过引入许多模块,这可以很快解决。每个模块将需要负责其自己的 ChangeHistory 表的创建和管理。

TL; DR:我可以探索哪些实践来创建可以接收对多个其他不相关表的引用的中间表? 我可以添加一个 record_type
字段,其中包含记录所属的表的名称,但这很丑陋。我需要像“ 表ID ”之类的东西来引用它来自的表。这样,当/如果添加或删除模块,模型就不会崩溃。

有任何想法吗?提前非常感谢。


阅读 136

收藏
2021-05-23

共1个答案

一尘不染

以我的经验,当开发人员试图使他们的系统真正“动态”时,他们实际上是在尝试编写尚未想到的问题的代码。通常这是一条糟糕的道路。一个模块包含两个表而不是一个表真的需要很多额外的工作吗?

在每种情况下,当我看到尝试制作通用“完成所有事情”表的模式(或反模式?)时,它都会平放在其表面上。RDBMS在定义明确的问题区域上效果最佳。如果模块需要保留历史记录,则该模块应添加一个历史记录表以与该表本身一起使用。这也具有巨大的优势,因为您很可能希望根据要保留历史记录的表或模块在历史记录中保留不同类型的信息。如果您有一个通用的历史记录表,它将变得更加困难。

现在,如果您只想捕获最后一个要更新或插入特定项目(表行)的用户,并且该用户项可能在多个表中,则可以使用继承模式,其中有一个父表和多个子表。例如:

CREATE TABLE Audited_Items
(
    id    INT    NOT NULL    IDENTITY,
    CONSTRAINT PK_Audited_Items PRIMARY KEY CLUSTERED (id)
)
CREATE TABLE Articles
(
    id    INT            NOT NULL,
    [Article specific columns]
    CONSTRAINT PK_Articles PRIMARY KEY CLUSTERED (id),
    CONSTRAINT FK_Articles_Audited_Items FOREIGN KEY (id) REFERENCES Audited_Items (id)
)
CREATE TABLE Media
(
    id    INT            NOT NULL,
    [Media specific columns]
    CONSTRAINT PK_Media PRIMARY KEY CLUSTERED (id),
    CONSTRAINT FK_Media_Audited_Items FOREIGN KEY (id) REFERENCES Audited_Items (id)
)
CREATE TABLE Audit_Trail
(
    audited_item_id    INT         NOT NULL,
    audit_datetime     DATETIME    NOT NULL,
    user_id            INT         NOT NULL,
    [audit columns]
    CONSTRAINT PK_Audit_Trail PRIMARY KEY CLUSTERED (audited_item_id, audit_datetime),
    CONSTRAINT FK_Audit_Trail_Audited_Items FOREIGN KEY (audited_item_id) REFERENCES Audited_Items (id)
)
2021-05-23