PostgreSQL 10.1 手册_部分 II. SQL 语言_第 5 章 数据定义_5.9. 继承

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: 5.9. 继承 5.9.1. 警告 PostgreSQL实现了表继承,这对数据库设计者来说是一种有用的工具(SQL:1999及其后的版本定义了一种类型继承特性,但和这里介绍的继承有很大的不同)。

5.9. 继承

PostgreSQL实现了表继承,这对数据库设计者来说是一种有用的工具(SQL:1999及其后的版本定义了一种类型继承特性,但和这里介绍的继承有很大的不同)。

让我们从一个例子开始:假设我们要为城市建立一个数据模型。每一个州有很多城市,但是只有一个首府。我们希望能够快速地检索任何特定州的首府城市。这可以通过创建两个表来实现:一个用于州首府,另一个用于不是首府的城市。然而,当我们想要查看一个城市的数据(不管它是不是一个首府)时会发生什么?继承特性将有助于解决这个问题。我们可以将capitals表定义为继承自cities表:

CREATE TABLE cities (
    name            text,
    population      float,
    altitude        int     -- in feet
);

CREATE TABLE capitals (
    state           char(2)
) INHERITS (cities);

在这种情况下,capitals继承了它的父表cities的所有列。州首府还有一个额外的列state用来表示它所属的州。

PostgreSQL中,一个表可以从0个或者多个其他表继承,而对一个表的查询则可以引用一个表的所有行或者该表的所有行加上它所有的后代表。默认情况是后一种行为。例如,下面的查询将查找所有海拔高于500尺的城市的名称,包括州首府:

SELECT name, altitude
    FROM cities
    WHERE altitude > 500;

对于来自PostgreSQL教程(见第 2.1 节)的例子数据,它将返回:

   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

这里的ONLY关键词指示查询只被应用于cities上,而其他在继承层次中位于cities之下的其他表都不会被该查询涉及。很多我们已经讨论过的命令(如SELECTUPDATEDELETE)都支持ONLY关键词。

我们也可以在表名后写上一个*来显式地将后代表包括在查询范围内:

SELECT name, altitude
    FROM cities*
    WHERE altitude > 500;

*并不是必须的,因为这种行为总是默认的。 但是,仍支持此语法以与更改默认值的旧版本兼容。

在某些情况下,我们可能希望知道一个特定行来自于哪个表。每个表中的系统列tableoid可以告诉我们行来自于哪个表:

SELECT c.tableoid, c.name, c.altitude
FROM cities c
WHERE c.altitude > 500;

将会返回:

 tableoid |   name    | altitude
----------+-----------+----------
   139793 | Las Vegas |     2174
   139793 | Mariposa  |     1953
   139798 | Madison   |      845

(如果重新生成这个结果,可能会得到不同的OID数字。)通过与pg_class进行连接可以看到实际的表名:

SELECT p.relname, c.name, c.altitude
FROM cities c, pg_class p
WHERE c.altitude > 500 AND c.tableoid = p.oid;

将会返回:

 relname  |   name    | altitude
----------+-----------+----------
 cities   | Las Vegas |     2174
 cities   | Mariposa  |     1953
 capitals | Madison   |      845

另一种得到同样效果的方法是使用regclass别名类型, 它将象征性地打印出表的 OID:

SELECT c.tableoid::regclass, c.name, c.altitude
FROM cities c
WHERE c.altitude > 500;

继承不会自动地将来自INSERTCOPY命令的数据传播到继承层次中的其他表中。在我们的例子中,下面的INSERT语句将会失败:

INSERT INTO cities (name, population, altitude, state)
VALUES ('Albany', NULL, NULL, 'NY');

我们也许希望数据能被以某种方式被引入到capitals表中,但是这不会发生:INSERT总是向指定的表中插入。在某些情况下,可以通过使用一个规则(见第 40 章)来将插入动作重定向。但是这对上面的情况并没有帮助,因为cities表根本就不包含state列,因而这个命令将在触发规则之前就被拒绝。

父表上的所有检查约束和非空约束都将自动被它的后代所继承, 除非使用 NO INHERIT子句明确指定。其他类型的约束(唯一、主键和外键约束)则不会被继承。

