PostgreSQL表继承和重载特性

PostgreSQL实现了表继承,这个特性对数据库设计人员来说是一个很有效的工具。SQL99 及以后的标准定义了类型继承特性,和我们在这里描述的很多特性有区别。

让我们从一个例子开始:假设我们试图制作一个城市数据模型。每个州都有许多城市,但是只有一个首府。我们希望能够迅速检索任何州的首府。这个任务可以通过创建两个表来实现,一个是州府表,一个是非州府表。不过,如果我们不管什么城市都想查该怎么办? 继承的特性可以帮助我们解决这个问题。我们定义capitals表,它继承自cities表:

CREATE TABLE cities (
name text,
population float,
altitude int – 英尺
);
CREATE TABLE capitals (
state char(2)
) INHERITS (cities);
在这种情况下,capitals表继承它的父表cities 中的所有属性。州首府有一个额外的state属性显示其所在的州。

在PostgreSQL里,一个表可以从零个或多个其它表中继承属性,而且一个查询既可以引用一个表中的所有行,也可以引用一个表及其所有后代表的行(后面这个是缺省行为)。比如,下面的查询查找所有海拔 500 英尺以上的城市名,包括州首府:

SELECT name, altitude
FROM cities
WHERE altitude > 500;
使用PostgreSQL教程里面的数据,它返回:

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
cities前面的ONLY表明该查询应该只针对cities 而不包括其后代。许多我们已经讨论过的命令(SELECT, UPDATE 和 DELETE)都支持ONLY关键字。

你也可以在表名后面写一个*显示指定包括所有后代表:

SELECT name, altitude
FROM cities*
WHERE altitude > 500;
因为这个行为是默认的,所以写并不是必须的(除非你已经改变了 sql_inheritance里面的配置选项)。然而,写 可以用于强调搜索额外的表。

有时候你可能想知道某个行版本来自哪个表。在每个表里我们都有一个tableoid 系统属性可以告诉你源表是谁:

SELECT c.tableoid, c.name, c.altitude
FROM cities c
WHERE c.altitude > 500;
结果如下(你可能会得到不同的 OID):

tableoid | name | altitude
----------±----------±---------
139793 | Las Vegas | 2174
139793 | Mariposa | 1953
139798 | Madison | 845
通过和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
对于INSERT或COPY,继承并不自动影响其后代表。在我们的例子里,下面的INSERT语句将会失败:

INSERT INTO cities (name, population, altitude, state)
VALUES (‘New York’, NULL, NULL, ‘NY’);
我们可能希望数据被传递到capitals表里面去,但这是不会发生的:INSERT总是插入明确声明的那个表。在某些情况下,我们可以使用规则进行重定向插入。不过它不能对上面的例子有什么帮助,因为cities表并不包含state 字段,因此命令在规则施加之前就会被拒绝掉。

所有父表的检查约束和非空约束都会自动被所有子表继承。不过其它类型的约束(唯一、主键、外键约束)不会被继承。

一个子表可以从多个父表继承,这种情况下它将拥有所有父表字段的总和,并且子表中定义的字段也会加入其中。如果同一个字段名出现在多个父表中,或者同时出现在父表和子表的定义里,那么这些字段就会被"融合",这样在子表里就只有一个这样的字段。要想融合,字段的数据类型必须相同,否则就会抛出一个错误。融合的字段将会拥有其父字段的所有检查约束,并且如果某个父字段存在非空约束,那么融合后的字段也必须是非空的。

表继承通常使用带INHERITS子句的CREATE TABLE语句定义。另外,一个已经用此方法定义的子表可以使用带INHERIT的ALTER TABLE 命令添加一个新父表。注意:该子表必须已经包含新父表的所有字段且类型一致,此外新父表的每个约束的名字及其表达式都必须包含在此子表中。同样,一个继承链可以使用带NO INHERIT的ALTER TABLE命令从子表上删除。允许动态添加和删除继承链对基于继承关系的表分区很有用。

创建一个将要作为子表的新表的便利途径是使用带LIKE子句的 CREATE TABLE命令。它将创建一个与源表字段相同的新表。如果源表中存在约束,那么应该指定LIKE的INCLUDING CONSTRAINTS 选项,因为子表必须包含源表中的CHECK约束。

任何存在子表的父表都不能被删除,同样,子表中任何从父表继承的字段或约束也不能被删除或修改。如果你想删除一个表及其所有后代,最简单的办法是使用CASCADE选项删除父表。

