我有一个 MySQL 数据库,其中包含 3 个包含主要数据类的表:
companies (company_id)
persons (person_id, company_id)
loans (loan_id, company_id)
“贷款”和“人”都属于公司。公司可以有贷款,公司可以有人员(如董事、员工等)
在几种情况下,其他数据可能属于公司、个人或贷款,例如“笔记”。例如,用户可以添加特定于公司、个人或贷款的“注释”。
还有其他示例,例如“地址”和“电话号码”,它们可以属于公司或个人。
我显然希望有一个数据表,例如“笔记”、“地址”和“电话号码”,但是我正在努力寻找将这些数据与公司、人员和贷款联系起来的最佳方式。
让我们在这里使用“笔记”作为示例。
更好的做法是:
1/ Have 3 extra tables linking 'notes' to companies people and loans:
notes(note_id)
persons_notes(person_id, note_id)
companies_notes(company_id, note_id)
loans_notes (loan_id, note_id)
2/ Have a single table 'entities' which has a primary key entity_id used to link all 3 tables:
entities(entity_id)
persons(person_id, entity_id)
companies(company_id, entity_id)
loans (loan_id, entity_id)
notes (note_id, entity_id)
后者在逻辑上是有道理的,但感觉不对,因为个人和公司是与贷款完全不同的一类数据。不知怎的,感觉很脏。
备注和地址将与贷款、个人和公司建立一对多的关系。也就是说,一家公司可能有很多地址或备注。这就是我考虑链接表的原因。
一家公司可以有一个注册地址和无限的交易地址。一个人可以有一个当前地址和以前的地址(如果当前地址少于 3 年)。
在这种情况下,拥有贷款(商业贷款)的是公司。人属于公司,通常是公司的董事。所以,一家公司可以有很多人和很多贷款。
- 一个公司/个人/贷款每人可以有很多笔记
- 一个公司/个人可以有多个地址
这个问题(以各种形式)经常出现在这个论坛上。
它被称为 EAV(实体属性值)。有充分的理由,它被称为反模式。有很多理由不使用这种形式的数据模型。它们在此处、此处和此处进行了概述(+ 中的链接请查看同一线程中其他发帖人的回复)。
并非所有人都同意 EAV 总是一件坏事,只是在大多数情况下。Aaron Bertrand(这个小组的大人物)就此事写了这篇文章。然而,我的建议是坚持传统的设计,并且(可能)让自己的生活更轻松。
为什么不像你描述的那样只有三个主表
和两个“附属”表
那么 Person、Company 和 Loan 可以有 Address_id 和 Note_id 字段。不需要复杂的链接表(至少现在还不需要:-))。或者首先,您甚至可以在主表中包含注释和地址(如果曾经有一个地址和一个注释 (BLOB) 字段)?
无论您做什么,在您成为经验丰富的数据建模师之前,请避免使用 EAV。ps 欢迎来到论坛!
[编辑]
您能告诉我们您使用的是哪个 RDBMS 吗?可能对我的回复有些影响。这里的版主不喜欢长时间的乒乓式聊天。
我“拼凑”了一个图表和脚本,可以帮助您入门。
任何进一步的问题/问题,让我知道。大部分应用程序设计和数据建模都是反复试验——你生成一个数据模型,开始对它进行编程,你会发现你最初的想法无法发挥作用的各种方式。这就是原型设计的目的。给它一个bash,然后解决问题。
以及该图表中的脚本。
我通常做的是通过将分层数据结构存储在以简单键为键的 CLOB 中并添加审计字段和乐观锁定版本来避免该问题。
每个表都是一个“模式”。
从技术上讲,您也可以使用文件来执行此操作,但是您必须处理备份两件事。
但是,我确实在数据库中保留了查询和关系数据,但我没有限制自己遍历多个表并加入它们(使用像 Hibernate 这样的对象关系映射器更容易),我使用R DBMS 作为其主要强度关系映射。
如果我在“数据”表中添加一条新记录,会发生什么情况,我会在要查询的关系表和查找表中构建相应的条目。
它的好处是,如果您能够处理备份两组事物,您可以将数据作为单独的文件,让您的数据库只有关系/查找数据。这是 Mail.app 在 mac 和 WinAmp 中完成的方法。
您也不会被困在您的结构中,因为您可以根据需要使用文件进行重建。