PostgreSQL · 错误码速查
PostgreSQL「database does not exist」:库名不存在,先连 postgres 库看清楚有哪些库
这条报错说明认证已经通过,但你指定的数据库名在这台实例上不存在。最常见的是 psql -U app 没写 -d,默认去连和用户同名的 app 库;其次是 Docker 复用旧数据卷,POSTGRES_DB 没生效。先用 psql -U app -d postgres -c '\l' 连到维护库看现有库,再 CREATE DATABASE appdb OWNER app; 或把连接串里的库名改对。
官方原文
database "%s" does not exist出自 PostgreSQL 源码 postinit.c 的 InitPostgres(),建立连接时以 FATAL 级别报出,错误码 ERRCODE_UNDEFINED_DATABASE(SQLSTATE 3D000)。库刚被删或改名的瞬间连接,会附带 DETAIL: It seems to have just been dropped or renamed.;库目录缺失时附带 The database subdirectory "..." is missing.。
出处:PostgreSQL 源码 REL_18_STABLE:src/backend/utils/init/postinit.c(InitPostgres) 最后核对:
| SQLSTATE | 3D000(invalid_catalog_name) | 出处 |
|---|---|---|
| 说明了什么 | pg_hba.conf 匹配和认证都已通过,只是库名在 pg_database 里查不到 | 出处 |
| psql 默认库名 | 等于连接所用的用户名 | 出处 |
| Docker 镜像 | POSTGRES_DB 默认等于 POSTGRES_USER,只在数据目录为空时创建 | 出处 |
| 库名大小写 | 未加引号的名字折成小写,CREATE DATABASE MyDB 建出的是 mydb | 出处 |
没写库名时,客户端会去连哪个库
psql 文档写明:默认用户名是操作系统用户名,确定用户名之后,默认数据库名就等于用户名。所以下面几种写法都会去找一个你可能从没建过的库:
| 你执行的 | 实际连接的库 | 结果 |
|---|---|---|
psql -U app | app | 库里只有 appdb 时失败 |
sudo -u postgres psql | postgres | 成功:initdb 默认建有 postgres 库 |
psql -U app -d postgres | postgres | 成功(app 有 CONNECT 权限时) |
psql postgresql://app@127.0.0.1/appDB | appDB(原样,区分大小写) | 库实际叫 appdb 时失败 |
postgres 库是 initdb 自动创建的维护库,专门用来“先连上再说”。排查时一律先连它,再看其他库在不在。
只读排查:确认库名和你连的实例
-- 连到维护库:psql -U app -d postgres
SELECT datname, pg_get_userbyid(datdba) AS owner, datallowconn
FROM pg_database
ORDER BY datname;
-- 核对自己连的是哪个实例(多实例 / 容器 / 端口转发时很有用)
SELECT inet_server_addr(), inet_server_port();- 列表里有、但名字大小写不同:连接时用库里的实际名字,或用双引号建的库要原样写。
- 列表里根本没有:要么库建在另一个实例上(端口、容器、主机不同),要么从没建过。
datallowconn为 false:这个库禁止连接(如 template0),会报别的错,不是本页这条。
Docker 与框架:建库这一步被跳过了
| 场景 | 为什么会报 | 怎么做 |
|---|---|---|
Docker 改了 POSTGRES_DB | 变量只在数据目录为空时生效,沿用旧卷不会建新库 | 保留数据:进容器 CREATE DATABASE;开发环境可删卷重建(会丢数据) |
Rails db:migrate / Django migrate | 迁移命令假定库已存在 | 先执行 rails db:create,或手动建库 |
Rails db:create 本身报错 | 建库前要先连一个已存在的库(Rails 的 PostgreSQL 适配器默认连 postgres 维护库),该库被删或无权限 | 确认 postgres 库存在、用户有 CREATEDB 权限 |
| CI 里每次都是新容器 | 服务容器起来了,但没有建库步骤 | 在 service 定义里设 POSTGRES_DB,或在 job 第一步 createdb |
Rails 的行为以你所用版本的官方文档为准;上表只描述通用原理:任何“建库”操作都必须先连上一个已存在的库。
建库:指定属主,别在事务里执行
-- 以超级用户或有 CREATEDB 权限的用户执行
CREATE DATABASE appdb OWNER app;
-- 命令行等价写法
-- createdb -U postgres -O app appdb- 库存在但报
permission denied for database:缺的是 CONNECT 权限,GRANT CONNECT ON DATABASE appdb TO app;,不是本页这条错。 - 库名写对了仍报错且附带
The database subdirectory ... is missing:说明 pg_database 里有记录、磁盘上的目录没了,属于数据目录损坏,先停手备份,不要随手重建。 - 执行
DROP DATABASE时看到同样的文字是 ERROR 而不是 FATAL:说明要删的库本来就不存在,可改用DROP DATABASE IF EXISTS。
常见问题
psql: FATAL: database "app" does not exist 是什么意思?
没写 -d 时 psql 默认连和用户名同名的库。用 psql -U app -d postgres 先连维护库,再 \l 看现有库,或 CREATE DATABASE app OWNER app 建一个。
Docker 设置了 POSTGRES_DB 为什么库没建?
POSTGRES_DB 只在数据目录为空、首次初始化时生效,沿用旧数据卷不会建新库。保留数据就进容器手动 CREATE DATABASE。
role does not exist 和 database does not exist 有什么区别?
role does not exist 是用户名不存在(SQLSTATE 28000);database does not exist 是用户名没问题、库名不存在(SQLSTATE 3D000)。后者说明认证已经通过。
库名大小写有关系吗?
有。CREATE DATABASE MyDB 不加引号会建成 mydb,连接时写 MyDB 就找不到。连接串里的库名是原样比对的。
可以在 SQL 客户端的事务里建库吗?
不行,CREATE DATABASE 不能在事务块里执行。有些图形客户端默认开事务,需要切成自动提交再执行。
免费 · 留邮箱领检查单
PostgreSQL 14 停更升级检查单(Excel 可直接打开)
- PG14 2026-11-12 停更,升 17 / 18 前后 19 项检查:只读预检、--check、回滚、补统计、回归
- 每项写清怎么查、通过标准、不处理会怎样(附测试库实测数字)
- 配合站上的只读预检 SQL 使用,每个业务库各跑一次
下一步
价格以对应页面当前标价为准。
出处(最后核对 2026-11-05)
- PostgreSQL 源码 REL_18_STABLE:src/backend/utils/init/postinit.c(InitPostgres)
- PostgreSQL 18 文档附录 A:PostgreSQL Error Codes
- PostgreSQL 18 文档:psql(默认用户名与默认数据库名)
- Docker 官方 postgres 镜像文档(POSTGRES_USER / POSTGRES_DB,仅空数据目录初始化时生效)
- PostgreSQL 18 文档 4.1.1:Identifiers and Key Words(未加引号的标识符折叠为小写)
- PostgreSQL 18 文档:CREATE DATABASE
本页摘录并解读上面列出的官方文档,不是官方页面;官方文档更新后以官方为准。本页内容都来自官方文档,没有我们自己的测试结果。