如何引用最初在另一个 table 中未知的 table 映射
How to reference a table mapping that is not initially known in another table
我有四个 table:ExternalName
、InternalName
、ExternalInternalNameMap
和 Transaction
。
ExternalName 和 InternalName 有很多对许多关系。 ExternalInternalNameMap 是 ExternalName 和 InternalName 之间的连接 table。
约束是:
- 一笔交易只能有一个 ExternalName 和一个与之关联的 InternalName。
- 一个 ExternalName 可以有很多事务。
- 一个 InternalName 可以有很多事务。
因此一个ExternalInternalNameMap可以有多个事务,一个事务只能对应一个ExternalInternalNameMap。
事务 table 必须加入其他 table,以便 ExternalName 和 InternalName 可以与事务相关联。
将 ExternalInternalNameMap.Id 作为事务 table 中的外键似乎是一个自然的选择,但是当一行最初添加到事务 table 时,只有 ExternalName 是已知的。后来,用户将 ExternalName 映射到 InternalName。只有这样我们在 ExternalInternalNameMap 中才有一行。用户需要查看交易数据才能知道如何将 ExternalName 映射到 InternalName。
选项 A:
事务可能有一个到 ExternalInternalNameMap 的 fk,但 InternalNameId(在 table 中)最初将为 NULL。在那种情况下,我们不能在 table 中强制执行重复的 InternalNameId 和 ExternalNameId 组合。
选项 B:
事务可以包含到 ExternalName 的 fk 和到 InternalName 的 fk(最初为 NULL)。但是在那种情况下,数据库不会强制事务包含有效的 ExternalName 和 InternalName 映射。
是否有其他方法可以解决这些问题?
编辑:更正图表
FOREIGN KEYS不能解决所有问题;暂时忘记他们...
当新交易出现时:
- 插入到内部 and/or 外部,如果这些名称还没有
存在
- 如果关系不存在则插入到 Map 中
- 插入交易。
请注意,通过按顺序执行这三个步骤,您始终可以保证在与某行建立 FK 关系之前存在该行。 (哎呀——为什么要声明 FK?)
所以,我想我会投票给选项 A。
请记住,无论何时您需要从 Transaction 进入 Internal,您都需要通过 Map —— 即两个 JOIN。并且,类似地,2 个 JOIN 去往另一个方向。因此,请确保每个方向都有索引。 (FK 生成一个方向的索引。)
我建议结合使用 A 和 B 选项。
要在数据库设计级别实施完整性约束,您需要在联结点上使用复合主键 table。
ExternalInternalNameMap
的 PK 将是 {EN_ID, IN_ID}
在 Transaction
table 中有一个可选的外键 ExternalInternalNameMap
脉冲检查约束将导致一致性。
Transaction table = {FK_EN_ID, FK_EINM_EN_ID, FK_EINM_IN_ID, ...}
检查交易约束 table =
{FK_EINM_EN_ID is null OR (FK_EINM_EN_ID = FK_EN_ID)}
一种可能的方法是引入 'unknown' 内部名称的概念。
对于每个外部名称,您还在 ExternalInternalNameMap
中引入一条记录,将该外部名称映射到一个特殊的内部名称 'Unknown'。因此对于每个外部名称,(最多)存在一个这样的 'unknown' 映射。
基本上,按照方法A即可。创建交易时,请参考相应外部名称的'unknown'映射。一旦内部名称已知,更新交易;使其引用 ExternalInternalNameMap
中包含 'full' 映射的记录。
注意我们不是在这里引入重复映射;您可以对 (ExternalNameId, InternalNameId)
.
组合施加唯一约束
可能的变化:
- 而不是在 table
InternalName
中使用专用记录 'Unknown'(或 'TBD' 或其他),您还可以决定在 [=] 中使用 NULL 引用44=] ExternalInternalNameMap
。这确实需要列 InternalNameId
可以为空。
- 您可以预先创建 'unknown' 映射(对于 table
ExternalName
中的每条记录,ExternalInternalNameMap
中恰好有一条记录将该外部名称映射到 'unknown'),或者您可以在需要时创建 'unknown' 映射(除非它已经存在),即在创建交易时。
我有四个 table:ExternalName
、InternalName
、ExternalInternalNameMap
和 Transaction
。
ExternalName 和 InternalName 有很多对许多关系。 ExternalInternalNameMap 是 ExternalName 和 InternalName 之间的连接 table。
约束是:
- 一笔交易只能有一个 ExternalName 和一个与之关联的 InternalName。
- 一个 ExternalName 可以有很多事务。
- 一个 InternalName 可以有很多事务。
因此一个ExternalInternalNameMap可以有多个事务,一个事务只能对应一个ExternalInternalNameMap。
事务 table 必须加入其他 table,以便 ExternalName 和 InternalName 可以与事务相关联。
将 ExternalInternalNameMap.Id 作为事务 table 中的外键似乎是一个自然的选择,但是当一行最初添加到事务 table 时,只有 ExternalName 是已知的。后来,用户将 ExternalName 映射到 InternalName。只有这样我们在 ExternalInternalNameMap 中才有一行。用户需要查看交易数据才能知道如何将 ExternalName 映射到 InternalName。
选项 A:
事务可能有一个到 ExternalInternalNameMap 的 fk,但 InternalNameId(在 table 中)最初将为 NULL。在那种情况下,我们不能在 table 中强制执行重复的 InternalNameId 和 ExternalNameId 组合。
选项 B:
事务可以包含到 ExternalName 的 fk 和到 InternalName 的 fk(最初为 NULL)。但是在那种情况下,数据库不会强制事务包含有效的 ExternalName 和 InternalName 映射。
是否有其他方法可以解决这些问题?
编辑:更正图表
FOREIGN KEYS不能解决所有问题;暂时忘记他们...
当新交易出现时:
- 插入到内部 and/or 外部,如果这些名称还没有 存在
- 如果关系不存在则插入到 Map 中
- 插入交易。
请注意,通过按顺序执行这三个步骤,您始终可以保证在与某行建立 FK 关系之前存在该行。 (哎呀——为什么要声明 FK?)
所以,我想我会投票给选项 A。
请记住,无论何时您需要从 Transaction 进入 Internal,您都需要通过 Map —— 即两个 JOIN。并且,类似地,2 个 JOIN 去往另一个方向。因此,请确保每个方向都有索引。 (FK 生成一个方向的索引。)
我建议结合使用 A 和 B 选项。
要在数据库设计级别实施完整性约束,您需要在联结点上使用复合主键 table。
ExternalInternalNameMap
的 PK 将是 {EN_ID, IN_ID}
在 Transaction
table 中有一个可选的外键 ExternalInternalNameMap
脉冲检查约束将导致一致性。
Transaction table = {FK_EN_ID, FK_EINM_EN_ID, FK_EINM_IN_ID, ...}
检查交易约束 table =
{FK_EINM_EN_ID is null OR (FK_EINM_EN_ID = FK_EN_ID)}
一种可能的方法是引入 'unknown' 内部名称的概念。
对于每个外部名称,您还在 ExternalInternalNameMap
中引入一条记录,将该外部名称映射到一个特殊的内部名称 'Unknown'。因此对于每个外部名称,(最多)存在一个这样的 'unknown' 映射。
基本上,按照方法A即可。创建交易时,请参考相应外部名称的'unknown'映射。一旦内部名称已知,更新交易;使其引用 ExternalInternalNameMap
中包含 'full' 映射的记录。
注意我们不是在这里引入重复映射;您可以对 (ExternalNameId, InternalNameId)
.
可能的变化:
- 而不是在 table
InternalName
中使用专用记录 'Unknown'(或 'TBD' 或其他),您还可以决定在 [=] 中使用 NULL 引用44=]ExternalInternalNameMap
。这确实需要列InternalNameId
可以为空。 - 您可以预先创建 'unknown' 映射(对于 table
ExternalName
中的每条记录,ExternalInternalNameMap
中恰好有一条记录将该外部名称映射到 'unknown'),或者您可以在需要时创建 'unknown' 映射(除非它已经存在),即在创建交易时。