PostgreSQL 18 中文参考文档(未翻译部分保留英文)🌐 切换到英文原版 →

3.6. 表继承 #

继承(Inheritance)是面向对象数据库的重要理念之一,它为关系型数据库的模型设计拓展了富有创意的全新可能性。

让我们创建两张表:一张普通城市表 cities 与一张州首府表 capitals。从业务常理来看,首府本身必然也是城市,因此当你查询所有城市时,自然希望首府也能一并隐式返回。采用传统的传统设计,可能会尝试使用视图进行联合:

CREATE TABLE capitals (
  name       text,
  population real,
  elevation  int,    -- 海拔(英尺)
  state      char(2)
);

CREATE TABLE non_capitals (
  name       text,
  population real,
  elevation  int     -- 海拔(英尺)
);

CREATE VIEW cities AS
  SELECT name, population, elevation FROM capitals
    UNION
  SELECT name, population, elevation FROM non_capitals;

对于只读查询这种方式尚能应对,但在涉及对多行数据执行更新时,维护视图的代价将变得十分复杂。

利用继承机制能够以更优雅的方式解决该问题:

CREATE TABLE cities (
  name       text,
  population real,
  elevation  int     -- 海拔(英尺)
);

CREATE TABLE capitals (
  state      char(2) UNIQUE NOT NULL
) INHERITS (cities);

在上述定义中,子表 capitals 的每一行均自动继承其父表 cities 的全部字段定义(name、population 与 elevation)。字段 name 的类型为 text,这是 PostgreSQL 原生支持的变长文本字符串类型。capitals 表在此基础上拓展了特有的 state 字段,用于存储州名称缩写。在 PostgreSQL 中,一张表支持继承自零个或多个父表(支持多重继承)。

例如,以下查询用于检索海拔超过 500 英尺的所有城市(自动包含首府):

SELECT name, elevation
  FROM cities
  WHERE elevation > 500;

返回结果:

   name    | elevation
-----------+-----------
 Las Vegas |      2174
 Mariposa  |      1953
 Madison   |       845
(3 rows)

反之,如果查询只想检索海拔超过 500 英尺的非首府普通城市:

SELECT name, elevation
    FROM ONLY cities
    WHERE elevation > 500;

   name    | elevation
-----------+-----------
 Las Vegas |      2174
 Mariposa  |      1953
(2 rows)

此处的 ONLY 关键字用于显式限定:查询仅扫描本表 cities 本身的物理记录,而不要级联递归扫描继承层级树下方的子表。SELECT、UPDATE 以及 DELETE 等基础命令均支持该 ONLY 语法修饰。

Note

尽管继承机制在很多场景下非常便捷,但它尚未与全局唯一约束或外键完整性深度联动,这在一定程度上限制了其在某些企业级严苛建模场景的应用。详见 Section 5.11。