2015-04-12 103 views
0

我想不出这个标题,所以甚至不知道从哪里开始研究自己。 我必须建立一个数据库,其中有一张CD/DVD表格,但其中的娱乐类型需要元数据/信息方面的不同属性,例如音乐CD包含艺术家,出版商,制作人,CDNo。尽管一段软件可能有相似之处,但有一些音乐不会有,并且可能与电影和游戏相同。因此,我不确定E-R图如何工作,到目前为止,我决定:数据库结构/设计

正在物品表或库存表中的CD/DVD尚未确定名称。

tbl_items - > ITEM_ID, item_format(DVD或CD,也许axpand蓝光或HD-DVD), item_entertainment_type(音乐,电影等)< ---也许在另一个不确定。 元数据表的外键,当元数据已经存在时,这使得新CD/DVD的发送时,我只需输入一个新的项目,因此它是元数据和项目之间的一对多(项目>元) 。

我认为的问题是,它是不好的做法有空外键字段,只要选择哪个添加关系,所以musicMeta_id INT NULL, FOREIGN KEY musicMetaID REFERENCES tbl_musicMeta(musicMeta_id) 像每个类型?或者以某种方式合并它们,或者数据库有一个技巧。

我正在使用MySQL和php。

谢谢!

回答

2

有没有一般规则或最佳做法的外键不应该为空。很多时候,一个实体不与另一个实体有关系是非常合理的。例如,您可能有一张您正在追踪的艺术家的表格,但此刻,您没有这些艺术家记录的CD。对于可以是音乐/音频或软件的媒体(CD,DVD,BluRay),您可以拥有一个共同信息表,然后是两个外键,每个扩展表一个(AudioData和SoftwareData ),但必须是NULL。这提出了一种称为除了别的之外的独占弧的情况。 这个通常被认为是有问题的。

想象一个超类和两个派生类,如Java或C++的OO语言。表示,在一个关系模式的一种方法是:

create table Media(
    ID  int not null, -- identity, auto_generated, generated always as identity... 
    Type char(1) not null, 
    Format char(1) not null, 
    ... <other common data>, 
    constraint PK_Media primary key(ID), 
    constraint FK_Media_Type foreign key(Type) 
     references MediaTypes(ID), -- A-A/V, S-Software, G-Game 
    constraint FK_Media_Format foreign key(Format) 
     references MediaFormats(ID) -- C-CD, D-DVD, B-BluRay, etc. 
); 
create unique index UQ_Media_ID_Type(ID, Type) on Media; 
create table AVData(-- For music and video 
    ID  int not null, 
    Type  char(1) not null, 
    ... <audio-only data>, 
    constraint PK_AVData primary key(ID), 
    constraint CK_AVData_Type check(Type = 'A', 
    constraint FK_AVData_Media foreign key(ID, Type) 
     references Media(ID, Type) 
); 
create table SWData(-- For software, data 
    ID  int not null, 
    Type  char(1) not null, 
    ... <software-only data>, 
    constraint PK_SWData primary key(ID), 
    constraint CK_SWData_Type check(Type = 'S', 
    constraint FK_SWData_Media foreign key(ID, Type) 
     references Media(ID, Type) 
); 
create table GameData(-- For games 
    ID  int not null, 
    Type  char(1) not null, 
    ... <game-only data>, 
    constraint PK_GameData primary key(ID), 
    constraint CK_GameData_Type check(Type = 'G', 
    constraint FK_GameData_Media foreign key(ID, Type) 
     references Media(ID, Type) 
); 

现在,如果你正在寻找一个电影,你搜索AVData表,然后与媒体表连接为其余的信息等软件或游戏。如果您有一个ID值,但不知道它是什么类型,请搜索媒体表格,Type值会告诉您要连接三个(或更多)数据表中的哪一个。关键是FK是指的泛型表,而不是它。

当然,电影或游戏或软件可以在多种媒体类型上发布,因此您可以在Media表和各个数据表之间具有交集表。 Otoh,那些通常贴有不同的SKU标签,因此您可能还想将它们作为不同的项目对待。

正如您所期望的那样,代码可能会变得相当复杂,但不是太糟糕。Otoh,我们的设计目标不是简单的代码,而是数据的完整性。这使得不可能将游戏数据与电影项目混合。并且你摆脱了只有一个必须有一个值而其他必须为空的一组字段。

+0

MySQL不强制执行CHECK约束。 –

+0

然后使用触发器。 – TommCatt

+0

非常感谢,由于截止日期的原因,我不得不放弃一个愚蠢的解决方案,但这对未来将有所帮助。 –

-1

我的意见:摆脱FOREIGN KEYs;只要确保你有合适的INDEXes