这里有一种方法来实现父/子表为您的应用程序。
首先,超类型表。它包含所有子类型共有的所有列。
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