Database design 许多表格共有的建模数据

Database design 许多表格共有的建模数据,database-design,Database Design,我有一个动态数据模型,可能有数千个实体表,我们称它们为E1、E2、…,或者通常称为EX 还有少量实用程序表,其中包含可能附加到这些实体的数据,例如审计表或“附加文档”表,我们将它们称为U1、U2、…,或者通常称为UX 每对EX-UX的关系为1对多(例如,E1中的每个实例可能有多个附加文档,但每个文档仅附加到任何EX中的一个实例) 基本问题是每个UX包含引用不同表的行 有几种方法可以对这种关系建模: 链接表解决方案 为每对EX/UX创建一个链接表。例如: E1_U1 ( E1_ID FK

我有一个动态数据模型,可能有数千个实体表,我们称它们为E1、E2、…,或者通常称为EX

还有少量实用程序表,其中包含可能附加到这些实体的数据,例如审计表或“附加文档”表,我们将它们称为U1、U2、…,或者通常称为UX

每对EX-UX的关系为1对多(例如,E1中的每个实例可能有多个附加文档,但每个文档仅附加到任何EX中的一个实例)

基本问题是每个UX包含引用不同表的行

有几种方法可以对这种关系建模:

链接表解决方案

为每对EX/UX创建一个链接表。例如:

E1_U1 (
    E1_ID FK TO E1
    U1_ID FK TO U1
)
  • 优点:干净。EX的型号不变
  • 缺点:表的数量激增,我们也可以为每个实体创建每个实用程序表的实例。如果我需要反向查找,例如,在EX中显示U1中某个实例引用的实例,我需要搜索所有链接表EX_U1

实体表解决方案

创建一个新的表实体,其中包含一个列实体_ID,这是任何EX中每行的唯一ID。在这个模型中,用实体_ID替换每个EX的主键是有意义的

ENTITY (
    ENTITY_ID PK
)

E1 (
    ENTITY_ID PK, FK TO ENTITY
    ...
)

U1 (
    U1_ID PK
    ENTITY_ID FK TO ENTITY
    ...
)
  • 优点:我想这是建模继承的标准方法
  • 缺点:显著更改了数据模型和应用程序逻辑。 只有通过在所有EX中搜索正确的实体ID才能进行反向查找
键入外键解决方案

为每个UX指定两列作为“类型化外键”:ETABLE\u ID和ETABLE\u ROW\u ID。ETABLE\u ID引用该表(即哪个EX),ETABLE\u ROW\u ID引用该表中的行

在我的模型中,这是可能的,因为

  • 我已经在应用程序逻辑中保留了实体表的元模型,因此ETABLE_ID随时可用
  • ETABLE_ROW_ID保证为所有E的相同类型
  • 优点:不改变EX的模型。反向查找可以在应用程序逻辑中轻松实现
  • 缺点:问题显然是我们不能将外键约束应用于ETABLE_ROW_ID
虽然它不是干净的关系设计,但我仍然支持最后一种解决方案,因为它具有实际优势。我可以在应用程序逻辑中建模的丢失的引用完整性


这个问题的首选解决方案是什么?有经验/建议吗?

类型为的实体表解决方案:

ENTITY (
    ENTITY_ID PK,
    ENTITY_TYPE,
    UNIQUE KEY (ENTITY_ID, ENTITY_TYPE)
)

E1 (
    ENTITY_ID PK, 
    ENTITY_TYPE, constrained to value '1'
    FK (ENTITY_ID, ENTITY_TYPE) TO ENTITY table    
    ...
)

U1 (
    U1_ID PK
    ENTITY_ID FK TO ENTITY
    ...
)
将类型存储在实体表中的优点是,您不必搜索所有E表来找出它是什么类型

每个E表都将自己的类型约束为固定值,因此E1中的任何行自然只能引用类型为1的实体行

另见:

  • 我过去对标签的回答
  • 我的演讲
  • 我的书

在U中包含来自E的唯一实体id的复合键、E1(或Ex)中的行的外键以及U中的顺序id列如何?这将允许任何数量的实体只有一个U。我不确定我是否理解。“来自E的唯一实体\u id”是指“实体表”解决方案吗?为了便于讨论,我对问题中的EX/UX术语做了一些清理。
ENTITY (
    ENTITY_ID PK,
    ENTITY_TYPE,
    UNIQUE KEY (ENTITY_ID, ENTITY_TYPE)
)

E1 (
    ENTITY_ID PK, 
    ENTITY_TYPE, constrained to value '1'
    FK (ENTITY_ID, ENTITY_TYPE) TO ENTITY table    
    ...
)

U1 (
    U1_ID PK
    ENTITY_ID FK TO ENTITY
    ...
)