一个表可以从超过一个的父表继承,在这种情况下它拥有父表们所定义的列的并集。任何定义在子表上的列也会被加入到其中。如果在这个集合中出现重名列,那么这些列将被合并,这样在子表中只会有一个这样的列。重名列能被合并的前提是这些列必须具有相同的数据类型,否则会导致错误。 以类似的方式合并可继承检查约束和非空约束。因此,例如, 如果其来自的列定义中的任何一个被标记为非空,则合并列将被标记为非空。 如果检查约束具有相同的名称,则检查约束将被合并,并且如果条件不同,合并将失败。

表继承通常是在子表被创建时建立,使用CREATE TABLE语句的INHERITS子句。一个已经被创建的表也可以另外一种方式增加一个新的父亲关系,使用ALTER TABLEINHERIT变体。要这样做,新的子表必须已经包括和父表相同名称和数据类型的列。子表还必须包括和父表相同的检查约束和检查表达式。相似地,一个继承链接也可以使用ALTER TABLE的 NO INHERIT变体从一个子表中移除。动态增加和移除继承链接可以用于实现表划分(见第 5.10 节)。

一种创建一个未来将被用做子女的新表的方法是在CREATE TABLE中使用LIKE子句。这将创建一个和源表具有相同列的新表。如果源表上定义有任何CHECK约束,LIKEINCLUDING CONSTRAINTS选项可以用来让新的子表也包含和父表相同的约束。

当有任何一个子表存在时,父表不能被删除。当子表的列或者检查约束继承于父表时,它们也不能被删除或修改。如果希望移除一个表和它的所有后代,一种简单的方法是使用CASCADE选项删除父表(见第 5.13 节)。

ALTER TABLE将会把列的数据定义或检查约束上的任何变化沿着继承层次向下传播。同样,删除被其他表依赖的列只能使用CASCADE选项。ALTER TABLE对于重名列的合并和拒绝遵循与CREATE TABLE同样的规则。

继承的查询只对父表执行访问权限检查。因此,例如,在cities 表上授予UPDATE权限意味着也更新capitals 表中的行的权限,当它们通过cities访问时。 这说明了这些数据(也)在父表中。但是,如果没有额外的授权, 不能直接更新capitals表。类似的,在继承查询期间, 父表的行安全策略(请参阅第 5.7 节) 将应用到来自子表的行。子表的策略(如果有的话)仅在查询中显式指定该表时应用; 在这种情况下,任何附属于其父母的策略都将被忽略。

外部表(见第 5.11 节)也可以是继承层次 中的一部分,即可以作为父表也可以作为子表,就像常规表一样。如果 一个外部表是继承层次的一部分,那么任何不被该外部表支持的操作也 不被整个层次所支持。

5.9.1. 警告

注意并非所有的SQL命令都能工作在继承层次上。用于数据查询、数据修改或模式修改(例如SELECTUPDATEDELETE、大部分ALTER TABLE的变体,但INSERTALTER TABLE ... RENAME不在此列)的命令会默认将子表包含在内并且支持ONLY记号来排除子表。负责数据库维护和调整的命令(如REINDEXVACUUM)只工作在独立的、物理的表上并且不支持在继承层次上的递归。每个命令相应的行为请参见它们的参考页(SQL 命令)。

继承特性的一个严肃的限制是索引(包括唯一约束)和外键约束值应用在单个表上而非它们的继承子女。在外键约束的引用端和被引用端都是这样。因此,按照上面的例子:

  • 如果我们声明cities.nameUNIQUE或者PRIMARY KEY,这将不会阻止capitals表中拥有和cities中城市同名的行。而且这些重复的行将会默认显示在cities的查询中。事实上,capitals在默认情况下是根本不能拥有唯一约束的,并且因此能够包含多个同名的行。我们可以为capitals增加一个唯一约束,但这无法阻止相对于cities的重复。

  • 相似地,如果我们指定cities.name REFERENCES某个其他表,该约束不会自动地传播到capitals。在此种情况下,我们可以变通地在capitals上手工创建一个相同的REFERENCES约束。

  • 指定另一个表的列REFERENCES cities(name)将允许其他表包含城市名称,但不会包含首府名称。这对于这个例子不是一个好的变通方案。

