模式(schema)可以连接为一个命名空间或目录。不同的模式下可以有相同的名称的表、函数等对象且互相不冲突。模式是为了便于管理,只要有权限,每个模式的对象可以互相调用.
在PostgreSQL中,一个数据库包含一个或多个模式,模式又包含了表、函数及操作符等数据库对象。在PostgreSQL中,不能同时访问不同数据库中的对象,当要访问另一个数据库中的表或其他对象时,需要重新连接到这个新的数据库,而模式没有此限制。
我们需要使用模式的主要原因:
CREATE SCHEMA schema_name [ AUTHORIZATION role_specification ] [ schema_element [ ... ] ] CREATE SCHEMA AUTHORIZATION role_specification [ schema_element [ ... ] ] CREATE SCHEMA IF NOT EXISTS schema_name [ AUTHORIZATION role_specification ] CREATE SCHEMA IF NOT EXISTS AUTHORIZATION role_specification where role_specification can be: user_name | CURRENT_USER | SESSION_USER
模式使用例子:
1.创建schema salesapp [root@node1 ~]# su - postgres -bash-4.2$ psql postgres=# \c testdb; postgres=# CREATE ROLE salesapp with LOGIN ENCRYPTED PASSWORD 'abc123'; testdb=# \du List of roles Role name | Attributes | Member of -----------+------------------------------------------------------------+----------- postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {} salesapp | | {} testdb=# CREATE SCHEMA AUTHORIZATION salesapp; CREATE SCHEMA 这里可以直接 testdb=# CREATE SCHEMA salesapp; 或者 testdb=# CREATE SCHEMA salesapp AUTHORIZATION salesapp; testdb=# \dn List of schemas Name | Owner ----------+---------- public | postgres salesapp | salesapp (2 rows) testdb=# create table salesapp.t1(c1 int); CREATE TABLE testdb=# select * from pg_tables where schemaname='salesapp'; schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity ------------+-----------+------------+------------+------------+----------+-------------+------------- salesapp | t1 | postgres | | f | f | f | f (1 row) testdb=# insert into salesapp.t1 values(1); INSERT 0 1 testdb=# insert into salesapp.t1 values(2); INSERT 0 1 testdb=# select * from salesapp.t1; c1 ---- 1 2 (2 rows) ===================================================================== 2.用salesapp用户连接数据库,可以看到这个schema下面的表 -bash-4.2$ psql -h 127.0.0.1 -p 5432 testdb salesapp Password for user salesapp: psql (13.2) Type "help" for help. testdb=> \dt List of relations Schema | Name | Type | Owner ----------+------+-------+---------- public | e | table | postgres public | t | table | postgres public | t2 | table | postgres public | x1 | table | postgres public | x2 | table | postgres public | x3 | table | postgres salesapp | t1 | table | postgres salesapp | t11 | table | postgres ===================================================================== 3.删除schema testdb=# DROP SCHEMA salesappold; ERROR: cannot drop schema salesappold because other objects depend on it DETAIL: table salesappold.t1 depends on schema salesappold table salesappold.t11 depends on schema salesappold HINT: Use DROP ... CASCADE to drop the dependent objects too. testdb=# \dn List of schemas Name | Owner -------------+---------- public | postgres salesappold | sales (2 rows) testdb=# DROP SCHEMA salesappold CASCADE; NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to table salesappold.t1 drop cascades to table salesappold.t11 DROP SCHEMA testdb=# \dn List of schemas Name | Owner --------+---------- public | postgres (1 row)
在模式中修改名称和属主
ALTER SCHEMA name RENAME TO newname
ALTER SCHEMA name OWNER TO newowner
1. 改模式名称 postgres=# \c testdb; You are now connected to database "testdb" as user "postgres". testdb=# \dn List of schemas Name | Owner ----------+---------- public | postgres salesapp | salesapp (2 rows) testdb=# alter schema salesapp rename to salesappold; ALTER SCHEMA testdb=# \dn List of schemas Name | Owner -------------+---------- public | postgres salesappold | salesapp (2 rows) 2. 改模式属主 testdb=# CREATE ROLE sales with LOGIN ENCRYPTED PASSWORD 'abc123'; CREATE ROLE testdb=# alter schema salesappold owner to sales; ALTER SCHEMA testdb=# \dn List of schemas Name | Owner -------------+---------- public | postgres salesappold | sales (2 rows) 注意:要指定OWNER的话,请确保OWNER已存在。
要创建或者访问模式中的对象,需要先写出一个受修饰的名字,这个名字包含模式名及表名,用"点"分开。
schema_name.table_name
通常情况下,创建和访问表的时候不用指定模式,实际上这时访问的是"public"模式。每当我们创建了一个新的数据库时,PostgreSQL会自动创建一个名为"public"的模式,当登陆该数据库时,如果没有特殊指定,都是以该模式(public)操作各种数据对象的。
使用一个数据库对象时,虽然可以使用它的全称来定位对象,但这样一来,每次都不得不输入schema_name.object_name,这显然很繁琐。PostgreSQL提供了模式搜索路径,指定在哪个模式下执行,类似于设置默认模式。
1.查看当前SCHEMA,并列出public模式下的表 postgres=# \c testdb You are now connected to database "testdb" as user "postgres". testdb=# SHOW search_path; search_path ----------------- "$user", public (1 row) testdb=# \d List of relations Schema | Name | Type | Owner --------+------+-------+---------- public | e | table | postgres public | t | table | postgres public | t1 | table | postgres public | t2 | table | postgres public | x1 | table | postgres public | x2 | table | postgres public | x3 | table | postgres testdb=# create schema sales; CREATE SCHEMA testdb=# SET search_path TO sales,public; 或者 testdb=# SET search_path TO sales; testdb=# SHOW search_path; search_path --------------- sales, public (1 row) testdb=# create table sales.t1(c1 int); CREATE TABLE testdb=# \d List of relations Schema | Name | Type | Owner --------+------+-------+---------- public | e | table | postgres public | t | table | postgres public | t2 | table | postgres public | x1 | table | postgres public | x2 | table | postgres public | x3 | table | postgres sales | t1 | table | postgres (7 rows) testdb=# create table t2(c1 int); CREATE TABLE testdb=# \d List of relations Schema | Name | Type | Owner --------+------+-------+---------- public | e | table | postgres public | t | table | postgres public | x1 | table | postgres public | x2 | table | postgres public | x3 | table | postgres sales | t1 | table | postgres sales | t2 | table | postgres (7 rows) 可以看到,我们不指定schema建表,也会默认在sales下面。
默认情况下,用户无法访问模式不属于他们的对象。若要访问,模式的所有者必须在模式上赋予他们"USAGE"权限。为了让用户使用模式中的对象,可能需要赋予适合该对象的额外权限。
用户也可以在别人的模式里创建对象,当然,这需要被赋予了该模式上的"CREATE"权限。请注意,默认情况下每个人在public模式上都有"CREATE"和"USAGE"权限,也就是允许所有可以连接到指定数据库上的用户在这里创建对象。如果你不打算这么做,可以撤销这个权限
testdb=# REVOKE CREATE ON SCHEMA PUBLIC FROM PUBLIC; 第一个PUBLIC是模式名称 第二个PUBLIC是所有用户 用sales用户连接testdb -bash-4.2$ psql -h 127.0.0.1 -p 5432 testdb sales; Password for user sales: xxx psql (13.2) Type "help" for help. testdb=> create table t3(c1 int); ERROR: permission denied for schema public LINE 1: create table t3(c1 int); 这里可以看到提示没有public模式权限。