sql-server - 表创建 - 将常用字段移动到单独的表
问题描述
我有一个场景,三种类型的功能具有相同的字段集(除了它们的主键)。
下面是示例。我想知道,将公共字段分组在一个表中是否更好?如果我们创建一个公用表,如何给对应主键表的FK引用呢?更好的方法是什么?
tbl国家 | 状态 | 城市 |
---|---|---|
乡下人 | 状态标识 | 城市编号 |
姓名 | 国家 ID | 状态标识 |
官方语言 | 官方语言 | 官方语言 |
官方旗帜 | 官方旗帜 | 官方旗帜 |
官花 | 官花 | 官花 |
官方动物 | 官方动物 | 官方动物 |
官鸟 | 官鸟 | 官鸟 |
... | ... | ... |
... | ... | ... |
... | ... | ... |
ETC | ETC | ETC |
解决方案
您预期的第三范式(3NF)本来就很好。从简单的角度来看(影响连接),它尽可能好。国家、州和城市之间的外键是显而易见的和微不足道的。
现在,为了避免复制某些列名,您可以将国家、州和城市这三个元素放入一个表中——有效地使其成为第二范式。这样一来,您的列名的含义就开始角色扮演了。我的意思是官方语言可以与国家、州或城市相关。从存储表设计来看,这不再明显。只能通过多列键的解释。
因此,简而言之,通过节省一些打字/复制,您将使用具有复杂含义的单个表格而不是使用具有明确含义的三个表格来复杂化任何进一步的工作。
现在对于数据选择,只有在没有别名的情况下,这才是一个问题。考虑选择一个国家的城市的官方语言。
SELECT
name,
officialLanguage,
name,
officialLanguage
FROM city
INNER JOIN state
ON state.stateid = city.stateid
INNER JOIN country
ON country.countryid = state.countryid
;
这将失败,因为选择的列不明确。
现在考虑这个查询(别名被缩短只是为了演示别名 - 我个人尝试使用最多 10 个字母的别名):
SELECT
cit.name AS city_name,
cit.officialLanguage AS city_language,
cou.name AS country_name,
cou.officialLanguage aS country_language
FROM city AS cit
INNER JOIN state AS sta
ON sta.stateid = cit.stateid
INNER JOIN country AS cou
ON cou.countryid = sta.countryid
;
它非常简洁明了。我可以在不同的查询中使用国家表,而不必从包含国家、州和城市等混合对象的表中预先选择这些国家。
这种方法的唯一缺点是正确索引表的多重连接。
此外,由于世界上有很多国家、州和城市,这种单表方法可能会成为性能问题。
4NF(或至少 BCNF 或 3.5NF,因为它是其他已知的)最适合在连接中实现快速性能,但在正确索引时连接可能变得复杂(写入)。然而,对于数据库引擎,这些是最容易阅读的。
2NF(或我称之为 Excel 表格)对人类来说最容易阅读。这需要复杂的连接和/或条件(WHERE 子句)才能正确识别一个子集。
对于数据库设计,最好至少使用 3NF 或更好,然后准备视图以将数据转回 2NF,以使您的数据易于阅读。
推荐阅读
- ios - 如何使 SwiftUi 按钮的文本变大和/或加粗
- import - 将csv文件导入py
- python - Asyncpg:KeyError '0'
- c# - 如何将 BIM 360 文件的内容作为文件流读取并将其写入另一个流
- angular - 角度测试未通过 100% 否则未采用路径
- spock - 2 期待 Spock 中的区块?
- mysql - 在 MySQL 存储过程中使用 SELECT...FOR UPDATE 的 ResultSet
- javascript - 电子导航(单页导航)
- r - 创建一个新的 1 和 0 列作为计算 R 中唯一值的方法
- javascript - 在javascript中将响应从服务器流式传输到本地文件?