数据库表,一个表引用多个不相关的表 [英] Database tables, one table referencing multiple unrelated tables

查看:180
本文介绍了数据库表,一个表引用多个不相关的表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题在我的搜索中的各种论坛中已经出现了几次,但没有一个提供了简明的解决方案。



如果我有以下表格: p>

 用户
+ - id
+ - 用户名
+ - 密码

文章
+ - id
+ - 标题
+ - 内容



我想加入他们,以确定谁创建了什么文章,我可以简单地将列 user_id 添加到文章中作为参考。或者,我添加一个中间表来显示谁/什么时候/什么,例如:

 用户
+ - ...

文章
+ - ...

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

现在这是很好的,但我正在开发的系统需要更加动态,因为可以轻松地引入和集成新的模块。所以现在,如果我添加了一个媒体表,我需要在文章媒体之间分割 ChangeHistory : p>

 用户
+ - ...

文章
+ - ...

媒体
+ - id
+ - 标题
+ - 路径

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

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

随着许多模块的引入,这可能会很快失败。每个模块需要负责创建和管理自己的 ChangeHistory 表。



TL; DR:什么做法我探索创建一个可以接收对多个其他无关表的引用的中间表?我可以添加一个* record_type *字段,保存记录所属的表的名称,但是这很丑。我需要像表ID 这样的东西来引用它的表。这样,当/如果模块被添加或删除,模型不会崩溃。



任何想法?感谢您提前许可。

解决方案

根据我的经验,当开发人员试图让他们的系统真正动态试图编写他们还没有想到的问题。这通常是一条不好的路。在一个模块中包含两个表格而不是一个表格真的是非常多的工作吗?



在我看到的模式(或反模式)的每种情况下试图做一个通用的做一切表,它的脸上平静下来。 RDBMS在定义明确的问题领域最有效。如果模块需要保留历史记录,那么模块应该添加一个历史记录表来与表本身一起去。这还有一个巨大的优势,在这个道路上,你可能希望保留历史上不同类型的信息,这取决于历史记录的表或模块。如果你有一个通用历史记录表变得更加困难。



现在,如果你想简单地捕获最后一个用户来更新或插入一个特定的项目(表格行)那么可以在多个表中,那么您可以使用一个继承模式,其中有一个父表和多个子表。例如:

  CREATE TABLE Audited_Items 

id INT NOT NULL IDENTITY,
CONSTRAINT PK_Audited_Items PRIMARY KEY CLUSTERED(id)

CREATE TABLE文章

id INT NOT NULL,
[文章具体列]
CONSTRAINT PK_Articles主键CLUSTERED(id),
CONSTRAINT FK_Articles_Audited_Items FOREIGN KEY(id)REFERENCES Audited_Items(id)

CREATE TABLE Media

id INT NOT NULL,
[媒体专栏]
CONSTRAINT PK_Media PRIMARY KEY CLUSTERED(id),
CONSTRAINT FK_Media_Audited_Items FOREIGN KEY(id)参考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)


This question has come up a few times in various forums in my searching, but none have provided a concise resolution.

If I have the following tables:

User
+- id
+- username
+- password

Article
+- id
+- title
+- content

and I want to join them in order to determine who created what articles, I could simply add the column user_id to Article to use as a reference. Alternatively, I'm adding an intermediate table to show who/when/what, for example:

User
+- ...

Article
+- ...

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

Now this is fine, but the system I'm working on needs to be much more dynamic, in that new modules can be easily introduced and integrated. So now if I add a Media table I need to split the ChangeHistory between Article and Media having:

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

This can get out of hand quickly with the introduction of many modules. Each module would need to be responsible for the creation and management of it's own ChangeHistory table.

TL;DR: What practices can I explore to create an intermediate table that can receive references to multiple other unrelated tables? I could add a *record_type* field, holding the name of the table to which the record belongs, but that's ugly. I would need something like a "table ID" to reference the table from which it's coming. That way, when/if modules are added or removed, the model doesn't fall apart.

Any ideas? Thanks so much in advance.

解决方案

In my experience, when developers try to make their system really "dynamic" they're actually trying to code for problems that they haven't thought of yet. That's usually a bad path to take. Is it really so much extra work for a module to include two tables instead of one?

In every case where I've seen the pattern (or anti-pattern?) of trying to make a generic "does everything" table it's fallen flat on its face. RDBMSs work best with well-defined problem areas. If the module has a need to keep history then the module should add a history table to go with the table itself. This also has a huge advantage in that down the road you're likely to want to keep different types of information in the history depending on the table or module for which the history is being kept. If you have a generic history table that becomes much more difficult.

Now, if you want to simply capture the last user to update or insert a particular item (table row) and that could be in multiple tables then you could use a pattern of inheritance where you have a parent table and multiple children tables. For example:

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)
)

这篇关于数据库表,一个表引用多个不相关的表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