schame是位于database之下容器,用来组织数据库对象,如表、视图、索引等,表、视图等必须位于某一个schema下。
database之间是无法互相访问,但同一个database下的不同schame的对象是可以互相访问。
每一个数据库中都存在一个名称为public的schema,public用来存放在创建对象时未明确指定schema的对象,public的属主为postgres。
mydb=# \dn
List of schemas
Name | Owner
--------+----------
myq | myq
public | postgres
(2 rows)
创建schema,创建时可以指定schema的属主用户,如果不指定则为当前用户
mydb=# \dn
List of schemas
Name | Owner
--------+----------
public | postgres
s1 | myq
(2 rows)
mydb=# create schema s2;
CREATE SCHEMA
mydb=# \dn
List of schemas
Name | Owner
--------+----------
public | postgres
s1 | myq
s2 | myq
(3 rows)
创建表,创建表时可以指定表位于哪个schema,如果忽略,则按照search_path的规则存放
#不指定schema
mydb=# create table a(name varchar(10));
CREATE TABLE
mydb=# \dt
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
public | a | table | myq
(1 row)
#指定schema
mydb=# create table s2.b(name varchar(10));
CREATE TABLE
mydb=# \dt s2.*
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
s2 | b | table | myq
(1 row)
搜索路径(search_path)
如一个database下有多个schema,多个schema中都有同名的对象,那么在访问对象时如何确定要访问的对象呢?
pg中有一个变量名为search_path,定义的查找对象的顺序,可以使用show search_path;命令显示变量的值
mydb=# show search_path;
search_path
-----------------
"$user", public
(1 row)
search_path变量的默认值为"$user", public。变量的值是schema的列表,"$user"表示与用户同名的schame,public为publicschema。
pg在查找对象时就是按照search_path中定义的schema顺序查找的。先在列表中的第一个schema即与用户同名的schame中查找对象是否存在,如果未找到继续查找第二个schema,找到即停止搜索。
mydb=# \dt
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
myq | a | table | myq
(1 row)
mydb=# \dt public.*
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
public | a | table | myq
(1 row)
mydb=# \dt s1.*
List of relations
Schema | Name | Type | Owner
--------+----------+-------+-------
s1 | a | table | myq
s1 | accounts | table | myq
s1 | t | table | myq
(3 rows)
mydb=# select * from myq.a;
name
------
myq
(1 row)
mydb=# select * from public.a;
name
--------
public
(1 row)
mydb=# select * from s1.a;
name
------
s1
(1 row)
如果在查询时不指定schema,看下查询结果是哪个schema下的表
#存在与用户同名的schema
mydb=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
myq | Superuser | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
mydb=# \dn
List of schemas
Name | Owner
--------+----------
myq | myq
public | postgres
s1 | myq
(3 rows)
mydb=# select * from a;
name
------
myq
(1 row)
#不存在与用户同名的schame
mydb=# \dn
List of schemas
Name | Owner
--------+----------
public | postgres
s1 | myq
(2 rows)
mydb=# select * from a;
name
--------
public
(1 row)
总结:
1. schema为表的容器,表必须存放于某个schema中
2. 创建表时如果未指定schema,则会按照search_path的规则查找schema存放。指定schema的语法为schema.tablename
3. search_path定义了查找对象的schema的顺序,依次搜索列表中的schema查找对象,找到即停止搜索,找到最后没找到就会报表不存在错误