Schema(模式)概念与操作
本教程共 50 篇 · 第 7 篇 · 更新于 2026-07-31 · 约 7 分钟阅读
7. Schema(模式)概念与操作
本节目标:学完你能说清模式是什么,会建模式、在模式里建表,并理解 search_path 怎么影响表名查找。
很多新手建表时从没管过「模式」,表却总能建出来。这是因为有个默认模式在替你兜底。这一章把它讲透。
模式是什么
模式(Schema)可以理解成数据库内部的「文件夹」或「命名空间」。它把表、视图、函数、索引等对象组织在一起。
打个比方:数据库像一块硬盘,模式像硬盘里的文件夹,表就是文件夹里的文件。同一个数据库里可以有很多模式,不同模式下可以存在同名表而不冲突。
Note模式有点像操作系统的目录,但有一个关键区别:模式不能嵌套。你不能在一个模式里再建子模式。想分层,只能在命名上做文章,比如
app_users、app_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。
一个容易混淆的点
假设 public 和 myschema 下各有一张 users 表。当前 search_path 是 myschema, 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起步,真需要隔离了再拆,是更务实的做法。
下一章我们用它来正式建表。