pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
让我们创建两个表。capitals表包含也是城市的州首府。自然,capitals表应该继承自cities表。
CREATE TABLE cities (
name text,
population float,
altitude int -- (英尺)
);
CREATE TABLE capitals (
state char(2)
) INHERITS (cities);
在这种情况下,一行capitals数据从它的父表cities继承所有属性(name、population和altitude)。州首府有一个额外的属性state,用来表示它所属的州。在PostgreSQL中,一个表可以从零个或多个其他表继承,而对一个表的查询则可以引用一个表的所有行,或者一个表加上它所有后代的所有行。
继承层次实际上是一个有向无环图。
例如,下面的查询将查找所有位于海拔500英尺以上的城市的名称,包括州首府:
SELECT name, altitude
FROM cities
WHERE altitude > 500;
它将返回:
name | altitude -----------+----------- Las Vegas | 2174 Mariposa | 1953 Madison | 845
另一方面,下面的查询将找到所有高度超过 500 尺且不是州首府的城市:
SELECT name, altitude
FROM ONLY cities
WHERE altitude > 500;
name | altitude
-----------+-----------
Las Vegas | 2174
Mariposa | 1953
这里cities之前的“ONLY”指示查询只应作用于cities本身,而不作用于继承层次中位于cities之下的表。很多我们已经讨论过的命令 —— SELECT、UPDATE和DELETE —— 都支持这种“ONLY”记法。
在以前版本的PostgreSQL中,默认行为是不在查询中包含子表。这种做法被发现容易出错,而且也违反了SQL:1999标准。在旧语法下,要得到子表需要在表名后面追加*。例如
SELECT * from cities*;
你仍然可以通过追加*来显式指定扫描子表,也可以通过写“ONLY”来显式指定不扫描子表。但是从7.1版开始,对于不带修饰的表名,默认行为是同时扫描其子表,而在此之前默认是不这样做。要得到旧的默认行为,可以把配置选项SQL_Inheritance设置为off,例如
SET SQL_Inheritance TO OFF;
或者在你的postgresql.conf文件中加入一行。
在某些情况下,我们可能希望知道一个特定行来自于哪个表。每个表中的系统列tableoid可以告诉我们行来自于哪个表:
SELECT c.tableoid, c.name, c.altitude FROM cities c WHERE c.altitude > 500;
将会返回:
tableoid | name | altitude ----------+-----------+----------- 139793 | Las Vegas | 2174 139793 | Mariposa | 1953 139798 | Madison | 845
(如果重新生成这个结果,可能会得到不同的OID数字。)通过与pg_class进行连接可以看到实际的表名:
SELECT p.relname, c.name, c.altitude FROM cities c, pg_class p WHERE c.altitude > 500 AND c.tableoid = p.oid;
将会返回:
relname | name | altitude ----------+-----------+----------- cities | Las Vegas | 2174 cities | Mariposa | 1953 capitals | Madison | 845
一个表可以从超过一个的父表继承,在这种情况下它拥有父表们所定义的列的并集(再加上专门为子表声明的任何列)。
继承特性的一个严重限制是,索引(包括唯一约束)和外键约束只作用于单个表,而不作用于其继承子表。对于外键约束的引用端和被引用端,这一点都成立。因此,沿用上面的示例:
如果我们把cities.name声明为UNIQUE或PRIMARY KEY,这并不能阻止capitals表中出现与cities中城市同名的行。而且这些重复行默认还会出现在针对cities的查询结果中。事实上,默认情况下capitals根本没有唯一约束,因此它可以包含多行同名记录。你当然可以给capitals添加唯一约束,但这仍无法阻止相对于cities的重复。
相似地,如果我们指定cities.name REFERENCES某个其他表,该约束不会自动地传播到capitals。在此种情况下,我们可以变通地在capitals上手工创建一个相同的REFERENCES约束。
如果让另一个表的某列REFERENCES cities(name),那么该表可以包含城市名称,但不能包含首府名称。对于这种情况,并没有什么好的变通办法。
这些不足未来可能会在某个发行版中修复,但在此期间,在决定继承是否适合你的应用时,仍需要非常小心。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。