让我们创建两个表。首府表包含每个州的首府,它们也是 城市。通常,首府表应该从城市表中继承过来。
CREATE TABLE cities ( name text, population float, altitude int -- (in ft) ); CREATE TABLE capitals ( state char(2) ) INHERITS (cities);
在这种情况下,一行首府从它的父表,城市表中继承所有属性(名字, 人口以及海拔)。name 的类型是 text,它是 PostgreSQL 的本生类型,用于变长 ASCII 字串。population 的类型是float, PostgreSQL 用于双精度浮点数的本生类型。 州首府有一个额外的属性,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" 符号.
有时候你可能想知道某条元组来自哪个表.在每个表里我们都有一个系统属性叫 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
废弃: 以前版本的 PostgreSQL 里,缺省是不访问 子表.我们发现这样是容易出错的而且违背 SQL 标准.在旧语法里面,要访问 子表,你需要附加一个 * 到表名后面.例如
SELECT * from cities*;你仍然可以通过附加*明确声明需要扫描子表, 也可以通过写 "ONLY" 声明明确声明不扫描子表. 不过,从版本 7.1 开始,对那些不带修饰的表名子的缺省行为是 同时扫描它的子表,而以前的缺省是正相反.要获得老的缺省行为, 把配置选项 SQL_Inheritance 关闭,也就是∶
SET SQL_Inheritance TO OFF;或者向你的 postgresql.conf 文件里面加一行.
继承特性的一个局限性是索引(包括唯一约束)和外键约束只施用于 单个表,而不包括它们的继承的子表.因此,在上面的例子里, 声明另外一个表的字段 REFERENCES cities(name) 将允许其它表包含城市名但不含首府名.这个缺陷可能在未来的 某个版本中得到修补.