问题描述
编辑:目前我将保持问题开放。得到一个非常粗略的答案。
很快,这是一个架构
问这个问题是因为来自这个话题 https://www.sisense.com/blog/when-and-how-to-use-surrogate-keys/
结合自然键和代理键某些业务场景可能 需要保持自然键完整,作为用户的一种手段 与数据库交互。在这些情况下……
如果推荐使用自然键,请使用代理键字段作为 主键,自然键作为外键。虽然用户可能 与自然键交互,数据库仍然可以有代理 用户视线之外的键,不会打扰用户 体验。
如果必须使用自然键而不需要额外的 代理键,请务必将其与代理键元素结合使用。在 我们的财务数据库示例,费用报告 (ER-123) 有一个 自然键与代理顺序键结合使用。 这种格式可以防止列出的许多自然关键副作用
我真的发现也许可以解决我的问题。因为怕代理键。但是 XPO 和 ORM 提供程序支持代理键 (100%)。不像复合键。在许多文章中将其描述为新数据库设计中的一个错误。 Surrogate Key vs Natural Key for EF Surrogate vs. natural/business keys
还有很多关于这个的文章。这不是这里的情况。我说的是组合或使用代理键并添加自然键(作为索引或唯一索引,而不是PK) 现在回到上面的架构和上面谈论结合两者的主题。我有一个有代理键 Oid 的分支,所有表都有 Oid 作为代理键。我也有自然键,例如(BranchID),
-
@H_502_27@分支表具有 (Oid[surrogate],BranchID[Natural Key - Unique Index not PK]
@H_502_27@InvTransHed 有 (Oid[Surrogate],itd_brn,itd_type,ith_num) 作为自然键(我的意思是唯一索引)
@H_502_27@InvTransDet 有 (Oid[Surrogate],itd_brm,itd_typ,itd_num,itd_lne 作为自然键 [唯一索引])
我实际上所做的是将所有代理键 Oid 与其外键端联系起来。例如: Branch.Oid 与 InvTransHed.BranchSKey 关联 [Skey = 代理键]
为什么我需要将 Surrgoate Key 与 Natural Key(作为唯一索引)结合起来?
-
@H_502_27@使用 JOIN 轻松创建报告(直接使用 InvTransDet 分支,无需移动到 InvTransHed)。
@H_502_27@技术支持的可读性。无需关心代理键即可轻松进行任何连接。或链接到父表,直到达到我们需要的程度。
@H_502_27@易于理解和 ORM 提供程序(肯定 100% 友好)
这里有一个让我大吃一惊的问题:
-
@H_502_27@我是否应该只将代理键与其另一侧的外键联系起来。或者我还必须将自然索引链接到它们的自然键。 Branch.BranchID => InvTransHed.ith_brn?
@H_502_27@关于命名对方 FK。 Branch.Oid 代理链接与 InvTransHed.BranchSkey。对于可读性而言,命名在这里是否重要?
@H_502_27@请指导我(标题 = 问题)。
解决方法
PK 和 FK 等约束是我们记录和强制执行数据库参照完整性的主要机制。
我们不能仅依靠文档和数据架构命名约定来向开发人员和用户解释如何解释数据。使用 RDBM 的重点是保持参照完整性。引用和任何检查约束构成了将数据插入数据库时必须遵守的规则的“真相”基础。
您正确地指出您要强制FK 和Natural 代理键的组合的唯一性,因此主要是约束。
如果约束的存在没有问题,那么我们只需要考虑索引。
-
Unique Constraint vs Unique Index
Unique Constraint 没有必要也与唯一 Index 配对,但是对于开发人员发现它只是更多的文档或者,如果您也将其定义为索引,则至少更容易被发现。
当或如果性能成为问题时,您可能会更改索引的唯一性或将其完全删除,但是您总是希望在这种情况下保持唯一性约束以确保索引的完整性数据。
虽然不是必要,但一致的命名约定有助于提高数据模式的可读性并解释结构的意图,一致性是关键,但首先当您违反约定时,读者现在必须怀疑或再次猜测之前的所有假设。
因此,如果约定可能受到质疑,约束的存在总是会提供明确的答案。
您使用的实际命名约定成为设计者的个人偏好。我使用 Id
作为 PK 和 {tablename}Id
作为 FK。当链接不明确时,例如一个表对自身有 FK,或同一个表有多个 FK,然后我用 名词 或 动词 作为该列的前缀来描述关系:CreatedBy_UserId
vs ModifiedBy_UserId
我觉得这个约定适合于可读和自然的 SQL 和 C# 语法。
SELECT ID,Description,Modified,ModifiedBy.Name
FROM Product
INNER JOIN User [ModifiedBy] ON Product.ModifiedBy_UserId = ModifiedBy.Id
作为惯例,我知道 PK 是 always Id
,所以无论在哪里使用它,您都可以假设它是 principal关系。
除非需要自然键,否则您永远不必有代理键和主键。 因为自然键受制于:
- 更长的长度而不是技术PK(以INT IDENTITY为例)
- 由于用户输入错误导致的一些更新
- 不稳定的价值观的分散
- 最棒的是:数据类型可以在数据库的生命周期中改变(最近欧洲标准化了车辆登记,因此每个欧洲国家都必须为其更改数据类型!)
密钥越长,性能越差,维护成本越高。
更新 PK 是一场噩梦,尤其是当有许多外键依赖它们时!
当一个键的值作为一个不稳定的分散时,收集的统计数据不太准确,因此可能会导致不太好的执行计划
改变一个自然键的数据类型会长时间阻塞很多表...
但不要忘记您可以拥有依赖于唯一键的外键。 FK 约束是基于另一个 UNIQUE 或 PK 约束的约束...