Appearance
继承
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;
查询结果:
name | elevation |
---|---|
Las Vegas | 2174 |
Mariposa | 1953 |
Madison | 845 |
使用ONLY关键字限制查询范围
如果我们只想查询父表而不包含子表的数据,可以使用ONLY
关键字:
sql
SELECT name, elevation
FROM ONLY cities
WHERE elevation > 500;
查询结果:
name | elevation |
---|---|
Las Vegas | 2174 |
Mariposa | 1953 |
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的表继承提供了一种优雅的方式来组织具有共同属性但又有独特特征的数据。通过继承,我们可以:
- 减少数据冗余
- 简化数据维护
- 提高查询灵活性
- 实现更优雅的数据模型
这种面向对象的特性使PostgreSQL在处理复杂数据关系时比传统关系型数据库更加灵活强大。