【问题标题】:Do I really need a relation table in my case?我真的需要一个关系表吗?
【发布时间】:2015-02-06 14:00:58
【问题描述】:

假设我有一个模块。我构建了一个界面,用户可以在其中将模块分配给组。 可以说目前我有 3 个组。在 UI 中,用户将选择所有 3 个组来将模块分配给他们。例如在多个选择框中。

用户的意图是将模块分配给所有组。

我想我需要一个多对多关系表。我的源代码会执行一个 sql 查询来插入 3 个条目。

但是等等。如果两周后管理员添加了一个新组怎么办...在关系表中只有 3 个条目。用户想知道为什么模块没有分配给新添加的组。

什么是优雅的解决方案?我需要确定更新关系表,或者我在我的模块表中创建一个新列 - 称为“组” - 我以这种格式添加分配的 groupsId:“1;2;7;15”或关键字“全部”。 优点是使用关键字“All”,我可以在我的代码中知道该模块已分配给所有组。 使用关系表我没有这个选项。此外,我不需要将组分配给模块。我只需要将一个模块分配给组。 在我看来,在这种情况下我不需要关系表。

你会说什么?还是您有其他方法?

【问题讨论】:

  • 如果值得做,那就值得做好。规范化您的数据库并相应地编写您的 UI。
  • 我会使用关系表,除非一个模块与所有现有组有关系,您只需插入 1 行,如 [moduleID; 'ALL']。这样您就不必处理在groupcolumn 中拆分字符串。
  • 在组表中设置外键“模块”
  • 不要在数据库中添加像“All”或null或类似的东西作为具有语义意义的关系键。而是在您的 UI 中处理您创建新数据以在关联表中插入相关/需要的数据。允许数据库使用引用完整性和易于连接语句比必须执行此类逻辑更好 - 将为您提供最佳性能、最佳可维护性和最佳数据完整性
  • 您的第一个问题是您将 datbase 视为 UI 的事后考虑。 UI 将做什么或不做什么与数据库的正确设计无关。您需要考虑数据库规范化术语来设计表结构,而不是根据您的 UI 将要做什么。

标签: sql


【解决方案1】:

要建立多对多关系,您需要一个关系表。

要使用诸如将逗号分隔的值放在字段中以建立多个关系的解决方案仅在您从单独的查询中从单独的表中获取数据时才有效,当您需要使用它来连接数据库中的数据时,它变得非常复杂非常快。

在关系表中,您可以使用null 值来表示“全部”。在此示例中,模块 1 和 2 仅是组 1 的成员,模块 3 是所有组的成员:

ModuleId GroupId
-------- -------
       1       1
       2       1
       3    null

要使用这样的关系为组获取数据,您可以使用如下查询:

select
    g.GroupName,
    m.ModuleName
from
    Groups g
    inner join GroupModules gm on gm.GroupId is null or gm.GroupId = g.GroupdId
    inner join Modules m on m.ModuleId = gm.ModuleId

另一种选择是照常使用关系表,并在模块上添加一个属性,表明它是所有组的成员。添加新组时,您还将在关系表中为属于所有组的所有模块添加记录。示例(在 T-SQL 中):

create procedure Group_Add
  @GroupName varchar(50)
as

set nocount on

declare @id int

insert into Groups (
  GroupName
) values (
  @GroupName
)

set @id = scope_identity()

insert in GroupModules (
  GroupId,
  ModuleId
)
select
  @id, ModuleId
from
  Modules
where
  IsInAllGroups = 1

【讨论】:

  • NULL 通常表示未知值。将业务逻辑放入 NULL 和这样的连接结构 - 虽然可能 - 可能会产生可维护性问题,并且由于参数嗅探,您的查询执行计划可能会很差。
【解决方案2】:

典型的数据库模式是 3 个表,Module、Group、GroupModule。这就是在数据库设计中正确处理的多对多关系。

如何填充数据是您的 UI 的一个问题。您确实可以有一个下拉列表,其中包含所有单词,供他们在选择与模块关联的组时使用。它甚至可以是默认值。您所做的是编写代码来解释 ALL 为每个组插入一条记录。

现在,如果您要添加组和模块,您还需要一个过程来确保在添加组时,所有应该拥有所有组的人都添加到新组中。就我个人而言,我会在 Module 表上放置一个 IS_ALL 标志以使其更容易。然后您就知道为所有组选择了哪些模块。您需要确保如果有人返回并将模块更改为特定组,而不是更新该字段的所有内容。

【讨论】:

    猜你喜欢
    • 2012-04-20
    • 1970-01-01
    • 2021-11-19
    • 2012-12-19
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 2014-01-31
    • 2012-03-13
    相关资源
    最近更新 更多