首页 / PostgreSQL 入门教程 / Schema(模式)概念与操作

PostgreSQL 入门教程

Schema(模式)概念与操作

本教程共 50 篇 · 第 7 篇 · 更新于 2026-07-31 · 约 7 分钟阅读

PostgreSQLPostgreSQL 入门教程Schema模式search_path命名空间

7. Schema(模式)概念与操作

本节目标:学完你能说清模式是什么,会建模式、在模式里建表,并理解 search_path 怎么影响表名查找。

很多新手建表时从没管过「模式」,表却总能建出来。这是因为有个默认模式在替你兜底。这一章把它讲透。

模式是什么

模式(Schema)可以理解成数据库内部的「文件夹」或「命名空间」。它把表、视图、函数、索引等对象组织在一起。

打个比方:数据库像一块硬盘,模式像硬盘里的文件夹,表就是文件夹里的文件。同一个数据库里可以有很多模式,不同模式下可以存在同名表而不冲突。

Note

模式有点像操作系统的目录,但有一个关键区别:模式不能嵌套。你不能在一个模式里再建子模式。想分层,只能在命名上做文章,比如 app_usersapp_orders

用模式的好处:

  • 多个用户共用一个库时互不干扰。
  • 把对象按业务分门别类,好管理。
  • 第三方应用的对象放独立模式,避免和你自己的表重名。
Tip

一个很实用的做法:给每个业务模块一个模式。比如订单系统用 orders 模式、用户系统用 users 模式。这样几百张表也不乱。

默认的 public 模式

你之前建表时从没指定模式,表却出现在 public 模式下。这是因为每个新库都自带一个叫 public 的模式,而且它是默认查找位置。

之前看到的 \d 输出里,表前面那个 public 就是模式名:

     Table "public.users"

也就是说,CREATE TABLE users (...) 实际等价于建在 public 模式下。

Note

public 模式默认所有人都能建表,这在小项目无所谓;但多人协作或生产环境,为了安全常会回收 public 的建表权限。这块后面权限章节再展开,现在知道「默认有个 public」即可。

创建模式

语法很简单:

CREATE SCHEMA myschema;

建好之后,在它里面建表,要带上模式名前缀:

CREATE TABLE myschema.users (
    id      INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    username TEXT NOT NULL
);

这里 myschema.users 是「模式名.表名」的写法,叫限定名(qualified name)。查这张表时也要带上前缀:

SELECT * FROM myschema.users;
Tip

自增主键我们用 GENERATED ALWAYS AS IDENTITY,这是 PostgreSQL 18 推荐写法。SERIAL 是老式写法,新项目不建议再用了。

还可以建模式的同时指定属主:

CREATE SCHEMA myschema AUTHORIZATION alice;

这表示 myschema 归用户 alice 所有,她对这个模式里的对象有完全控制权。

删除模式

删除空模式(里面没任何对象):

DROP SCHEMA myschema;

如果模式里还有表,直接删会报错。两种选择:

  • 先把里面的表删干净,再删模式。
  • 或者加 CASCADE,连里面的对象一起删:
DROP SCHEMA myschema CASCADE;
Warning

CASCADE 会把这个模式里的表、视图等全部删掉,且不可恢复。用之前一定确认里面没有要保留的东西。删模式不会问你第二次。

修改模式

改模式名字:

ALTER SCHEMA myschema RENAME TO newschema;

改模式属主:

ALTER SCHEMA myschema OWNER TO new_owner;
Note

改名只影响模式本身,里面表的限定名前缀会跟着变(因为前缀是模式名)。之前写的 SELECT * FROM myschema.users; 要改成 newschema.users;。所以改名前,最好确认没有别处的 SQL 写死了旧前缀。

search_path:决定去哪找表

前面说默认表建在 public。那 Postgres 怎么知道不写模式名时该去哪找?靠一个叫 search_path 的设置。

search_path 是一个「查找顺序列表」。不写模式前缀时,Postgres 就按这个列表从左到右找,找到第一个匹配的表就用。

看当前设置:

SHOW search_path;

默认通常是:

"$user", public

意思是:先找和当前用户名同名的模式,找不到再找 public。因为一般没有同名模式,所以最终都落到了 public

临时改 search_path(仅当前会话有效):

SET search_path TO myschema, public;

设完之后,即使不写前缀,SELECT * FROM users; 也会优先去 myschema 里找 users

Tip

想让某个模式成为默认工作区,把它的模式名放进 search_path 最前面最方便。比如在项目里习惯把所有表放 app 模式,就可以 SET search_path TO app, public;。当前会话退出后就失效,不会污染环境。

也可以给单个用户设永久的 search_path:

ALTER ROLE myuser SET search_path TO app, public;

这样 myuser 每次连进来,默认就先找 app 模式,不用每次手动 SET。

一个容易混淆的点

假设 publicmyschema 下各有一张 users 表。当前 search_pathmyschema, public。你写:

SELECT * FROM users;

Postgres 会返回 myschema.users,因为 myschema 排在前面。这就是 search_path 的「就近原则」。想精确指定,永远写全限定名 public.users 最稳。

模式速查

操作语句
建模式CREATE SCHEMA 名;
删空模式DROP SCHEMA 名;
连对象删DROP SCHEMA 名 CASCADE;
改名ALTER SCHEMA 名 RENAME TO 新名;
改属主ALTER SCHEMA 名 OWNER TO 用户;
看查找顺序SHOW search_path;

小结

模式是库内部的命名空间,默认用 public。建表可写「模式.表名」,不写就按 search_path 去找。掌握它,你管理大量表时就不会乱。

给模式授权

模式建好后,默认只有属主和超级用户能在里面建对象。想让别的用户也能用,要授权:

GRANT USAGE ON SCHEMA myschema TO appuser;
GRANT CREATE ON SCHEMA myschema TO appuser;

USAGE 是「能用里面的对象」,CREATE 是「能往里建新对象」。权限细节后面有专门章节,这里先知道「模式也能授权」这件事。

Note

public 模式默认对所有人开放 CREATE 权限,所以你之前建表从没授权。但生产环境常会回收这个默认权限,改成显式授权,更安全。

information_schema:另一个特殊模式

每个库里还有一个叫 information_schema 的系统模式,里面是一堆视图,记录着「这个库有哪些表、哪些列、哪些约束」这类元信息。想用 SQL 查结构而不是用 \d,可以查它:

SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public';

这招在做「自动探库」的工具时很有用。平时看结构还是 \d 快,但记住 information_schema 的存在,关键时刻能派上用场。

跨模式查询的完整例子

假设你有两个模式:hr(人事)和 sales(销售),各有一张 users 表。想同时看两边的老板:

SELECT 'hr' AS src, username FROM hr.users WHERE username = 'boss'
UNION ALL
SELECT 'sales' AS src, username FROM sales.users WHERE username = 'boss';

靠「模式.表名」就能量化到具体哪张表,不会糊涂。这也正是模式存在的意义:隔离同名对象。

什么情况下该用多个模式

给你一个判断参考:

  • 单人或小项目,表不多:一个 public 足够,别过度设计。
  • 多模块中大型项目:按模块拆模式,清晰。
  • 第三方插件/扩展:让它们待在自己模式,不污染你的表。
  • 多租户(不同客户数据隔离):有的方案用「每租户一个模式」,隔离性最强。
Warning

模式不是越多越好。拆太细,查询时到处写前缀,反而累。先 public 起步,真需要隔离了再拆,是更务实的做法。

下一章我们用它来正式建表。