【问题标题】:SQL - Database normalisationSQL - 数据库规范化
【发布时间】:2015-10-07 17:47:39
【问题描述】:

我有建议的表结构来扩展数据库:

OrganisationalAssets 表中。以下列可以为空:

  • Organisation_Id
  • Lo​​cation_Id
  • Language_Id

我们遇到的问题是Organisation_Id 列仅对某些类型的资产可以为空。有些资产与组织有关,有些则永远不会。对于与组织相关的内容,其他列、位置和语言适用。如果组织为 NULL。那么 Language 和 Location 是这些资产的冗余列。

对我来说,这听起来像是我的表错误地存储了两种类型的资产。内部和外部资产。内部不受组织、语言和位置的限制,而外部资产则受到限制。

但是,我不完全确定如何更改结构以反映这一点。无论它们是内部资产还是外部资产,它们仍然可以有许多与之关联的 AssetSettings。外部资产将具有一组不同的 AssetSettings,具体取决于组织、Location_Id 和 Language_Id,而内部资产则没有。他们每个人都只会有一组设置。

我不确定是否:

  1. 让结构保持原样,因为它可以工作。虽然它没有正确规范化。
  2. 尝试重新构建表格以允许两种类型的资产,如果允许,如何实现。

样本数据 以下是一些示例数据,希望能更清楚地说明我的问题:

组织资产

+----+----------+-----------------+-------------+-------------+
| Id | Asset_Id | Organisation_Id | Location_Id | Language_Id |
+----+----------+-----------------+-------------+-------------+
|  1 |        1 | 2               | 3           | 4           |
|  2 |        1 | 2               | 3           | 999         |
|  3 |        2 | NULL            | NULL        | NULL        |
+----+----------+-----------------+-------------+-------------+

前两行是 AssetId 1。它属于两个不同的位置,是一个外部资产。 第三行是内部资产,因此其他列是多余的。

资产设置

+----+------------------------+------+--------+
| Id | OrganisationalAsset_Id | Key  | Value  |
+----+------------------------+------+--------+
|  1 |                      1 | Key1 | Value1 |
|  2 |                      1 | Key1 | Value1 |
|  3 |                      2 | KeyA | ValueA |
|  4 |                      3 | KeyB | ValueB |
+----+------------------------+------+--------+

在 AssetSettings 表中。我们可以看到 Id1 的资产有两个设置(即 OrganisationalAsset_Id 1 和 2)。 我们还可以看到第二个资产出现在表格中,它只能有一组设置,因为它不属于任何组织、位置或语言。

【问题讨论】:

  • 我会提出的一个建议是停止在任何表中使用 ID 作为列名。如果它是一个 OrganizationID,它应该是每个表中的那个。 ID 太模棱两可了,而且跨表更改名称的列实在是太糟糕了。

标签: sql sql-server database-normalization


【解决方案1】:

嗯,从你描述的结构中我可以看出,标准化数据的最佳解决方案是移动所有这 3 个字段(Organisation_Id Location_IdLanguage_Id)到 [AssetSettings] 表。在这种情况下,您将避免为不适当的资产设置 NULL 值,并且您始终可以随时随地参考必填字段。

您可以完全删除 OrganisationalAsset 表并将 AssetSettings 表直接链接到 Assets 表。

而且您仍然在 一个 表中拥有所有资产,因此您不必将它们拆分两个表中,其中最常见的问题是资产有 两个 ID 字段,因此您需要为每个包含 AssetId 的表保留额外的 AssetType 字段。

【讨论】:

  • 我能做到。但是,我只是将问题移至 AssetSettings 表吗?对于那些从未与组织/语言/位置相关联的资产,它将始终为 NULL。但是,对于外部资产,始终需要本组织。我用一些示例数据更新了我的问题。
  • 对不起,可能是我的错,没有解释清楚。我并不是要按原样移动它们,我的意思是您应该拥有 [Key] = Organisation_Id 以及具有此类信息的那些资产的适当值。我并不是要向表中添加新字段。
  • 因此,如果您的 Asset#1 具有 Organisation_Id,它将在 AssetSettings 表中具有适当的行 - Id = Identity,OrganisationalAsset_Id = 1,[Key] = Organisational_Id,Value = 149。如果它具有 Language_Id 值 - 另一个行,Id = Identity,OrganisationalAsset_Id = 1,[Key] = Language_Id,Value = 3
  • 对不起,如果我很密集,但我不确定你在说什么。您可以使用您正在考虑的表结构类型编辑您的答案吗?
  • 想象一下您的 Organisation_Id、Location_Id 和 Language_Id 是资产的设置。并且您需要以与其他设置相同的方式将它们存储到 AssetSettings 表中吗?不要犹豫,询问更多细节,我很高兴为您提供帮助。如果您可以举例说明将哪些数据存储到 AssetSettings 表中,我将尝试用我的意思来更新答案:)
【解决方案2】:

1) 这似乎是合理的,它是冗余和简单之间的选择,了解数据、使用情况等将帮助您做出此决定。

2) 既然您已经确定了两种不同类型的 Assets,为什么不对其进行建模

Assets (Id, Name, AssetType_Id) 
    -- Id is PK

AssetTypes (Id, Name)
    -- Id is PK

InternalAssets (Id, AssetSettings_Id) 
    -- Id is PK and FK referencing Assets(Id)
    -- AssetSettings_Id is FK referencing AssetSettings

ExternalAssets (Id, Asset_Id, AssetSettings_Id, Organisation_Id, Location_Id, Language_Id)
    -- Id is PK 
    -- Asset_Id is FK referencing Assets(Id)
    -- AssetSettings_Id is FK referencing AssetSettings

AssetSettings (Id, Setting1, Setting2, Setting3)
    -- Id is PK 

您可能希望添加一个约束,使 InternalAsset 不能是 ExternalAsset,反之亦然。

您还可以创建OrganisationalAssets 的视图,这将合并两个*Assets 表,这可能有助于简化查询。

【讨论】:

  • 我唯一的问题是 AssetSettings 表。如果我有一个资产(在资产表中)并且它属于相同的组织和位置,但有两种不同的语言(在 ExternalAssets 中,因为它是一对多的)。这意味着我可以拥有两组 AssetSettings,每个 ExternalAsset 一组。一个用于位置 x,一个用于位置 Y。当我尝试获取位置 X 的 AssetSettings 时,我不能,因为 AssetSettings 不理解 ExternalAsset 的概念。
  • 我认为这个问题可以通过不使用 AssetSettings 的 EAV 表来解决,请参阅我的更新答案。
猜你喜欢
  • 2011-11-17
  • 1970-01-01
  • 2012-11-18
  • 2011-04-05
  • 2011-09-28
  • 2012-10-08
  • 2012-06-21
相关资源
最近更新 更多