我对数据建模非常陌生,根据微软的实体框架,不允许没有主键的表,这显然是个坏主意。我试图找出为什么这是一个坏主意,以及如何修复我的模型,以便我没有这个洞。
我目前的模型中有4个表:User,City,HelloCity和RateCity。它的建模如图所示。这个想法是许多用户可以访问许多城市,用户只能对一个城市进行一次评级,但他们可以多次迎接一个城市。出于这个原因,我在HelloCity表中没有PK。
有关如何更改此内容以符合最佳做法的任何见解,以及为什么这会违反最佳做法?
答案 0 :(得分:9)
此回复主要以意见/经验为基础,因此我列举一些浮现在脑海中的理由。请注意,这并非详尽无遗。
以下是您应该使用主键(PK)的一些原因:
TableA.id
是否引用了TableB.table_a_id
?如果TableB.table_a_id = 5
,那么保证在id = 5
中有一行TableA
。保持数据完整性和一致性,这很好。在我看来,不拥有PK可能合法(即RDBMS会让你),但它不是道德(即你不应该这样做)。我认为你需要有非常好/有力的理由来争辩不在你的数据库表中使用PK(我仍然觉得它们有争议),但是根据你目前的经验水平(即你说你是“数据建模的新手”),我说它还不足以证明缺乏PK的合理性。
还有更多的理由,但我希望这足以让你完成它。
就你的M:M
关系而言,你需要创建关联表,你可以在其中创建一个复合PK,PK是其他两个表的2个PK的组合。
换句话说,如果表M:M
和A
之间存在B
关系,那么我们会创建一个与C
关联的表1:M
同时使用表格A
和B
。 “图形化”,它看起来类似于:
+---+ 1 M +---+ M 1 +---+
| A |------| C |------| B |
+---+ +---+ +---+
C
表PK有点像这样:
+-----+
| C |
+-----+
| id | <-- C.id = A.id + B.id (i.e. combined/concatenated, not addition!)
+-----+
答案 1 :(得分:3)
主键实质上标记了具有唯一标识符的行。这可以由一行中的一列或多列组成,但最常见的只是使用一列。使其有用的部分原因是当您有其他表(例如场景中的表)时,您可以在其他表中引用此值。由于它是唯一的,我可以在另一个表(例如HelloCity
)中查看具有该唯一ID的列,并立即知道在User表中查找的位置以获取有关该列所指的人的更多信息
例如,HelloCity
仅存储User
和City
的ID。为什么?因为当您已将其存储在其他位置时,重新记录有关City
的所有数据以及另一个表中有关User
的所有数据,这是愚蠢的。它的美妙之处在于,用户需要出于某种原因更新其DisplayName
。为此,您只需在User中进行更改即可。现在,引用用户的任何行都会立即返回新的DisplayName
;否则你必须使用旧的DisplayName
查找每条记录并相应地更新它,这在较大的数据库中可能需要相当长的时间。
请注意,主键在该特定表中仅是唯一的 - 理论上您可以在City
和User
表中看到相同的主键值(如果您&#39;重新使用简单整数作为ID)但您的数据库将根据您在表之间建立的关系以及查询中的JOIN语句来了解差异。
主键帮助的另一种方式是它们自动在列上生成索引。这可以提高WHERE子句搜索主键列值的查询的性能。而且,由于您可能会在其他表中引用该主键,因此它也可以更快地进行查找。
在您的数据模型中,我看到一些列已经有了&#39; Id&#39;在他们中。在不知道您的数据集的情况下,我希望那些已经具有所有唯一值的数据,因此在这些数据库上放置PK应该没问题。如果您在执行此操作时出错,则可能存在重复。
回到关于HelloCity
的问题 - 当涉及到密钥时,实体框架有点挑剔。如果你真的想要安全地玩它,你可以为每个条目自动生成一个唯一的ID,并称之为好。这是有道理的,因为它是多对多的关系,这意味着任何组合都可以出现任意次数,因此理论上没有可靠的方法来区分唯一条目。如果您希望将来删除单个条目,您如何知道要引用的行?您可以在所有字段上进行搜索并且问候语可能不同,但如果对具有相同问候语的城市进行多次访问,您可能会意外删除所有这些记录而不只是一个。
但是,如果它是一对一的关系,您可以将CityId
和UserId
组合成主键,因为该组合应始终是唯一的(因为您应该从来没有看到多行进行相同的组合。)
答案 2 :(得分:2)
主键的两个主要原因:
答案 3 :(得分:0)
晚了聚会,但我想补充一点,在特殊情况下,表不需要主键或任何类型的键。
例如,以 singleton 为例。始终包含单行(或行数众所周知)的表。 Oracle中的dual
表就是一种情况。
通常,单例的主键为()
:即没有列的键。不过,我不知道任何允许它的数据库。
在其他情况下,不需要PK,通常使用通常是“端表”的日志表,因为通常将其绘制在图的边界;没有其他表格引用它们(即它们没有子代)。充分利用索引就足以应对它们,因为从本质上讲,它们不需要强制执行行唯一性。
但是,要关闭,是的,关系数据库中99.99%的表应该具有PK。