Database design 如何引用最初在另一个表中未知的表映射

Database design 如何引用最初在另一个表中未知的表映射,database-design,Database Design,我有四个表:ExternalName,InternalName,ExternalInternalNameMap和TransactionExternalName和InternalName具有多对多关系。ExternalInternalNameMap是ExternalName和InternalName之间的连接表 制约因素包括: 一个事务只能有一个ExternalName和一个与其关联的InternalName ExternalName可以有许多事务 一个InternalName可以有许多事务

我有四个表:
ExternalName
InternalName
ExternalInternalNameMap
Transaction

ExternalName和InternalName具有多对多关系。ExternalInternalNameMap是ExternalName和InternalName之间的连接表

制约因素包括:

  • 一个事务只能有一个ExternalName和一个与其关联的InternalName
  • ExternalName可以有许多事务
  • 一个InternalName可以有许多事务
因此,ExternalInternalNameMap可以有许多事务,而一个事务只能对应于一个ExternalInternalNameMap

事务表必须连接到其他表,以便ExternalName和InternalName可以与事务关联

在事务表中使用ExternalInternalNameMap.Id作为外键似乎是一种自然选择,但当一行最初添加到事务表中时,只有ExternalName是已知的。稍后,用户将外部名称映射到内部名称。只有这样,我们才能在ExternalInternalNameMap中有一行。用户需要查看事务数据以了解如何将ExternalName映射到InternalName

选项A
事务可以有一个fk到ExternalInternalNameMap,但InternalNameId(在该表中)最初将为空。在这种情况下,我们无法在该表中强制执行重复的InternalNameId和ExternalNameId组合

选项B
事务可以包含fk到ExternalName和fk到InternalName(最初为空)。但在这种情况下,数据库不会强制事务包含有效的ExternalName和InternalName映射

有没有其他方法可以解决这些问题


编辑:更正的图表

外键不能解决所有问题;暂时忘掉他们吧

当出现新交易时:

  • 如果尚未插入内部和/或外部名称,则插入这些名称 存在
  • 如果关系不存在,则插入到映射中
  • 插入到事务中
  • 请注意,通过按此顺序执行这三个步骤,始终可以确保在与行建立FK关系之前存在一行。(哎呀,为什么要费心声明FKs?)

    所以,我想我是在投票支持类似选项A的东西


    请记住,无论何时您需要从事务进入内部,都需要遍历映射——这是两个连接。同样,2连接到另一个方向。因此,确保每个方向都有索引。(FK在一个方向上生成索引。)

    我建议将A和B选项组合使用。

    要在数据库设计级别强制实施完整性约束,您需要在连接表上使用复合主键。
    ExternalInternalNameMap
    的主键将是
    {EN\u ID,IN\u ID}

    使用可选外键
    ExternalInternalNameMap
    inside
    Transaction
    table pulse检查约束将导致一致性。

    Transaction table = {FK_EN_ID, FK_EINM_EN_ID, FK_EINM_IN_ID, ...}
    
    检查事务表上的约束=

    {FK_EINM_EN_ID is null OR (FK_EINM_EN_ID = FK_EN_ID)}
    

    一种可能的方法是引入“未知”内部名称的概念。 对于每个外部名称,还可以在
    externalnamemap
    中引入一条记录,将该外部名称映射到一个特殊的内部名称“Unknown”。因此,对于每个外部名称,(最多)都存在一个这样的“未知”映射

    基本上,只需遵循方法A。创建事务时,请参考相应外部名称的“未知”映射。一旦知道内部名称,更新交易;使其引用
    externalnamemap
    中包含“完整”映射的记录

    注意,我们在这里没有引入重复映射;您可以对组合
    (ExternalNameId,InternalNameId)
    设置唯一约束

    可能的变化:

    • 您也可以决定在表
      externalnamemap
      中使用空引用,而不是在表
      internalnamemap
      中使用专用记录“Unknown”(或“TBD”或其他任何内容)。这确实要求列
      InternalNameId
      可以为空
    • 您可以预先创建“未知”映射(对于表
      ExternalName
      中的每个记录,
      externalnamemap
      中只有一条记录将该外部名称映射到“未知”),或者您可以在需要时创建“未知”映射(除非它已经存在),即在创建事务时

    检查图表上的1::*符号,我认为其中一个是反向的。Rick是对的,应该颠倒
    ExternalInternalNameMap
    InternalName
    之间的关系。莫森答案中的图表是正确的。