PostgreSQL: PostgreSQL数据库创建与管理
最后更新:2026-08-26
数据库是 PostgreSQL 中最顶层的组织单元——就像一个文件柜,里面可以放很多抽屉(表)。
1. 你将学到
- CREATE DATABASE 创建数据库
- DROP DATABASE 删除数据库
- ALTER DATABASE 修改数据库属性
- 模板数据库(template0 / template1)
- 字符集与排序规则
- psql 元命令:\l / \c
2. 一个开发运维的真实故事
(1) 痛点:三个环境三种字符集
Charlie 需要为电商项目创建 3 个数据库,分别对应 dev / staging / prod 环境:
- dev 环境:英文排序规则(开发方便)
- staging 环境:UTF8 + 英文排序(与生产一致)
- prod 环境:UTF8 + 特定排序规则(中东市场,需要阿拉伯语支持)
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) 收益
- 每个环境独立数据库,数据互不干扰
- 字符集统一为 UTF8,支持多语言数据
- 排序规则匹配业务需求,查询结果顺序正确
3. 数据库基础概念
(1) PostgreSQL 的组织层级
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 实例。
📖 小节
- CREATE DATABASE 创建数据库,支持指定编码/排序规则/模板/所有者/连接限制
- template0 是纯净模板(不可修改),template1 是可定制模板(默认模板)
- 在 template1 中预装扩展,新数据库自动继承
- ALTER DATABASE 可重命名、设置参数、修改所有者
- DROP DATABASE 不可逆,IF EXISTS 防报错,WITH (FORCE) 强制断开连接
- 推荐始终使用 UTF8 编码,排序规则根据业务需求选择
- psql 元命令
\l列出数据库、\c切换数据库、\conninfo显示连接信息
📝 作业
-
基础题(难度⭐):创建一个名为
my_bookstore的数据库,使用 UTF8 编码,然后用\l验证创建成功,最后删除它。 -
进阶题(难度⭐⭐):先在 template1 中安装
uuid-ossp扩展,然后创建一个新数据库test_template,验证新数据库是否自动继承了 uuid-ossp 扩展。 -
挑战题(难度⭐⭐⭐):创建两个数据库,分别使用
C和en_US.utf8排序规则。在两个数据库中分别创建相同的表并插入数据'apple'、'Banana'、'cherry'、'Apple',用 ORDER BY 查询对比排序结果的差异,解释为什么不同。