首页 > 解决方案 > 表创建 - 将常用字段移动到单独的表

问题描述

我有一个场景,三种类型的功能具有相同的字段集(除了它们的主键)。

下面是示例。我想知道,将公共字段分组在一个表中是否更好?如果我们创建一个公用表,如何给对应主键表的FK引用呢?更好的方法是什么?

tbl国家 状态 城市
乡下人 状态标识 城市编号
姓名 国家 ID 状态标识
官方语言 官方语言 官方语言
官方旗帜 官方旗帜 官方旗帜
官花 官花 官花
官方动物 官方动物 官方动物
官鸟 官鸟 官鸟
... ... ...
... ... ...
... ... ...
ETC ETC ETC

标签: sql-serverdatabase-design

解决方案


您预期的第三范式(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,以使您的数据易于阅读。


推荐阅读