2015-07-20 40 views
0

我是一個SQL和數據建模的初學者。我正在通過Zed Shaw的tuogial SQL the hard way。除了完成練習之外,我還試圖自己弄清楚一些事情。在教程中,我被要求創建一個寵物表。我想將寵物連接到fur_color表以跟蹤寵物毛皮的顏色。如何建模一對多的關係,這是一種有條件的

我的問題是,並非所有的寵物(如鳥類)都有毛皮。我只想爲皮草寵物保存毛皮。在我看來,有一些潛在的條件(寵物有毛皮)。

我的解決方案到目前爲止,基於關係是一對多關係的假設(一個寵物可以有一個顏色,一個顏色可以有很多寵物):我創建了一個新的表fur_colour,屬性爲id,id_pet和顏色。我想知道這是否正確,因爲每次記錄都會存儲顏色。

CREATE TABLE pet (
    id INTEGER PRIMARY KEY, 
    name TEXT, 
    breed TEXT, 
    dead INTEGER 
); 
CREATE TABLE fur_colour (
    id INTEGER PRIMARY KEY, 
    pet_id INTEGER, 
    colour TEXT 
); 
INSERT INTO pet (id, name, breed) 
    VALUES (1,"Santa's Little Helper", 'dog'), 
      (2,'Snowball II', 'cat'), 
      (3,'Canary M. Burs', 'bird'); 
INSERT INTO fur_colour (id, pet_id, colour) 
    VALUES (1, 1, 'brown'), 
      (2, 2, 'black'); 
SELECT pet.name, fur_colour.colour FROM pet, fur_colour WHERE 
    pet.id = fur_colour.pet_id; 

另一種解決方案是要創造一個所有可能的顏色都存儲在表的顏色,並與表fur_colour,在這裏我只是存放可以獲得同樣的效果和pet_id連接毛皮和顏色。但到目前爲止,我瞭解到這個解決方案是模擬多對多關係。

CREATE TABLE pet (
id INTEGER PRIMARY KEY, 
name TEXT, 
breed TEXT 
); 
CREATE TABLE fur_colours (
    id INTEGER PRIMARY KEY, 
    colour TEXT 
); 

CREATE TABLE pet_colour (
    id_pet INTEGER, 
    id_colour INTEGER 
); 

INSERT INTO pet (id, name, breed) 
    VALUES (1,"Santa's Little Helper", 'dog'), 
      (2,'Snowball II', 'cat'), 
      (3,'Canary M. Burs', 'bird'); 
INSERT INTO fur_colours (id, colour) 
    VALUES (1, 'grey'), 
      (2, 'brown'), 
      (3, 'white'), 
      (4, 'black'); 

INSERT INTO pet_colour (id_pet, id_colour) 
    VALUES (1, 2), 
      (2, 4); 

SELECT pet.name, fur_colours.colour FROM pet, fur_colours, pet_colour WHERE 
    pet.id = pet_colour.id_pet AND 
    fur_colours.id = pet_colour.id_colour; 

有沒有更好的方法來模擬這種情況?

回答

1

您的第一個解決方案使用英文名稱表示顏色。名稱並不能爲顏色提供很好的標識符 - 它們需要所有命名,可以用各種方式編寫(灰色vs灰色vs灰色vs灰色等等),假定首選語言,並且不是有效的表示。但是,如果您有固定的值列表並設置了正確的檢查限制,則此解決方案可以正常工作。

你的第二個解決方案通過代理號代表顏色。如果您的可接受顏色列表有限,這可能會有效。代理ID比名稱更穩定,並且具有有效顏色表使維護更容易(添加/移除顏色需要操作數據而不是模式)。同樣,確保設置正確的約束以確保有效的數據 - 對名稱的唯一約束,以及用於防止無效寵物顏色的外鍵約束。

對於更多種顏色,您可以將它們表示爲給定色彩空間中的數字。例如,一個32位整數可以表示RGB值:黑色= 0,紅色= 16711680,黃色= 16776960,白色= 16777215。這些很容易從/轉換爲十六進制。如果你想命名顏色,那麼你可以使用像你的fur_colours這樣的表格,但是使用RGB值作爲標識符而不是代理ID。

一般來說,爲每個實體找到一個好的標識符是數據庫設計隱藏的技術之一。一種尺碼不適合所有。自然鍵非常有價值,應該包含在設計中,即使它們不用於主鍵(但使用它們通常會使數據庫更易於使用)。有時鍵是複合的。代理ID常常是必要的。人們可以寫一本關於身份和表徵的書。

現在,您的表設計爲fur_colour/pet_colour有一個問題 - 既不強制關係的基數!如果您將pet_id設置爲主鍵(並在fur_colour的情況下放置代理ID),則會強制要求寵物只有一種顏色。這是pet_id的主要/唯一約束,它使它成爲一對多(或缺少它使其成爲多對多),而不是您的顏色是通過名稱還是代理ID來表示的。