目录
1 Schema的概念
database schema table之间的关系
引入schema的原因
创建Schema
查看Schema
删除Schema
2 Public Schema
3 Schema的索索路径
4 Schema 与 权限
5 系统Catalog Schema
6 使用方式(最佳实践)
7 可移植性
一个PostgreSQL数据库集群中包含一个或更多的数据库。 角色和一些其他对象类型被整个集群共享,连接到服务器的客户端只能访问单个数据库中的数据,在连接请求中指定的那一个。
一个数据库包含一个或多个模式,模式中包含着表。模式还包含其他类型的命名对象,包括数据类型、函数和操作符。相同的对象名称可以被用于不同的模式中而不会出现冲突,例如schema1和myschema都可以包含名为mytable的表。和数据库不同,模式并不是被严格地隔离:一个用户可以访问他们所连接的数据库中的所有模式内的对象,只要他们有足够的权限。
重点:
cluster可以包含多个database ,每个database可以包含多个schema,schema中包含table和其他对象
database
每个PG服务可以包含多个独立的database
schema
如果把databases比作一个国家,那么schema就是一些独立的省。大多数对象是隶属于某个schema的,然后schema又隶属于某个databases。在创建一个新的database时,PG会自动为其创建一个名为public的schema。如果未设置searc_path变量,那么PG会将你创建的所有对象默认放入public schema中。如果表的数量较少,这是没问题的,但是如果你有几千张表,那么我们还是建议你将他们分门别类放入不同的schema中。
表
任何一个数据库中,表都是最核心的对象类型。在PG中,表首先属于某个schema,而schema有属于某个database,这样就构成一种三级存储结构。PG的表支持两种很强大的功能。第一种是继承,即一张表可以有父表和子表,这种层次化的结构可以极大的简化数据库设计,还可以为你省掉大量的重复查询代码。第二种是创建一张表的同时,系统会自动为此表创建一种对应的自定义数据类型。
允许多个用户使用一个数据库并且不会互相干扰。
将数据库对象组织成逻辑组以便更容易管理。
第三方应用的对象可以放在独立的模式中,这样它们就不会与其他对象的名称发生冲突。
# 切换到db3数据库 postgres=# \c db3 You are now connected to database "db3" as user "postgres". db3=# # 创建schema db3=# create SCHEMA myschema; CREATE SCHEMA # 在myschema中创建表cities CREATE TABLE db3.myschema.cities ( name varchar(80), location point ); # 创建一个由其他人所拥有的模式(因为这是将用户动作限制在良定义的名字空间中的方法之一)。其语法是: db3=# CREATE SCHEMA myschema3 AUTHORIZATION role3; CREATE SCHEMA db3=# db3=# db3=# \dn List of schemas Name | Owner -----------+---------- myschema | postgres myschema2 | postgres myschema3 | role3 public | postgres (4 rows)
db3=# \dn List of schemas Name | Owner -----------+---------- myschema | postgres myschema2 | postgres public | postgres (3 rows)
# 删除不为空的schema会报错 db3=# drop schema myschema; ERROR: cannot drop schema myschema because other objects depend on it DETAIL: table cities depends on schema myschema HINT: Use DROP ... CASCADE to drop the dependent objects too. # 要删除一个模式以及其中包含的所有对象,可用 db3=# DROP SCHEMA myschema CASCADE; NOTICE: drop cascades to table cities DROP SCHEMA
创建的表如果不指定任何schema名称。默认情况下这些表(以及其他对象)会自动的被放入一个名为“public”的schema中。任何新数据库都包含这样一个模式。因此,下面的命令是等效的:
CREATE TABLE products ( ... ); CREATE TABLE public.products ( ... );
搜索路径中的第一个schema被称为当前schema。除了是第一个被搜索的schema外,如果CREATE TABLE命令没有指定schema名,它将是新创建表所在的schema。
# 显示当前的搜索路径 db3=# SHOW search_path; search_path ----------------- "$user", public (1 row)
第一个元素说明一个和当前用户同名的schema会被搜索。如果不存在这个schema,该项将被忽略。第二个元素指向我们已经见过的public schema。
搜索路径中的第一个模式是创建新对象的默认存储位置。这就是默认情况下对象会被创建在公共模式中的原因。当对象在任何其他没有模式限定的环境中被引用(表修改、数据修改或查询命令)时,搜索路径将被遍历直到一个匹配对象被找到。因此,在默认配置中,任何非限定访问将只能指向公共模式。
# 修改搜索路径
SET search_path TO myschema,public;
SET search_path TO myschema;
除public和用户创建的模式之外,每一个数据库还包括一个pg_catalog模式,它包含了系统表和所有内建的数据类型、函数以及操作符。pg_catalog总是搜索路径的一个有效部分。如果没有在路径中显式地包括该模式,它将在路径中的模式 之前 被搜索。这保证了内建的名称总是能被找到。然而,如果我们希望用用户定义的名称重载内建的名称,可以显式的将pg_catalog放在搜索路径的末尾。
由于系统表名称以pg_开头,最好还是避免使用这样的名称,以避免和未来新版本中可能出现的系统表名发生冲突。系统表将继续采用以pg_开头的方式,这样它们不会 与非限制的用户表名称冲突。
模式能够以多种方式组织数据。一个安全模式使用方式可以防止不受信任的用户更改其他用户的查询行为。当数据库没有使用安全模式使用方式时,希望安全地查询该数据库的用户将在每个会话开始时采取保护操作。具体的说,他们开始会话前会设置search_path为空字符串,或者删除search_path中非超级用户可写的模式。以下的一些使用方式在默认配置下可以很容易实现。
将普通用户约束在其私有的方案中。要实现这一点,执行REVOKE CREATE ON SCHEMA public FROM PUBLIC,并且为每一个用户创建一个用其用户名命名的模式。回想一下,默认搜索路径开头的$user会解析为用户名。因此,如果每个用户都有单独的模式,则默认情况下他们访问自己的模式。在不受信任的用户已经登录的数据库中采用此使用方式后,请考虑检查公共模式中名字与模式pg_catalog中对象相类似的对象。此方式是一种安全模式的使用方式,除非不受信任的用户是数据库所有者或拥有CREATEROLE权限,在这种情况下将不存在没有安全模式使用方式。
从默认搜索路径中删除公共模式,通过修改postgresql.conf或执行ALTER ROLE ALL SET search_path ="$user"。每一个角色都仍然保留在公共模式中创建对象的能力,但是只有符合的名称才会选择到这些对象。虽然符合的的表引用是安全的,但是调用公共模式中的函数会是不安全或不可靠的。如果要在公共模式中创建函数或扩展,请改用第一个方式。否则,与第一个使用方式一样,这是安全的,除非不受信任的用户是数据库所有者或拥有CREATEROLE权限。
保持默认。所有用户都隐式地访问公共模式。这模拟了根本没有使用模式的情况,可以用于从无模式的世界平滑过渡。但是,这绝不是一个安全的使用方式。只有当数据库仅有单个用户或者少数相互信任的用户时,才可以接受。
对于任何一种模式,如果要安装共享的应用(所有人都要用的表、第三方提供的额外函数,等等),可把它们放在单独的模式中。记得授予适当的权限以允许其他用户访问它们。然后用户可以通过以模式名限定名称的方式来引用这些额外的对象,或者他们可以把额外的模式放在自己的搜索路径中。