目录
模式(schema)是数据库中的一个概念,可以将其理解为一个命名空间或目录。不同的模式下可以有相同名称的表、函数等对象且互相不冲突。提出模式的概念是为了便于管理,只要有权限,每个模式(schema)的对象可以互相调用。
在PostgreSQL中,一个数据库包含一个或多个模式,模式中又包含了表、函数及操作符等数据库对象。在 PostgreSQL 中,不能同时访问不同数据库中的对象,当要访问另一个数据库中的表或其他对象时,需要重新连接到这个新的数据库,而模式没有此限制。一个用户在连接到一个数据库后,就可以同时访问这个数据库中多个模式的对象。从这个特性来说,PostgreSQL中模式的概念与MySQL中 Database的概念是等同的。在 MySQL 中可以同时访问多个Database中的对象,就与在PostgreSQL 中可以同时访问多个Schema中的对象是一样的。在Oracle数据库中,一个用户就对应一个schema。大家在以后的学习过程中需要注意在不同的数据库系统(Oracle、MySQL)中Database、模式这些概念的不同。
我们需要使用模式有以下几个主要原因:
(1) 允许多个用户在使用同一个数据库时彼此互不干扰。
(2) 把数据库对象放在不同的模式下,然后组织成逻辑组,让它们更便于管理。
(3) 第三方的应用可以放在不同的模式中,这样就不会和其他对象的名字冲突了。
创建模式的语法如下:
- CREATE SCHEMA schemaname [ AUTHORIZATION username ] [ schema_element [ ... ] ]
-
- CREATE SCHEMA AUTHORIZATION username [ schema_element [ ... ] ]
要创建或者访问模式中的对象,需要先写出一个受修饰的名字,这个名字包含模式名及表名,它们之间用一个“点”分开,如下:
schema_name.table_name
通常情况下,创建和访问表的时候都不用指定模式,实际上这时访问的都是“public”模式。每当我们创建一个新的数据库时,PostgreSQL都会自动创建一个名为“public”的模式。当登录到该数据库时,如果没有特殊的指定,都是以该模式(public)操作各种数据对象的。
使用一个数据库对象时,虽然可以使用它的全称来定位对象,但这样一来,每次都不得不键入schema_name.object_name,这显然很繁琐。对此,PostgreSQL中提供了模式搜索路径,有些类似于Linux中的SPATH环境变量,当我们执行一个Shell 命令时,只有在该命令位于$PATH的目录列表中时,才可以通过命令名直接执行,否则就需要输人它的全路径名。
在PostgreSQL中同样也可通过查找一个搜索路径来判断某个表究竟是哪个模式下,这个路径是一个需要查找的模式列表。在搜索路径里找到的第一个表将被当作选定的表。如果在搜索路径中没有匹配的表,那么就报告一个错误,即使匹配表的名字在数据库其他的模式中存在也如此。
在搜索路径中的第一个模式叫当前模式。除了是搜索的第一个模式之外,它还是在CREATETABLE没有声明模式名时新建表所属于的模式。要显示当前搜索路径,使用下面的命令:
- osdba=# SHOW search_path;
- search_path
- ----------------
- "$user",public
上面显示的是search_path 的默认配置,从这个默认配置可以看到“public”模式总是在搜索路径中。所以一般情况下,若创建的表默认没有指定模式,那都会在“public”模式下。在psql 中使用“\d”命令总是可以把“public”模式下的表显示出来。
在SQL标准里,同一个模式里的对象是不能被不同的用户所拥有的,而且有些数据库系统不允许你创建和它们的所有者不同名的模式,比如Oracle数据库。实际上,在Oracle这类只实现了标准中规定的基本模式的数据库系统里,模式和用户的概念几乎是一样的。因此,许多用户考虑对名字加以修饰,使它们真正由“username.tablename”组成。如果在PostgreSQL中为每个用户都创建了-一-个与用户名同名的模式,那么就能与Oracle数据库相兼容了。
同样,在SQL标准里也没有public模式的概念。为了最大限度地遵循标准,并且与其他数据库兼容(如与Oracle数据库),不应该使用(甚至是应该删除) public模式。
当然,有些数据库系统可能根本没有模式,或者是通过允许跨数据库访问来提供模式功能的,如MySQL。如果需要在这些数据库上实现最大限度的移植性,或许不应该使用模式。假设MySQL实例中有三个数据库,在移植到PostgreSQL时,或许你应该建三个模式,使其与MySQL实例中的三个数据库相对应,而不是在PostgreSQL中创建三个数据库与之对应。
在PostgreSQL数据库中,表还有一些其他的存储属性。比如,在表上可以设定以下存储参数:fillfactor和 toast.fillfactor。
fillfactor为这个表的填充因子,toast.fillfactor是这个表中TOAST 表的填充因子。填充因子是一个从10到100的整数,表示在插入数据时,在一个数据块中填充百分之多少的空间后就不再填充了,另一部分空间预留了更新时使用。比如,设置为60,则表示往一个数据块中插人的数据占用60%的空间后,就不再往这个数据块中插数据了。而保留的这40%的空间,就是为了更新数据时使用。
在PostgreSQL中,更新一条数据时,旧的数据行并不会被覆盖,而是会插人一条新的数据行,如果块中有空闲空间,则新行直接插入到这个数据块中,由于行仍然在这个数据块中,因此PostsgreSQL可以使用到Heap-Only Tuple技术,Heap-Only Tuple会在旧行与新行之间建一个链表,这样一来,就不需要更新索引了,索引项仍会指向旧行,但通过旧行与新行之间的链表可以找到最新的行。因为Heap-Only Tuple的链表不能跨数据块,如果新行必须插入新的数据块中,则无法使用Heap-Only Tuple技术,这时就需要更新这表上的所有索引了,这将导致很大的开销。所以对于更新频繁的表需要设置一个较小的fillfactor值。
建表时,可以为一个字段指定默认值。若已指定默认值的列新插入了一行,但设定了默认值的字段数值没有声明,那么这些字段将被自动填充为它们各自的默认值。比如,建了一张表“student”,对字段“age”设定默认值为15,当我们插放数据时,虽没有指定“age”字段,“age”字段还是被自动地设定为15了:
数据类型限制了在表的一个列中存储什么类型的数据,对于很多应用来说,这种限制还不够,有时还需要如下一些限制:
一个人的年龄只接受正数的数值,但目前在PostgreSQL没有只接受正数的数值类型;
而且人的年龄是有一定范围的,但目前的数值类型不能设定任意范围;
不允许表中出现完全一样的两行;
表与表之间是有关联的,比如,有“学生”与“班级”两张表,任何一个学生都是属于某一个班级的,因此要求“学生”表中记录的“班级”一定是存在于“班级”表中的。对于这些问题,SQL 允许你在字段和表上定义约束,约束允许你对数据进行任意控制。如果用户企图在字段里存储违反约束的数据,那么就会抛出一个错误。
目前约束有以下几类:
(1) 检查约束
(2) 非空约束
(3) 唯一约束
(4) 主键外键
PostgreSQL是通过表继承来实现分区表的。表分区就是把逻辑上的一个大表分割成物理上的几个小块。分区可以提供若干好处: