Chapter 8. 继承

让我们创建两个表.表 capitals 包含各州的首府,同时也是cities表. 自然而然,表 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 的类型是 textPostgres 用于变长ASCII字符串的本机类型. 字段 population 的类型是 floatPostgres 用于双精度浮点数的类型. 表 capitals 多一个字段,state,表明首府所在的州. 在 Postgres 里, 一个表可以从0到多个其他表继承下来,一个查询可以 检索一个表的所有记录,或是检索该表和其所有后代的记录.

注意: 继承实际上是开放的层次关系。 (The inheritance hierarchy is a actually a directed acyclic graph.)

例如,下面查询将找出所有海拔 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 的表.许多我们已经讨论过的命令 -- SELECTUPDATEDELETE -- 支持这个 “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;
   
which returns:
+---------+----------+----------+
|relname  |name      | altitude |
+---------+----------+----------+
|capitals |Las Vegas | 2174     |
+---------+----------+----------+
|cities   |Mariposa  | 1953     |
+---------+----------+----------+
|cities   |Madison   | 845      |
+---------+----------+----------+
   

废弃: 以前版本的 Postgres 里,缺省是不访问 子表.我们发现这样是容易出错的而且违背 SQL.在旧语法里面,要访问 子表,你需要附加一个 "*" 到表名后面.例如

SELECT * from cities*;
你仍然可以通过附加"*" 明确声明需要扫描子表, 也可以通过写 “ONLY” 声明明确声明不扫描子表. 不过,从版本 7.1 开始,对那些不带修饰的表名子的缺省行为是 同时扫描它的子表,而以前的缺省是正相反.要获得老的缺省行为, 把配置选项 SQL_Inheritance 关闭,也就是∶
SET SQL_Inheritance TO OFF;
或者向你的 postgresql.conf 文件里面加一行.