【问题标题】:Junction Table & Normalization Question连接表和归一化问题
【发布时间】:2011-09-27 11:04:03
【问题描述】:

我很难确定以下设计模式是否可以接受。对于关系模型,我有以下要求(以及其他一些要求):

1) 它必须能够表示应用程序(例如AppAAppBAppC),每个应用程序都有自己的一组属性。

2) 每个应用程序都可以通过不同的渠道进行通信,例如Internet(E-Mail、Twitter、Facebook)、Phone(SMS、MMS 等),因此程序之间存在多对多的关系,并且渠道。

3) 有一组预定义的标识符(地址、电话号码、登录帐户)可以由许多程序共享,因此,程序和标识符之间也是多对多的关系。

4) 相同的标识符可以发送多种类型的消息,程序也可以(同样,多对多),但我需要能够根据每个应用程序限制通信类型标识符的使用.

基本上,我所做的是创建四个表,ProgramChannelIdentCommunicationType 来存储有关每个表的信息,而不是为 (Program, Channel)、@987654331 创建联结表@,等等这只会使设计复杂化,我创建了一个由这四个表的主键组成的单个表,并在 (Program, Channel, Ident, CommunicationType) 上具有唯一约束。现在,此表的每条记录都链接到给定的通信。

当然,这以一种非常简单的方式解决了我的问题,但现在我在质疑自己,如果它违反了规范化原则,这是否完全可以接受。谁能给我意见?

【问题讨论】:

    标签: database-design normalization junction-table


    【解决方案1】:

    基本上,我所做的是创造 四个表,Program,Channel,Ident 和 CommunicationType 来存储 关于这些中的每一个的信息,以及,

    这是个好主意。

    而不是创建联结表 对于(节目,频道),(节目, 标识符),依此类推 只是让设计复杂化,我创造了 由以下组成的单个表 这四个表的主键 对(程序, Channel、Ident、CommunicationType)。

    在设计这样的表格时需要注意一件事。您的结构具有键 {Program, Channel, Ident, CommunicationType},允许 Program 和 Channel、Channel 和 Ident、Program 和 CommunicationType 等的所有可能组合。有时这是个坏主意。

    同一个标识符可以发送多个 消息的类型,因此可以 程序(再次,多对多),但我 需要能够限制使用 通信类型的标识符 每个应用程序的基础。

    这就是让它成为一个坏主意的原因。您似乎在说并非 Ident、Program 和 CommunicationsType 的每个组合都是有效的。

    将有效组合存储在它们自己的表中。使用外键引用来维护数据完整性。

    构建具有键 {Program, Ident, CommunicationsType} 的表。具有键 {Program, Channel, Ident, CommunicationType} 的表可以为其设置外键引用。

    构建尽可能多的表来实现您所知道的所有约束。更多的表意味着数据完整性检查更简单。 (您可能需要比我提到的更多的表。不要假设它们需要有两列;它们可能需要更多。)

    您是否需要一个键控为 {Program, Channel} 的表还不清楚。但如果你这样做了,那么你需要按照这些思路构建表格。 (航空代码。)

    create table pc (
        program_name varchar(10) not null references programs (program_name),
        channel_name varchar(10) not null references channels (channel_name),
        primary key (program_name, channel_name)
    );
    
    create table pict (
        program_name varchar(10) not null,
        channel_name varchar(10) not null,
        comm_type varchar(10) not null references communication_type (comm_type),
        primary key (program_name, channel_name, comm_type),
        foreign key (program_name, channel_name) 
            references pc (program_name, channel_name) 
    );
    
    create table your-table-name (
        program_name varchar(10) not null,
        channel_name varchar(10) not null,
        comm_type varchar(10) not null,
        ident varchar(10) not null,
        primary key (program_name, channel_name, comm_type, ident),
        foreign key (program_name, channel_name, comm_type) 
            references pict (program_name, channel_name, comm_type),
        foreign key (ident) references ident (ident)
    );
    

    根据需要添加其他列。在某些情况下,您可能会发现需要重叠的外键。我认为您在这里不需要它们,但我可能是错的。

    我不确定您所说的“如果它违反了规范化原则”是什么意思。 仅出于这个原因,具有四列主键的表不会违反任何正常形式,尽管它可能出于其他原因。未能实现所有已知的约束通常是,嗯,次优设计,但不是因为它违反了任何正常形式。

    【讨论】:

    • +1。非常感谢您的回答!我想我会遵循这个设计。你是对的,我的意思是不是{Program, Ident, CommunicationType 的每个组合都是有效的。而且我还需要有一个键控为 {Channel, Program} 的表,所以再次感谢您的设计。
    【解决方案2】:

    很抱歉为您提供要求更多信息的答案。我在这一点上的声誉不允许任何 cmets...

    根据解释,我认为选择的设计没有任何问题。

    但是,要真正回答您的问题,了解您选择此设计的原因会很有用。

    毕竟它也可以在没有包含所有键和复合唯一索引的单个表的情况下工作。以这种方式锁定所有组合是相当严格的。

    找到通信后,您仍需要加入一个或多个其他表才能访问构成通信的信息。

    为什么要以这种方式存储每个唯一的通信路径?

    【讨论】:

    • +1。非常感谢您的回答!我的目标是在任何地方都不存储冗余信息,因此我非常依赖表之间的连接。
    【解决方案3】:

    我不会这样做。

    我将在每对(或 n 个元组)表之间创建一个联结表。这最终将允许更简单的查询,并且还允许您在每种情况下独立于其他情况以适当的方式约束行。

    您可能还会发现这些连接点需要额外的属性,例如从一个软件到另一个软件,方向性、有效负载、使用的语言、正在访问的查询点等。

    【讨论】:

    • +1。你是对的,现在我发现这不是一个好主意。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多