PostgreSQL: PostgreSQL数据库创建与管理

最后更新:2026-08-26

数据库是 PostgreSQL 中最顶层的组织单元——就像一个文件柜,里面可以放很多抽屉(表)。

1. 你将学到


2. 一个开发运维的真实故事

(1) 痛点:三个环境三种字符集

Charlie 需要为电商项目创建 3 个数据库,分别对应 dev / staging / prod 环境:

Charlie 不确定创建数据库时如何指定字符集和排序规则,也不知道模板数据库是什么。

(2) CREATE DATABASE 的解法

PostgreSQL 的 CREATE DATABASE 支持在创建时指定字符集、排序规则和模板:

SQL
-- Create databases with different locales for each environment
CREATE DATABASE shop_dev
    WITH ENCODING = 'UTF8'
    LC_COLLATE = 'en_US.utf8'
    LC_CTYPE = 'en_US.utf8'
    TEMPLATE = template1;

CREATE DATABASE shop_staging
    WITH ENCODING = 'UTF8'
    LC_COLLATE = 'en_US.utf8'
    LC_CTYPE = 'en_US.utf8';

CREATE DATABASE shop_prod
    WITH ENCODING = 'UTF8'
    LC_COLLATE = 'en_US.utf8'
    LC_CTYPE = 'en_US.utf8';

(3) 收益


3. 数据库基础概念

(1) PostgreSQL 的组织层级

100%
graph TB
    PG[PostgreSQL Instance<br/>One running server] --> DB1[Database: shop_dev]
    PG --> DB2[Database: shop_staging]
    PG --> DB3[Database: shop_prod]
    DB1 --> SC1[Schema: public]
    SC1 --> T1[Table: users]
    SC1 --> T2[Table: orders]
    DB2 --> SC2[Schema: public]
    DB3 --> SC3[Schema: public]
层级 说明 数量关系
实例(Instance) 一个运行中的 PostgreSQL 服务器进程 1 个实例包含多个数据库
数据库(Database) 最顶层的独立命名空间 1 个数据库包含多个 Schema
模式(Schema) 数据库内的命名空间(默认 public) 1 个 Schema 包含多个表
表(Table) 存储数据的二维表格 表属于某个 Schema
💡 提示: PostgreSQL 与 MySQL 不同——MySQL 的"数据库"更像 PG 的"Schema"。PG 中,连接时必须指定一个数据库,不同数据库之间不能直接 JOIN 查询(需要 FDW 跨库查询,后续课程讲解)。


4. CREATE DATABASE

(1) 基本语法

SQL
CREATE DATABASE name
    [WITH]
    [OWNER = user_name]
    [TEMPLATE = template]
    [ENCODING = encoding_name]
    [LC_COLLATE = lc_collate]
    [LC_CTYPE = lc_ctype]
    [TABLESPACE = tablespace_name]
    [CONNECTION LIMIT = conn_limit]
    [IS_TEMPLATE = true | false];
参数 默认值 说明
OWNER 执行命令的用户 数据库所有者
TEMPLATE template1 创建新数据库时复制的模板
ENCODING 模板的编码 字符编码(推荐 UTF8)
LC_COLLATE 模板的排序规则 字符串排序顺序
LC_CTYPE 模板的字符分类 字符分类(大小写/数字等)
TABLESPACE 默认表空间 数据文件存储位置
CONNECTION LIMIT -1(无限制) 最大并发连接数
IS_TEMPLATE false 标记为模板数据库

▶ 示例:创建基础数据库

SQL
-- Create a simple database with default settings
CREATE DATABASE my_app;

-- Verify creation
\l

输出:

TEXT 📖 仅展示
CREATE TABLE

▶ 示例:创建带完整参数的数据库

SQL
-- Create database with all common options specified
CREATE DATABASE shop_prod
    WITH OWNER = devuser
    ENCODING = 'UTF8'
    LC_COLLATE = 'en_US.utf8'
    LC_CTYPE = 'en_US.utf8'
    CONNECTION LIMIT = 100;

输出:

TEXT 📖 仅展示
CREATE TABLE
⚠️ 注意: 创建数据库时不能在事务中执行(BEGIN...COMMIT 内执行 CREATE DATABASE 会报错)。这是 PG 的设计——数据库创建是 DDL 操作,无法回滚。


5. 模板数据库

(1) template0 vs template1

PostgreSQL 有两个内置模板数据库:

属性 template0 template1
用途 纯净模板,不可修改 可定制模板,允许修改
能否修改 ❌ 不允许 ✅ 可以
默认内容 最小化系统对象 同 template0 + 用户自定义对象
何时使用 需要恢复原始编码/排序规则时 日常创建数据库(默认)
创建方式 TEMPLATE = template0 TEMPLATE = template1(默认)
📌 重点: 当你在 template1 中创建了表、函数或扩展后,所有新数据库都会继承这些对象。这是预配置新数据库的便捷方式。