这些不足可能还将存在于某些未来的发布中,但是同时在决定继承是否对我们的应用有用时需要相当小心。

本文转自PostgreSQL中文社区,原文链接:5.9. 继承

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
1月前
|
存储 关系型数据库 分布式数据库
PolarDB常见问题之PolarDB冷存数据到OSS之后恢复失败如何解决
PolarDB是阿里云推出的下一代关系型数据库,具有高性能、高可用性和弹性伸缩能力,适用于大规模数据处理场景。本汇总囊括了PolarDB使用中用户可能遭遇的一系列常见问题及解答,旨在为数据库管理员和开发者提供全面的问题指导,确保数据库平稳运行和优化使用体验。
|
1月前
|
SQL 关系型数据库 分布式数据库
在PolarDB中,行数评估是通过对表的统计数据、基数估计以及算子代价模型来进行估算的。
【2月更文挑战第14天】在PolarDB中,行数评估是通过对表的统计数据、基数估计以及算子代价模型来进行估算的。
84 1
|
4月前
|
存储 SQL 关系型数据库
PolarDB这个sql行存和列存性能差别好大 ,为什么?
PolarDB这个sql行存和列存性能差别好大 ,为什么?
33 0
|
8天前
|
SQL 关系型数据库 MySQL
关系型数据库插入数据的语句
使用SQL的`INSERT INTO`语句向关系型数据库的`students`表插入数据。例如,插入一个`id`为1,`name`为'张三',`age`为20的记录:`INSERT INTO students (id, name, age) VALUES (1, '张三', 20)。如果`id`自增,则可简化为`INSERT INTO students (name, age) VALUES ('张三', 20)`。
10 2
|
8天前
|
SQL 存储 Oracle
关系型数据库查询数据的语句
本文介绍了关系型数据库中的基本SQL查询语句,包括选择所有或特定列、带条件查询、排序、分组、过滤分组、表连接、限制记录数及子查询。SQL还支持窗口函数、存储过程等高级功能,是高效管理数据库的关键。建议深入学习SQL及相应数据库系统文档。
9 2
|
14天前
|
人工智能 Cloud Native 算法
数据之势丨AI时代,云原生数据库的最新发展趋势与进展
AI与云数据库的深度结合是数据库发展的必然趋势,基于AI能力的加持,云数据库未来可以实现更快速的查询和决策,帮助企业更好地利用海量数据进行业务创新和决策优化。
数据之势丨AI时代,云原生数据库的最新发展趋势与进展
|
1月前
|
关系型数据库 MySQL OLAP
PolarDB +AnalyticDB Zero-ETL :免费同步数据到ADB,享受数据流通新体验
Zero-ETL是阿里云瑶池数据库提供的服务,旨在简化传统ETL流程的复杂性和成本,提高数据实时性。降低数据同步成本,允许用户快速在AnalyticDB中对PolarDB数据进行分析,降低了30%的数据接入成本,提升了60%的建仓效率。 Zero-ETL特性包括免费的PolarDB MySQL联邦分析和PolarDB-X元数据自动同步,提供一体化的事务处理和数据分析,并能整合多个数据源。用户只需简单配置即可实现数据同步和实时分析。
|
1月前
|
SQL 关系型数据库 分布式数据库
在PolarDB中,如果慢SQL导致了CPU升高,进而又产生了更多的慢SQL
【2月更文挑战第22天】在PolarDB中,如果慢SQL导致了CPU升高,进而又产生了更多的慢SQL
13 1
|
2月前
|
关系型数据库 分布式数据库 PolarDB
电子书阅读分享《PolarDB开发者大会:PolarDB在线数据实时分析加速》
电子书阅读分享《PolarDB开发者大会:PolarDB在线数据实时分析加速》
85 3
|
2月前
|
关系型数据库 分布式数据库 PolarDB
电子书阅读分享《PolarDB开发者大会:PolarDB在线数据实时分析加速》
电子书阅读分享《PolarDB开发者大会:PolarDB在线数据实时分析加速》
76 1