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