▶ 示例:使用模板预配置数据库

SQL
-- Step 1: Connect to template1 and add common extensions
\c template1

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";

-- Step 2: Now all new databases will have these extensions
\c postgres

CREATE DATABASE new_project;
-- new_project automatically has uuid-ossp and pg_trgm

-- Step 3: Verify
\c new_project
\dx

输出:

TEXT 📖 仅展示
CREATE TABLE

▶ 示例:使用 template0 重建编码

SQL
-- If template1 has a different encoding than you need,
-- use template0 to create a database with specific encoding
CREATE DATABASE db_with_latin
    TEMPLATE = template0
    ENCODING = 'LATIN1'
    LC_COLLATE = 'C'
    LC_CTYPE = 'C';

输出:

TEXT 📖 仅展示
CREATE TABLE

6. ALTER DATABASE

(1) 常用修改操作

操作 语法 说明
重命名 ALTER DATABASE old_name RENAME TO new_name 修改数据库名称
设置参数 ALTER DATABASE name SET parameter = value 为该数据库设置运行参数
重置参数 ALTER DATABASE name RESET parameter 恢复参数默认值
修改所有者 ALTER DATABASE name OWNER TO new_owner 更改数据库所有者
设置连接限制 ALTER DATABASE name CONNECTION LIMIT = n 修改最大连接数
标记为模板 ALTER DATABASE name IS_TEMPLATE = true 标记/取消标记为模板

▶ 示例:修改数据库属性

SQL
-- Rename a database (must disconnect all users first)
ALTER DATABASE shop_dev RENAME TO shop_development;

-- Set default search_path for a database
ALTER DATABASE shop_prod SET search_path TO public, admin;

-- Set work_mem for a specific database
ALTER DATABASE shop_prod SET work_mem = '64MB';

-- Change connection limit
ALTER DATABASE shop_prod CONNECTION LIMIT = 200;

-- Mark as template
ALTER DATABASE shop_base IS_TEMPLATE = true;

输出:

TEXT 📖 仅展示
-- SQL 语句执行成功
⚠️ 注意: 重命名数据库前,必须断开所有连接该数据库的用户。可以用以下查询查看活跃连接:

SQL
-- Find active connections to a database
SELECT pid, usename, application_name, client_addr, state
FROM pg_stat_activity
WHERE datname = 'shop_dev';

7. DROP DATABASE

(1) 删除语法

SQL
DROP DATABASE [IF EXISTS] name [WITH (FORCE)];
选项 说明
IF EXISTS 数据库不存在时不报错(仅提示)
WITH (FORCE) 强制断开所有连接后删除(PG 13+)

▶ 示例:删除数据库

