SQL 第一范式 (1NF) 与序列化
Posted
技术标签:
【中文标题】SQL 第一范式 (1NF) 与序列化【英文标题】:SQL First Normal Form (1NF) vs Serialisation 【发布时间】:2022-01-12 13:26:18 【问题描述】:假设我有一个足球队表,其中球员姓名与位置相关联:
teamId: 1
goalkeeper: 'Marc'
position1: 'John'
position2: 'Erik'
...
但现在我还想要一个属性来代表不考虑位置的玩家。我将创建一个新属性 teamString
序列化所有按字母顺序排序的玩家(这将确保具有相同玩家的不同 Teams
将具有相同的 teamString
属性):
teamString: Eric-John-Mark[...]
现在我可以过滤Teams
与相同的球员,即使他们在不同的位置上比赛。
这个新属性teamString
会违反1NF原则吗?
提前致谢
【问题讨论】:
只是为了确保我理解:您希望能够获得每支球队的球员名单,无论他们的位置如何? 没错,有时同一个玩家可能会被放在不同的位置。有时我需要根据球员的位置来寻找球队。 不要存储Eric-John-Mark
,而是使用GROUP_CONCAT()
计算它。
"1NF" has many meanings. (所有这些都涉及用一些表用参数化结构替换一些表,每个参数有一列。)“非规范化”和“UNF”和“0NF”&就此而言也是如此“关系”。因此,您需要告诉我们您的定义,最好还告诉我们教科书名称和版本。你是怎么被困在告诉你是否违反了你选择的“1NF”的?
【参考方案1】:
您的teamString
属性将违反1NF,因为您的teamString
属性将包含多个值。它会引用同一实体的非键属性中存在的值(可能是 3NF 违规,但我不确定)。
这里的问题是您将团队中的特定职位视为团队的属性,而不是关系。
我会在 team 和 player 之间建立关系:
team (1, n) - (0, n) player
一个团队可能有一对多的玩家。 玩家可以为零到多支球队效力。
由于两个最大基数都到 n
,你会得到一个 Many To Many 关系,这意味着 join table 带有来自双方的外键(团队 id + 玩家 ID)。在此表中,您可以为职位类型添加一列。
这意味着您应该删除团队表中的位置列(
goalkeeper
、position1
、...)。
position 表可能如下所示:
team_id | player_id | type |
---|---|---|
1 | 12 | goal_keeper |
1 | 15 | position1 |
2 | 12 | position_2 |
然后,该应用程序可能负责检查一支球队在特定位置上只有有限数量的球员。但是对于建模,您应该坚持在基数中使用的 0、1 和“n”值。
【讨论】:
以上是关于SQL 第一范式 (1NF) 与序列化的主要内容,如果未能解决你的问题,请参考以下文章