2011-02-11 137 views
21

我設計一個數據庫的網站,將有至少4種不同的對象類型來表示(文章,博客文章,照片,故事),每個都有不同足夠的數據需求來保證他們自己的表格。我們希望用戶能夠發表任何這些類型的評論。評論的數據要求很簡單,並且與評論所關注的事物的類型無關(即僅僅是評論機構和作者的電子郵件)。數據庫設計 - 文章,博客文章,照片,故事

我想避免冗餘創建和管理4個以上的獨立表格的評論,所以我想能夠在一張表中保存所有評論,可能指定通過2列的關係:一個指定父實體和一個父行ID。

,但我不明白怎麼回事,那麼,我將實現外鍵,因爲外鍵建立2,只有2個表之間的關係(是嗎?)。

因此,所有考慮到這一點,這將是最好的方法?

回答

34

這裏有一種方法來實現父/子表爲您的應用程序。

首先,超類型表。它包含所有子類型共有的所有列。

CREATE TABLE publications (
    pub_id INTEGER NOT NULL PRIMARY KEY, 
    pub_type CHAR(1) CHECK (pub_type IN ('A', 'B', 'P', 'S')), 
    pub_url VARCHAR(64) NOT NULL UNIQUE, 
    CONSTRAINT publications_superkey UNIQUE (pub_id, pub_type) 
); 

接下來,幾個子類型表。

CREATE TABLE articles (
    pub_id INTEGER NOT NULL, 
    pub_type CHAR(1) DEFAULT 'A' CHECK (pub_type = 'A'), 
    placeholder CHAR(1) NOT NULL, -- placeholder for other attributes of articles 
    PRIMARY KEY (pub_id, pub_type), 
    FOREIGN KEY (pub_id, pub_type) REFERENCES publications (pub_id, pub_type) 
); 

CREATE TABLE stories (
    pub_id INTEGER NOT NULL, 
    pub_type CHAR(1) DEFAULT 'S' CHECK (pub_type = 'S'), 
    placeholder CHAR(1) NOT NULL, -- placeholder for other attributes of stories 
    PRIMARY KEY (pub_id, pub_type), 
    FOREIGN KEY (pub_id, pub_type) REFERENCES publications (pub_id, pub_type) 
); 

這些子類型表中的CHECK()和FOREIGN KEY約束可以防止行引用超類型中錯誤的行。它有效地將子類型中的pub_id值分區,確保任何給定的pub_id都可以出現在一個子類型表中。這就是爲什麼您需要在一對列{publication.pub_id,publications.pub_type}上使用PRIMARY KEY或NOT NULL UNIQUE約束。

徵求意見的表格很簡單。鑑於它是所有子類型具有相同的結構,您可以引用超類型。

CREATE TABLE comments (
    pub_id INTEGER NOT NULL REFERENCES publications (pub_id), 
    comment_timestamp TIMESTAMP NOT NULL DEFAULT now(), 
    commenter_email VARCHAR(10) NOT NULL, -- Only allow people who have 
             -- really short email addresses 
    comment_text VARCHAR(30) NOT NULL, -- Keep 'em short! 
    PRIMARY KEY (pub_id, comment_timestamp, commenter_email) 
); 

添加數據的一點點。

INSERT INTO publications VALUES 
(1,'A', 'url 1 goes here'), 
(2,'A', 'url 2 goes here'), 
(3,'S', 'url 3 goes here'); 

INSERT INTO articles VALUES 
(1,'A', 'A'), 
(2,'A', 'B'); 

INSERT INTO stories VALUES 
(3,'S', 'A'); 

INSERT INTO comments VALUES 
(1, now(), '[email protected]','You''re stupid'), 
(1, now(), '[email protected]', 'You''re stupid, too!'); 

現在你可以創建一個視圖來顯示所有文章和解決的加入。你會爲每個子類型都做同樣的事情。

CREATE VIEW articles_all AS 
SELECT P.*, A.placeholder 
FROM publications P 
INNER JOIN articles A ON (A.pub_id = P.pub_id) 

您可能更喜歡像「published_articles」而不是「articles_all」這樣的名稱。

要選擇一篇文章及其所有評論,您可以只需左加入這兩張表。 (但是見下文,爲什麼你可能不會做。)

SELECT A.*, C.* 
FROM articles_all A 
LEFT JOIN comments C ON (A.pub_id = C.pub_id) 
WHERE A.pub_id = 1; 

你可能不是真的這樣做了一個網絡接口,因爲DBMS將不得不返回的文章,其中的「N」副本'n'等於評論的數量。但在某些應用程序中這樣做確實有意義。在有意義的應用程序中,每個子類型都使用一個可更新視圖,而應用程序代碼大部分時間都會使用可更新視圖。


的超類型較爲常見的業務應用/亞型涉及「方」(超類),「組織」和「個人」(亞型,非正式公司。地址,如「在上面的例子中的意見」,都涉及到父,因爲所有的亞型(組織和個人)有地址。

+0

事情的關鍵(原諒雙關語)你的解決方案是一個事實,即亞型表的PK也是FK到父表。 – 2011-02-12 10:50:13

1

在我看來你最好有您的意見4+獨立的表。或者你可以加入表格。所有評論的一張表...例如:博客表,評論表,blog_comment表。這將允許你有你的外鍵。

Blog 
-------- 
Blog_id 
{other fields} 

Blog_Comment 
-------------- 
Blog_id 
Comment_id 


Comment 
------------ 
Comment_id 
{other fields} 
+1

這是設計,我會推薦。最後一種可能性(以及您是否需要這樣的東西,這將取決於你的設計)將是在評論表或博客/視頻/ Etx表中的每個條目中添加一個用戶ID,例如一個可以檢索特定用戶的所有評論(同樣,如果這符合您的設計要求,並針對特定設計要求進行一些可能的調整。 。 。 )。 USerID最終可能需要一些想法。 – XIVSolutions 2011-02-12 16:56:10

4

可以使用超強型/亞型DB設計,避免了這個問題。爲圖像,視頻,筆記創建超級類型,然後鏈接到超級類型。保留超級類型表中的所有常用列。

這裏有幾個環節幾個類似的問題/解答與型號:

+2

您的意思是創建圖像,視頻筆記而不是超類型的子類型? – Pixelated 2014-09-24 12:47:53