SQL
-- Safe delete (no error if database doesn't exist)
DROP DATABASE IF EXISTS old_project;

-- Force delete (disconnect all users first, PG 13+)
DROP DATABASE IF EXISTS shop_dev WITH (FORCE);

输出:

TEXT 📖 仅展示
-- SQL 语句执行成功
🔥 易错: 删除数据库是不可逆操作!数据库中的所有表、数据、视图将永久丢失。生产环境务必先备份再删除。


8. 字符集与排序规则

(1) 常用字符编码

编码 说明 推荐场景
UTF8 Unicode,支持全球所有语言 所有项目(推荐)
LATIN1 西欧语言 旧系统兼容
EUC_JP 日语 日本旧系统
SQL_ASCII 无编码转换 纯 ASCII 数据

(2) 排序规则对比

排序规则 行为 示例
en_US.utf8 英文排序,大小写敏感 A, a, B, b
C 字节序排序,最快 A, B, a, b
en_US.utf8(with ICU) 支持更灵活的排序 可忽略大小写/重音

▶ 示例:查看系统支持的编码和排序规则

SQL
-- List available encodings
SELECT name, description FROM pg_encodings LIMIT 10;

-- List available collations
SELECT name, locale FROM pg_collation LIMIT 10;

输出:

TEXT 📖 仅展示
 id | name     | value 
----+----------+-------
  1 | example  | 42
(1 row)

▶ 示例:排序规则对查询结果的影响

SQL
-- Create a test table with text data
CREATE TABLE sort_test (name TEXT);
INSERT INTO sort_test VALUES ('apple'), ('Banana'), ('cherry'), ('Apple');

-- Sort with C locale (byte order: uppercase first)
SELECT name FROM sort_test ORDER BY name COLLATE "C";

-- Sort with en_US.utf8 (dictionary order: case-insensitive within same letter)
SELECT name FROM sort_test ORDER BY name COLLATE "en_US.utf8";

-- Clean up
DROP TABLE sort_test;

输出:

TEXT 📖 仅展示
-- C locale:
  Apple
  Banana
  apple
  cherry

-- en_US.utf8:
  apple
  Apple
  Banana
  cherry

9. psql 数据库管理元命令

命令 等价 SQL 说明
\l SELECT * FROM pg_database 列出所有数据库
\l+ 同上,含表空间/大小 详细列出数据库
\c dbname - 切换到指定数据库
\conninfo - 显示当前连接信息

▶ 示例:psql 管理数据库

BASH
# List all databases
\l

# Switch to shop_dev database
\c shop_dev

# Check current connection
\conninfo

# Switch back to postgres database
\c postgres

输出:

TEXT 📖 仅展示
# 命令执行成功

10. 完整示例:三环境数据库搭建

SQL
-- ============================================
-- Complete example: set up dev/staging/prod databases
-- For an e-commerce project
-- ============================================

-- Step 1: Connect to postgres (maintenance database)
\c postgres

-- Step 2: Create dev database with English locale
CREATE DATABASE shop_dev
    WITH ENCODING = 'UTF8'
    LC_COLLATE = 'en_US.utf8'
    LC_CTYPE = 'en_US.utf8'
    OWNER = devuser
    CONNECTION LIMIT = 50;

-- Step 3: Create staging database (same config as prod)
CREATE DATABASE shop_staging
    WITH ENCODING = 'UTF8'
    LC_COLLATE = 'en_US.utf8'
    LC_CTYPE = 'en_US.utf8'
    OWNER = devuser
    CONNECTION LIMIT = 50;

-- Step 4: Create prod database with connection limit
CREATE DATABASE shop_prod
    WITH ENCODING = 'UTF8'
    LC_COLLATE = 'en_US.utf8'
    LC_CTYPE = 'en_US.utf8'
    OWNER = devuser
    CONNECTION LIMIT = 200;

-- Step 5: Set default search_path for prod
ALTER DATABASE shop_prod SET search_path TO public, admin;

-- Step 6: Verify all databases created
SELECT datname, pg_encoding_to_char(encoding) AS encoding,
       datcollate, datctype, datconnlimit
FROM pg_database
WHERE datname LIKE 'shop_%'
ORDER BY datname;

输出:

TEXT 📖 仅展示
   datname    | encoding |  datcollate  |   datctype   | datconnlimit
--------------+----------+--------------+--------------+-------------
 shop_dev     | UTF8     | en_US.utf8   | en_US.utf8   |           50
 shop_prod    | UTF8     | en_US.utf8   | en_US.utf8   |          200
 shop_staging | UTF8     | en_US.utf8   | en_US.utf8   |           50

❓ 常见问题

Q 一个 PostgreSQL 实例最多能创建多少个数据库?
A 理论上没有硬性限制,但每个数据库都会占用一定的系统目录空间。实际建议单个实例不超过 100 个数据库。如果需要更多隔离,考虑使用 Schema 代替。
Q 创建数据库时报错"source database is being accessed by other users"怎么办?
A 这是因为 template1 正在被其他连接使用。解决方法:1)终止所有连接 template1 的会话;2)或使用 TEMPLATE = template0 代替。
Q LC_COLLATE 和 LC_CTYPE 有什么区别?
A LC_COLLATE 控制字符串排序顺序(ORDER BY 的结果),LC_CTYPE 控制字符分类(大小写转换、什么是字母等)。大多数情况下两者设置相同即可。
Q 创建数据库后能修改字符编码吗?
A 不能直接修改。必须用 pg_dump 导出数据,创建新编码的数据库,再用 pg_restore 导入。这也是为什么建议一开始就用 UTF8——它支持所有语言。
Q 如何查看当前数据库的大小?
A 使用 SELECT pg_size_pretty(pg_database_size('shop_dev')) 查看单个数据库大小,或 \l+ 查看所有数据库大小。
Q dev 和 prod 能不能共用一个数据库?
A 强烈不建议。开发中的操作(DROP TABLE、批量 DELETE)可能误删生产数据。最小化要求:dev 和 prod 用不同数据库,最好用不同 PG 实例。

📖 小节


📝 作业

  1. 基础题(难度⭐):创建一个名为 my_bookstore 的数据库,使用 UTF8 编码,然后用 \l 验证创建成功,最后删除它。

  2. 进阶题(难度⭐⭐):先在 template1 中安装 uuid-ossp 扩展,然后创建一个新数据库 test_template,验证新数据库是否自动继承了 uuid-ossp 扩展。

  3. 挑战题(难度⭐⭐⭐):创建两个数据库,分别使用 Cen_US.utf8 排序规则。在两个数据库中分别创建相同的表并插入数据 'apple''Banana''cherry''Apple',用 ORDER BY 查询对比排序结果的差异,解释为什么不同。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