Skip to content

继承

PostgreSQL中的表继承概念

继承是PostgreSQL提供的面向对象数据库特性之一,为数据库设计带来了全新的可能性。通过继承,我们可以创建表之间的父子关系,子表会自动获得父表中定义的所有列。

核心概念

PostgreSQL中的继承允许子表包含父表的所有列,同时可以添加自己独有的列。这种机制极大地增强了数据库设计的灵活性。

为什么需要表继承?

让我们通过一个实际案例来理解继承的作用。假设我们需要设计一个存储城市数据的数据库,其中包含普通城市和州首府。

NOTE

由于州首府也是城市的一种,它们共享许多相同的属性,但首府还有一些特殊属性(如所属州)。

传统解决方案

不使用继承时,我们可能会设计两个独立的表,然后创建视图来合并数据:

sql
-- 首府表
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;

WARNING

这种方法在查询时工作良好,但当需要更新数据时会变得非常麻烦,尤其是需要更新多行数据时。

使用继承的解决方案

PostgreSQL的表继承功能提供了更优雅的解决方案:

sql
-- 创建父表:所有城市共有的属性
CREATE TABLE cities (
  name       text,
  population real,
  elevation  int     -- (单位:英尺)
);

-- 创建子表:首府特有的属性
CREATE TABLE capitals (
  state      char(2) UNIQUE NOT NULL
) INHERITS (cities);

继承的优势

使用INHERITS关键字,capitals表自动继承了cities表的所有列(name、population和elevation),同时添加了自己特有的state列。

继承关系可视化

下面使用图表展示这种继承关系:

查询继承表

当我们查询父表时,PostgreSQL默认会包含子表中的数据。这为数据检索提供了极大的便利。

包含所有数据的查询

下面的查询会查找所有海拔超过500英尺的城市(包括首府):

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

查询结果:

nameelevation
Las Vegas2174
Mariposa1953
Madison845

使用ONLY关键字限制查询范围

如果我们只想查询父表而不包含子表的数据,可以使用ONLY关键字:

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

查询结果:

nameelevation
Las Vegas2174
Mariposa1953

ONLY关键字

ONLY关键字告诉PostgreSQL只查询指定的表,而不包含其继承层次结构中的子表。

支持ONLY关键字的命令

PostgreSQL中许多常用命令都支持ONLY语法,包括:

  • SELECT
  • UPDATE
  • DELETE

IMPORTANT

使用这些命令时添加ONLY关键字,可以限制操作仅应用于指定表,而不影响其子表。

继承的实际应用场景

数据分区

表继承常用于实现表分区。例如,可以为不同时间段的数据创建子表,所有子表共享相同的结构,但各自包含特定时间段的数据。

sql
CREATE TABLE measurements (
    city_id     int not null,
    logdate     date not null,
    temperature int,
    humidity    int
);

CREATE TABLE measurements_y2022m01 () INHERITS (measurements);
CREATE TABLE measurements_y2022m02 () INHERITS (measurements);

细化数据模型

当某些记录需要额外属性时,可以使用继承来细化数据模型,而不必修改基本表结构。

继承的限制与注意事项

CAUTION

  • 继承不会自动传播约束和索引。需要单独为子表创建约束和索引。
  • 表继承不会自动创建外键关系。
  • 删除父表中的行不会级联删除子表中的行。

总结

PostgreSQL的表继承提供了一种优雅的方式来组织具有共同属性但又有独特特征的数据。通过继承,我们可以:

  1. 减少数据冗余
  2. 简化数据维护
  3. 提高查询灵活性
  4. 实现更优雅的数据模型

这种面向对象的特性使PostgreSQL在处理复杂数据关系时比传统关系型数据库更加灵活强大。