ALTER TABLE会把所有数据定义和检查约束传播到后代里面去。另外,只有在使用CASCADE选项的情况下,才能删除依赖于其他表的字段。 ALTER TABLE在重复字段融合和拒绝方面和CREATE TABLE的规则相同。

请注意表访问权限是如何处理的。访问父表会自动访问在子表中的数据,而不需要更多的访问权限检查。这保留了父表中数据的表现。然而,直接访问子表不会自动允许访问父表,要访问父表需要更进一步的权限被授予。

警告
注意,不是所有的 SQL 命令可以在所有的继承层次上正常工作。数据查询,数据修改,模式修改的命令(比如SELECT,UPDATE,DELETE, ALTER TABLE的大多数变型,但不是INSERT和 ALTER TABLE … RENAME)典型的默认包括子表和支持ONLY符号来排除它们。为数据库维护和调优的命令(例如REINDEX,VACUUM)通常只对个别工作,物理表格不支持递归超过继承层次结构。单独命令各自的行为记录在了它们的参考页中。

继承的一个严重局限性是索引(包括唯一约束)和外键约束只能用于单个表,而不能包括它们的子表(不管对外键约束的引用表还是被引用表都是如此),因此,在上面的例子里:

即使我们声明cities.name为UNIQUE或PRIMARY KEY,也不会阻止capitals表拥有重复名字的cities数据行。并且这些重复的行在查询cities表的时候会显示出来。实际上,缺省时capitals将完全没有唯一约束,因此可能包含带有同名的多个行。你应该给capitals增加唯一约束,但即使这样做也不能避免与cities的重复。

类似的,即使我们声明cities.name 参照(REFERENCES)某些其它的表,这个约束也不会自动传播到capitals表。在这种条件下,你可以通过手工给capitals表增加同样的REFERENCES约束来做到这点。

声明一个其它表的字段为REFERENCES cities(name)将允许其它表包含城市名,但是不包含首府名。这种情况下没有很好的绕开办法。

这些缺点很可能在将来的版本中修补,但同时你也需要考虑一下,继承是否对你的应用真正有用。
转载地址:https://www.cnblogs.com/wolaiye320/p/5588928.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PostgreSQL是以加州大学伯克利分校计算机系开发的POSTGRES,现在已经更名为PostgreSQL. PostgreSQL支持大部分SQL标准并且提供了许多其它现代特性:复杂查询、外键、触发器、视图、事务完整性等。PostgreSQL 是一个免费的对象-关系数据库服务器(数据库管理系统),它在灵活的 BSD-风格许可证下发行。它提供了相对其他开放源代码数据库系统(比如 MySQL 和 Firebird),和专有系统(比如 Oracle、Sybase、IBM 的 DB2 和 Microsoft SQL Server)之外的另一种选择。事实上, PostgreSQL特性覆盖了 SQL-2/SQL-92 和 SQL-3/SQL-99,首先,它包括了可以说是目前世界上最丰富的数据类型的支持,其中有些数据类型可以说连商业数据库都不具备, 比如 IP 类型和几何类型等;其次,PostgreSQL 是全功能的自由软件数据库,很长时间以来,PostgreSQL 是唯一支持事务、子查询、多版本并行控制系统(MVCC)、数据完整性检查等特性的唯一的一种自由软件的数据库管理系统。 Inprise 的 InterBase 以及SAP等厂商将其原先专有软件开放为自由软件之后才打破了这个唯一。最后,PostgreSQL拥有一支非常活跃的开发队伍,而且在许多黑客的努力下,PostgreSQL 的质量日益提高。从技术角度来讲,PostgreSQL 采用的是比较经典的C/S(client/server)结构,也就是一个客户端对应一个服务器端守护进程的模式,这个守护进程分析客户端来的查询请求,生成规划树,进行数据检索并最终把结果格式化输出后返回给客户端。为了便于客户端的程序的编写,由数据库服务器提供了统一的客户端 C 接口。而不同的客户端接口都是源自这个 C 接口,比如ODBC,JDBC,Python,Perl,Tcl,C/C++,ESQL等, 同时也要指出的是,PostgreSQL 对接口的支持也是非常丰富的,几乎支持所有类型的数据库客户端接口。这一点也可以说是 PostgreSQL 一大优点。本课程作为PostgreSQL数据库管理一,主要讲解以下内容: 1.     PostgreSQL 存储过程基本知识2.     PostgreSQL 用户自定义函数3.     PostgreSQL 控制结构4.     PostgreSQL 游标和存储过程5.     PostgreSQL 索引6.     PostgreSQL 视图7.     PostgreSQL 触发器8.     PostgreSQL 角色、备份和还原9.     PostgreSQL 空间管理

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值