在制作表集合时进行Sql正确练习

时间:2014-07-07 11:00:03

标签: mysql sql

我不知道该怎么称呼这篇文章,但这是我的问题:

我有两张桌子:Online_Module& Offline_Module我的程序中使用了这两个表来确定是否必须在线或在现场学习模块。

现在我还有一个名为Academy的表。 Academy由许多模块组成。为此,我想创建以下子表:Academy_has_Module

这就是问题所在。由于Online_ModuleOffline_Module不在同一个表格中,因此Academy_has_Module中的一个值始终为null

以下是一些显示这些表格累积的图片:

Online_offline Academy_has_Module

如您所见,其中一个值始终为null。我想知道,在这种情况下最佳做法是什么?

2 个答案:

答案 0 :(得分:5)

1)创建一个表模块,保存用于在线和离线模块的字段:

id INT,
description
material
status
category

2)然后保留离线/在线模块表(编辑:减去字段 - 除了id字段 - 你现在保留在Module表中),但让它们FK引用新模块表,使用Module表作为中间链接。

修改 现在,不要用很多东西压倒你,但是你自己有几个问题需要Q& A,即: - 模块只能离线/在线吗? - 如果是的话,我想在DB中100%强制执行吗?

因为使用我的解决方案,您可以拥有一个模块,并通过多个离线/在线模块引用它。有办法解决它,但我认为它们会远远超出你的要求,我只是提到它,所以你知道..

至于获取信息(可能不是最好的,但这是我现在的水平,如果有人知道更好,请随时教我一个新的技巧:))。 *注意:丑陋的编码,对于完整的编码风格太累了:D *:

select *, case 
when OffM.Id is null and OnM.Id is null then 'No module!'
when OffM.Id is not null and OnM.Id is not null then 'Too many modules!'
when OffM.Id is null and OnM.Id is not null then 'Online module!'
when OffM.Id is not null and OnM.Id is null then 'Offline module!'
end --probably a different, better way to compare?
  from Academy_has_Module as AHM
  join Module as M
    on Academy.Module = M.Id
left join OfflineModule as OffM
    on OffM.ModuleID = M.Id
left join OnlineModule as OnM
    on OnM.ModuleID = M.Id

但是现在,根据我的理解,如果你在Module表中添加了一个ModuleType,ORM框架(我真的没那么说实话,所以没有第一手经验),可以用它来返回一个对象正确的班级。但这更深入到了项目中使用的整个架构和技术,超出了这个问题的范围,甚至超出了我的实际经验。

<强> EDIT2: 好的,我还想到了另外一件事:将在线/离线模块表结构更改为某种方式是不合理的?例如在线模块: - 可以有一个导师/负责人 - 可以从 - 到日期开放 -offline模块没有名字? - 在线模块的位置将是&#39; Online&#39; 然后将这些表与ModuleType(约束或FK)合并到枚举表中(不确定正确的术语是英语)。也许有点强迫,但(再次,这很大程度上取决于总体要求,我从来没有看到即使在一次迭代中添加一个简单的表,它总是影响某些东西,它在设计中传播)可以让你的生活变得简单。有时候,最好每条记录浪费几个字节的空间,然后试着太可爱了,并且在后面的路上稍微有些位置。

度过愉快的一天

答案 1 :(得分:0)

这是超类/子类设计(如果首选,则为超实体/子实体)。要扩展@ VladislavZalesak的答案,请将公共属性放入超实体表中。但是不要忘记实施正确的数据完整性检查。

create table Module(
    ID          int  not null primary key,
    ModType     char( 1 ) not null,
    Name        varchar( 45 ) not null,
    Description text,
    MaterialID  int,
    StatusID    int,
    CategoryID  int,
    constraint TypeCK check( ModType in( 'O', 'F' ))
);
create unique index ModuleType_UIX on Module( ID, ModType );

现在,如果ID是PK,它必须是唯一的。那么,为什么我们要创建一个ID ModType的唯一索引?所以我们可以将它们作为一个组来引用:

create table OnlineModule(
    ID          int not null primary key,
    ModType     char( 1 ) not null default 'O',
    Price       double,
    Time        varchar( 45 ),
    constraint OnlineTypeCK check( ModType = 'O' ),
    constraint OnlineTypeFK foreign key( ID, ModType )
        references Module( ID, ModType )
);

create table OfflineModule(
    ID          int not null primary key,
    ModType     char( 1 ) not null default 'F',
    StartDate   datetime,
    EndDate     datetime,
    Mentor      varchar( 45 ),
    constraint OfflineTypeCK check( ModType = 'F' ),
    constraint OfflineTypeFK foreign key( ID, ModType )
        references Module( ID, ModType )
);

现在,您的Acadamy_has_Module表只需要一个FK到模块,它可以提供您需要的大部分信息,甚至是离线或在线的信息。

两个子模块都与模块表具有标识关系,而不仅仅是ID,这在技术上是足够的,但也可以通过模块类型实现子/超关系。检查约束使结构得以实施。

您可以创建将模块连接到子模块的视图,以显示每种子模块的所有字段。

它可以扩展,因为你可以添加新的子模块。但是如果你认为可能会这样,你可能想要创建一个submodule_type表,并将ModType Module字段定义为该表的FK。这将消除每次添加新子类型时必须更改Module的检查约束。

当你第一次看它时有点麻烦,但它很灵活,解决了一些前期设计问题。