第 8 章 继承
我们来创建两个表。capitals 表包含各州首府,它们同时也是城市。自然地,capitals 表应当继承自 cities。
CREATE TABLE cities (
name text,
population float,
altitude int -- (in ft)
);
CREATE TABLE capitals (
state char(2)
) INHERITS (cities);
在这种情况下,capitals 的一行从其父表 cities
继承所有属性(name、population 和
altitude)。属性 name 的类型是
text,这是 Postgres 用于变长
ASCII 字符串的原生类型。属性 population 的类型是
float,这是 Postgres 用于双精度浮点数的原生类型。州首府有一个额外的属性 state,表示它所在的州。在
Postgres 中,一个表可以从零个或多个其他表继承,而查询既可以只引用一个表的所有行,也可以引用一个表及其所有后代的所有行。
注意
继承层次实际上是一个有向无环图。
例如,下面的查询找出所有位于海拔 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 | +---------+----------+----------+ |37292 |Las Vegas | 2174 | +---------+----------+----------+ |37280 |Mariposa | 1953 | +---------+----------+----------+ |37280 |Madison | 845 | +---------+----------+----------+
如果与 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 | +---------+----------+----------+ |capitals |Las Vegas | 2174 | +---------+----------+----------+ |cities |Mariposa | 1953 | +---------+----------+----------+ |cities |Madison | 845 | +---------+----------+----------+
已废弃
在以前的 Postgres 版本中,默认不访问子表。这被发现容易出错,也违反 SQL99。在旧语法下,要获得子表,需在表名后追加 "*"。例如
SELECT * from cities*;
仍然可以通过追加 "*" 显式指定扫描子表,也可以通过写
“ONLY” 显式指定不扫描子表。但从 7.1 版开始,不带修饰的表名的默认行为是同时扫描其子表,而以前的默认行为则不是这样。要获得旧的默认行为,可把配置选项
SQL_Inheritance 设为 off,例如
SET SQL_Inheritance TO OFF;
或者在你的 postgresql.conf 文件中加一行。