這裏有一種方法來實現父/子表爲您的應用程序。
首先,超類型表。它包含所有子類型共有的所有列。
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'等於評論的數量。但在某些應用程序中這樣做確實有意義。在有意義的應用程序中,每個子類型都使用一個可更新視圖,而應用程序代碼大部分時間都會使用可更新視圖。
的超類型較爲常見的業務應用/亞型涉及「方」(超類),「組織」和「個人」(亞型,非正式公司和人。地址,如「在上面的例子中的意見」,都涉及到父,因爲所有的亞型(組織和個人)有地址。
事情的關鍵(原諒雙關語)你的解決方案是一個事實,即亞型表的PK也是FK到父表。 – 2011-02-12 10:50:13