2015-04-12 102 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