pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
PostgreSQL 数据库集群(安装实例) 包含一个或多个命名的数据库。用户和用户组在整个 集群中共享,但其他数据不在数据库之间 共享。到服务器的任何客户端连接都只能访问 单个数据库中的数据,即连接请求中 指定的那个数据库。
一个集簇的用户并不必拥有访问集簇中每一个数据库的权限。 用户名的共享意味着不可能在同一个集簇中出现重名的不同用户,例如两个数据库中都有叫joe的用户。 但系统可以被配置为只允许joe访问某些数据库。
一个数据库包含一个或多个命名的模式,模式中又包含表。 模式还包含其他类型的命名对象,包括数据类型、函数和操作符。 在同一个模式中,同一类型的两个对象不能有相同的名称。 此外,表、序列、索引、视图、物化视图和外部表共享同一个名字空间, 因此例如当它们位于同一模式中时,索引和表就必须具有不同的名称。 相同的对象名可以在不同模式中重复使用而不发生冲突;例如, schema1和myschema都可以包含名为mytable的表。 与数据库不同,模式并不是被严格隔离的:只要拥有相应权限,用户就可以访问其所连接数据库中任意模式里的对象。
下面是一些使用模式的原因:
允许多个用户使用一个数据库并且不会互相干扰。
将数据库对象组织成逻辑组以便更容易管理。
第三方应用的对象可以放在独立的模式中,这样它们就不会与其他对象的名称发生冲突。
模式类似于操作系统层的目录,但是模式不能嵌套。
要创建一个独立的模式,使用命令 CREATE SCHEMA。给模式起一个你选择的名字。例如:
CREATE SCHEMA myschema;
要在模式中创建或访问对象,写一个由模式名和表名组成并以点分隔的 限定名:
schema.table
Actually, the even more general syntax
database.schema.table
can be used too, but at present this is just for pro-forma compliance with the SQL standard; if you write a database name it must be the same as the database you are connected to.
因此要在新模式中创建一个表,使用
CREATE TABLE myschema.mytable ( ... );
凡是可以使用表名的地方这都有效,包括后续章节讨论的表 修改命令和数据访问命令。
要删除一个为空的模式(其中的所有对象已经被删除),可用:
DROP SCHEMA myschema;
要删除一个模式以及其中包含的所有对象,可用:
DROP SCHEMA myschema CASCADE;
有关于此的更一般的机制请参见第 2.10 节。
我们常常希望创建一个由其他人所拥有的模式(因为这是将用户动作限制在良定义的名字空间中的方法之一)。其语法是:
CREATE SCHEMAschemanameAUTHORIZATIONusername;
我们甚至可以省略模式名称,在此种情况下模式名称将会使用用户名,参见第 2.8.6 节。
以pg_开头的模式名被保留用于系统目的,所以不能被用户所创建。
在前面的小节中,我们创建表时都没有指定模式名。默认情况下,这些表(以及其他对象)会自动放入名为“public”的模式中。每个新数据库都包含这样一个模式。因此,下面两条命令是等效的:
CREATE TABLE products ( ... );
以及:
CREATE TABLE public.products ( ... );
限定名写起来很繁琐,而且通常最好不要把某个特定模式名硬编码到应用中。因此,表通常通过非限定名来引用,也就是只写表名。系统会沿着一条搜索路径来决定该名称指的是哪个表;搜索路径就是要查找的一组模式列表。搜索路径中第一个匹配的表会被视为目标表。如果搜索路径中没有任何匹配,就会报错,即使数据库的其他模式中存在同名表也是如此。
搜索路径中的第一个模式被称为当前模式。除了是第一个被搜索的模式外,如果CREATE TABLE命令没有指定模式名,它将是新创建表所在的模式。
要显示当前的搜索路径,使用下面的命令:
SHOW search_path;
在默认设置下它返回:
search_path -------------- $user,public
第一个元素表示要搜索与当前用户同名的模式。由于这样的 模式尚不存在,这一项会被忽略。第二个元素指的是我们 已经见过的公共模式。
搜索路径中第一个存在的模式,是创建新对象时的默认位置。这就是默认情况下对象会被创建在公共模式中的原因。当对象在其他任何未限定模式的上下文中被引用时(表修改、数据修改或查询命令),系统会沿搜索路径查找,直到找到匹配对象为止。因此,在默认配置中,任何非限定访问仍然只能指向公共模式。
要把新模式放在搜索路径中,我们可以使用:
SET search_path TO myschema,public;
(我们在这里省略了$user,因为我们并不立即需要它)。然后我们可以删除该表而无需使用模式进行限定:
DROP TABLE mytable;
同样,由于myschema是路径中的第一个元素,新对象默认也会创建在其中。
我们也可以这样写:
SET search_path TO myschema;
这样一来,在没有显式限定时,我们就不再能访问公共模式了。公共模式本身并无特殊之处,只是默认存在而已;它同样可以被删除。
访问模式搜索路径的其他方法另见 第 6.13 节。
搜索路径对于数据类型名称、函数名称和操作符名称的作用与表名一样。数据类型和函数名称可以使用和表名完全相同的限定方式。如果我们需要在一个表达式中写一个限定的操作符名称,我们必须写成一种特殊的形式:
OPERATOR(schema.operator)
这是为了避免句法歧义。例如:
SELECT 3 OPERATOR(pg_catalog.+) 4;
实际上我们通常都会依赖于搜索路径来查找操作符,因此没有必要去写如此“丑陋”的东西。
默认情况下,用户看不到不属于自己的 模式中的对象。要允许这一点,模式的所有者需要授予该 模式上的 USAGE 权限。要让用户 能够使用模式中的对象,可能还需要根据 对象的情况授予额外的权限。
也可以允许用户在别人的模式中创建对象。 To allow that, the CREATE privilege on the schema needs to be granted. Note that by default, everyone has the CREATE privilege on the schema public. This allows all users that manage to connect to a given database to create objects there. If you do not want to allow that, you can revoke that privilege:
REVOKE CREATE ON public FROM PUBLIC;
(The first “public” is the schema, the second “public” means “every user”. In the first sense it is an identifier, in the second sense it is a reserved word, hence the different capitalization; recall the guidelines from 第 1.1.1 节.)
除public和用户创建的模式之外,每一个数据库还包括一个pg_catalog模式,它包含了系统表和所有内置的数据类型、函数以及操作符。pg_catalog总是搜索路径的一个有效部分。如果没有在路径中显式地包括该模式,它将在路径中的模式之前被搜索。这保证了内置的名称总是能被找到。然而,如果我们希望用用户定义的名称重载内置的名称,可以显式的将pg_catalog放在搜索路径的末尾。
在 PostgreSQL 7.3 之前的版本中, 以 pg_ 开头的表名是保留的。现在 不再如此:只要愿意,你可以在任何非系统 模式中创建这样的表名。但最好继续避免 这样的名字,以确保不会因为某个 未来版本定义了与你的表同名的系统目录 而遭遇冲突。(在默认搜索路径下,对 你的表名的非限定引用会被 解析为系统目录。)系统目录将继续遵循以 pg_ 开头命名的约定,因此只要用户避免 pg_ 前缀,它们就不会与非限定的 用户表名冲突。
模式可以用多种方式组织你的数据。以下是默认配置直接支持、 并且值得推荐的几种模式使用方式:
如果你不创建任何模式,那么所有用户都将隐式地访问 public 模式。这模拟了根本没有模式可用的情况。这种设置主要推荐用于数据库中只有单个用户或少数几个相互合作的用户的场景。这种设置也允许从不支持模式的环境平滑过渡。
你可以为每个用户创建一个与其同名的模式。请记住,默认搜索路径以$user开头,它会解析为用户名。因此,如果每个用户都有单独的模式,他们默认访问的就是自己的模式。
如果采用这种设置,你可能还想撤销对 public 模式的访问(或者干脆删除它),使用户真正被限制在他们自己的模式中。
要安装共享的应用(供所有人使用的表、 第三方提供的额外函数等),请把它们 放到单独的模式中。记住授予适当的 权限以允许其他用户访问它们。用户 之后可以通过用模式名限定名称来引用这些额外的 对象,也可以按自己的选择把这些额外的模式放进 自己的路径。
在 SQL 标准中,不存在同一模式中的对象 由不同用户所有的概念。此外,一些 实现不允许创建与其所有者不同名 的模式。事实上,在一个只实现了标准中 规定的基本模式支持的数据库系统 中,模式和用户这两个概念几乎是等价的。因此,许多用户认为限定名 实际上由 组成。如果你为每个用户创建一个每用户 模式,PostgreSQL 实际上就会表现得 如此。username.tablename
同样,SQL 标准中也没有public模式这一概念。为了尽可能符合标准,你不应使用(甚至可以移除)public模式。
当然,某些SQL数据库系统可能根本没有实现模式,或者提供(很可能是有限制地)允许跨数据库访问的命名空间。如果需要使用这样的系统,为了获得最好的可移植性,最好不要使用模式。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。