Kingbase-数据定义7-继承

本文介绍了KingbaseES中的表继承功能,如何通过继承设计数据库模型,以及如何处理查询、插入和约束继承。重点讲解了如何使用INHERITS和ONLY关键字,以及继承对索引和外键约束的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

10 继承
KingbaseES 实现了表继承,这对数据库设计者来说是一种有用的工具( 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 用来
表示它所属的州。
KingbaseES 中,一个表可以从 0 个或者多个其他表继承,而对一个表的查询则可以引用一个表的所有行或
者该表的所有行加上它所有的后代表。默认情况是后一种行为。例如,下面的查询将查找所有海拔高于 500
尺的城市的名称,包括州首府:
SELECT name, altitude
FROM cities
WHERE altitude > 500 ;
对于来自 KingbaseES 教程(见 引言 )的例子数据,它将返回:
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 之下的其他表都
不会被该查询涉及。很多我们已经讨论过的命令(如 SELECT UPDATE DELETE )都支持 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 数字。)通过与 sys_class 进行连接可以看到实际的表
名:
SELECT p . relname, c . name, c . altitude
FROM cities c, sys_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 ;
继承不会自动地将来自 INSERT COPY 命令的数据传播到继承层次中的其他表中。在我们的例子中,下
面的 INSERT 语句将会失败:
INSERT INTO cities (name, population, altitude, state)
VALUES ( 'Albany' , NULL, NULL, 'NY' );
我们也许希望数据能被以某种方式被引入到 capitals 表中,但是这不会发生: INSERT 总是向指定的表
中插入。在某些情况下,可以通过使用一个规则(见 规则系统 )来将插入动作重定向。但是这对上面的情况
并没有帮助,因为 cities 表根本就不包含 state 列,因而这个命令将在触发规则之前就被拒绝。
父表上的所有检查约束和非空约束都将自动被它的后代所继承,除非显式地指定了 NO INHERIT 子句。其
他类型的约束(唯一、主键和外键约束)则不会被继承。
一个表可以从超过一个的父表继承,在这种情况下它拥有父表们所定义的列的并集。任何定义在子表上的列
也会被加入到其中。如果在这个集合中出现重名列,那么这些列将被“合并”,这样在子表中只会有一个这
样的列。重名列能被合并的前提是这些列必须具有相同的数据类型,否则会导致错误。可继承的检查约束和
非空约束会以类似的方式被合并。例如,如果合并成一个合并列的任一列定义被标记为非空,则该合并列会
被标记为非空。如果检查约束的名称相同,则他们会被合并,但如果它们的条件不同则合并会失败。
表继承通常是在子表被创建时建立,使用 CREATE TABLE 语句的 INHERITS 子句。一个已经被创建的表也
可以另外一种方式增加一个新的父亲关系,使用 ALTER TABLE INHERIT 变体。要这样做,新的子表必须
已经包括和父表相同名称和数据类型的列。子表还必须包括和父表相同的检查约束和检查表达式。相似地,
一个继承链接也可以使用 ALTER TABLE NO INHERIT 变体从一个子表中移除。动态增加和移除继承链
接可以用于实现表划分(见 表分区 )。
一种创建一个未来将被用做子女的新表的方法是在 CREATE TABLE 中使用 LIKE 子句。这将创建一个和
源表具有相同列的新表。如果源表上定义有任何 CHECK 约束, LIKE INCLUDING CONSTRAINTS 选项
可以用来让新的子表也包含和父表相同的约束。
当有任何一个子表存在时,父表不能被删除。当子表的列或者检查约束继承于父表时,它们也不能被删除或
修改。如果希望移除一个表和它的所有后代,一种简单的方法是使用 CASCADE 选项删除父表(见 依赖跟踪
)。
ALTER TABLE 将会把列的数据定义或检查约束上的任何变化沿着继承层次向下传播。同样,删除被其他表
依赖的列只能使用 CASCADE 选项。 ALTER TABLE 对于重名列的合并和拒绝遵循与 CREATE TABLE 同样
的规则。
继承的查询仅在附表上执行访问权限检查。例如,在 cities 表上授予 UPDATE 权限也隐含着通过 cities
访问时在 capitals 表中更新行的权限。这保留了数据(也)在父表中的样子。但是如果没有额外的授权,
则不能直接更新 capitals 表。以类似的方式,父表的行安全性策略(见 行安全性策略 )适用于继承查询
期间来自于子表的行。只有当子表在查询中被明确提到时,其策略(如果有)才会被应用,在那种情况下,
附着在其父表上的任何策略都会被忽略。
外部表(见 外部数据 )也可以是继承层次中的一部分,即可以作为父表也可以作为子表,就像常规表一样。
如果一个外部表是继承层次的一部分,那么任何不被该外部表支持的操作也不被整个层次所支持。
10.1 警告
注意并非所有的 SQL 命令都能工作在继承层次上。用于数据查询、数据修改或模式修改(例如 SELECT
UPDATE DELETE 、大部分 ALTER TABLE 的变体,但 INSERT ALTER TABLE ... RENAME 不在此
列)的命令会默认将子表包含在内并且支持 ONLY 记号来排除子表。负责数据库维护和调整的命令(如
REINDEX VACUUM )只工作在独立的、物理的表上并且不支持在继承层次上的递归。每个命令相应的行为
请参见它们的参考页( SQL 语句参考 )。
继承特性的一个严肃的限制是索引(包括唯一约束)和外键约束值应用在单个表上而非它们的继承子女。在
外键约束的引用端和被引用端都是这样。因此,按照上面的例子:
如果我们声明 cities . name UNIQUE 或者 PRIMARY KEY ,这将不会阻止 capitals 表中拥
有和 cities 中城市同名的行。而且这些重复的行将会默认显示在 cities 的查询中。事实上,
capitals 在默认情况下是根本不能拥有唯一约束的,并且因此能够包含多个同名的行。我们可以为
capitals 增加一个唯一约束,但这无法阻止相对于 cities 的重复。
相似地,如果我们指定 cities . name REFERENCES 某个其他表,该约束不会自动地传播到
capitals 。在此种情况下,我们可以变通地在 capitals 上手工创建一个相同的 REFERENCES
约束。
指定另一个表的列 REFERENCES cities(name) 将允许其他表包含城市名称,但不会包含首府名
称。这对于这个例子不是一个好的变通模式。
一些没有为继承层次结构实现的功能是为声明性分区实现的。在决定使用遗留继承进行分区是否对您的应用
程序有用时,需要相当小心。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值