Dan*_*ugg 5 mysql sql database-design foreign-key-relationship
在我的搜索中,这个问题已在各种论坛中出现过几次,但没有一个提供简洁的解决方案.
如果我有以下表格:
User
+- id
+- username
+- password
Article
+- id
+- title
+- content
Run Code Online (Sandbox Code Playgroud)
我想加入他们以确定谁创建了哪些文章,我只需将user_id列添加到文章中即可用作参考.或者,我正在添加一个中间表来显示谁/何时/什么,例如:
User
+- ...
Article
+- ...
ChangeHistory
+- id
+- article_id
+- user_id
+- type [enum(insert, update, delete)]
+- datetime
Run Code Online (Sandbox Code Playgroud)
现在这很好,但我正在研究的系统需要更加动态,因为新模块可以很容易地引入和集成.所以现在如果我添加一个Media表,我需要在Article和Media之间拆分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
Run Code Online (Sandbox Code Playgroud)
通过引入许多模块,这可能会很快失控.每个模块都需要负责创建和管理自己的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 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)
)
Run Code Online (Sandbox Code Playgroud)