Docker PostgreSQL 操作指南与 SQL 语法速查
技术随笔
Docker PostgreSQL 操作指南与 SQL 语法速查
一、Docker 中操作 PostgreSQL
1.1 容器管理
# 查看所有运行中的容器
docker ps
# 查看指定容器
docker ps --format "{{.Names}}" | findstr postgres
# 查看容器日志
docker logs blog-postgres
# 进入容器内部
docker exec -it blog-postgres bash
# 启动/停止容器
docker start blog-postgres
docker stop blog-postgres
# 删除容器(数据卷保留,数据不丢)
docker rm blog-postgres
1.2 连接数据库
# 方式一:直接执行 SQL(推荐)
docker exec blog-postgres psql -U postgres -d blog -c "SQL 语句"
# 方式二:进入交互式命令行
docker exec -it blog-postgres psql -U postgres -d blog
# 连接后看到如下提示符
blog=#
1.3 常用 psql 命令
在交互式命令行(blog=#)中输入:
-- 查看所有数据库
\l
-- 切换到指定数据库
\c blog
-- 查看所有表
\dt
-- 查看表结构(字段名、类型、约束)
\d user_models
-- 查看表的完整信息(包括索引、触发器)
\d+ user_models
-- 查看所有索引
\di
-- 查看当前用户
\du
-- 查看帮助
\h
-- 查看某个命令的帮助
\h SELECT
-- 设置输出格式(对齐/无对齐)
\x on -- 扩展显示(字段竖排)
\x off -- 标准显示(表格横排)
-- 退出
\q
1.4 实用示例
# 查看用户表所有数据
docker exec blog-postgres psql -U postgres -d blog -c "SELECT * FROM user_models;"
# 查看用户表(竖排显示,字段多时更方便)
docker exec blog-postgres psql -U postgres -d blog -c "\x on" -c "SELECT * FROM user_models;"
# 统计表数据量
docker exec blog-postgres psql -U postgres -d blog -c "
SELECT
relname AS table_name,
n_live_tup AS row_count
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
"
二、数据库与表管理
2.1 数据库操作
-- 创建数据库
CREATE DATABASE blog;
-- 删除数据库(不可恢复!)
DROP DATABASE blog;
-- 重命名数据库
ALTER DATABASE blog RENAME TO blog_v2;
-- 查看当前数据库
SELECT current_database();
-- 查看数据库大小
SELECT pg_database_size('blog');
SELECT pg_size_pretty(pg_database_size('blog'));
2.2 表操作
-- 创建表
CREATE TABLE articles (
id BIGSERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
slug VARCHAR(255) UNIQUE NOT NULL,
body TEXT,
author_id BIGINT REFERENCES user_models(id),
category VARCHAR(100),
tags TEXT[],
published BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 删除表
DROP TABLE articles;
-- 清空表数据(保留表结构)
TRUNCATE TABLE articles;
-- 重命名表
ALTER TABLE articles RENAME TO posts;
-- 查看表结构
\d articles
2.3 字段操作
-- 添加字段
ALTER TABLE user_models ADD COLUMN phone VARCHAR(20);
-- 删除字段
ALTER TABLE user_models DROP COLUMN phone;
-- 修改字段类型
ALTER TABLE user_models ALTER COLUMN phone TYPE VARCHAR(30);
-- 修改字段名
ALTER TABLE user_models RENAME COLUMN phone TO mobile;
-- 设置默认值
ALTER TABLE user_models ALTER COLUMN role SET DEFAULT 1;
-- 删除默认值
ALTER TABLE user_models ALTER COLUMN role DROP DEFAULT;
-- 设置非空约束
ALTER TABLE user_models ALTER COLUMN username SET NOT NULL;
-- 取消非空约束
ALTER TABLE user_models ALTER COLUMN username DROP NOT NULL;
2.4 索引操作
-- 创建索引
CREATE INDEX idx_articles_author ON articles(author_id);
CREATE INDEX idx_articles_published ON articles(published);
CREATE UNIQUE INDEX idx_articles_slug ON articles(slug);
-- 复合索引(多字段)
CREATE INDEX idx_articles_category_published ON articles(category, published);
-- 删除索引
DROP INDEX idx_articles_author;
-- 查看索引
\d articles
-- 或
SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'articles';
三、数据操作(CRUD)
3.1 插入数据
-- 插入单条
INSERT INTO user_models (username, password, nickname, role, created_at)
VALUES ('admin', '哈希值', '管理员', 1, NOW());
-- 插入多条
INSERT INTO user_models (username, password, nickname, role, created_at)
VALUES
('user1', 'hash1', '用户一', 2, NOW()),
('user2', 'hash2', '用户二', 2, NOW());
-- 插入并返回整行
INSERT INTO user_models (username, password, nickname, role)
VALUES ('test', 'hash', '测试', 2)
RETURNING *;
-- 插入并只返回 ID
INSERT INTO user_models (username, password, nickname)
VALUES ('test', 'hash', '测试')
RETURNING id;
-- 从查询结果插入
INSERT INTO user_models (username, password, nickname, role)
SELECT username, password, nickname, 2 FROM old_users WHERE active = true;
3.2 查询数据
-- 查询所有列
SELECT * FROM user_models;
-- 查询指定列
SELECT id, username, nickname, role FROM user_models;
-- 条件查询
SELECT * FROM user_models WHERE role = 1;
SELECT * FROM articles WHERE published = true;
-- 多条件
SELECT * FROM articles
WHERE category = '系列教程'
AND published = true
AND created_at >= '2024-01-01';
-- 模糊查询
SELECT * FROM articles WHERE title LIKE '%Dioxus%';
SELECT * FROM articles WHERE title ILIKE '%dioxus%'; -- 不区分大小写
-- 排序
SELECT * FROM articles ORDER BY created_at DESC; -- 最新在前
SELECT * FROM articles ORDER BY created_at ASC; -- 最早在前
SELECT * FROM articles ORDER BY category, created_at DESC;
-- 分页
SELECT * FROM articles
ORDER BY created_at DESC
LIMIT 10 OFFSET 0; -- 第1页,每页10条
SELECT * FROM articles
ORDER BY created_at DESC
LIMIT 10 OFFSET 10; -- 第2页
-- 聚合统计
SELECT COUNT(*) FROM articles;
SELECT category, COUNT(*) FROM articles GROUP BY category;
SELECT category, COUNT(*) as cnt FROM articles
GROUP BY category ORDER BY cnt DESC;
-- 去重
SELECT DISTINCT category FROM articles;
SELECT COUNT(DISTINCT category) FROM articles;
-- 限制返回条数
SELECT * FROM articles LIMIT 5;
3.3 更新数据
-- 更新单个字段
UPDATE user_models SET nickname = '新昵称' WHERE id = 1;
-- 更新多个字段
UPDATE user_models
SET nickname = '新昵称',
email = 'new@email.com',
updated_at = NOW()
WHERE id = 1;
-- 更新并返回更新后的数据
UPDATE user_models
SET nickname = '新昵称'
WHERE id = 1
RETURNING *;
-- 条件更新
UPDATE articles
SET published = true
WHERE category = '系列教程'
AND created_at < '2024-06-01';
-- 使用表达式更新
UPDATE articles
SET view_count = view_count + 1
WHERE id = 100;
3.4 删除数据
-- 删除指定行
DELETE FROM user_models WHERE id = 1;
-- 条件删除
DELETE FROM articles WHERE published = false AND created_at < '2023-01-01';
-- 删除并返回删除的数据
DELETE FROM user_models WHERE id = 1 RETURNING *;
-- 清空表(比 DELETE 快,但无法回滚)
TRUNCATE TABLE articles;
-- 清空表并重置自增 ID
TRUNCATE TABLE articles RESTART IDENTITY;
四、用户管理
4.1 创建管理员账号
# 先确认表结构
docker exec blog-postgres psql -U postgres -d blog -c "\d user_models"
-- role 字段说明(根据项目 entity.rs 中的定义)
-- 0 = 普通用户
-- 1 = 管理员
-- 其他值根据项目定义
-- 插入管理员账号
-- 注意:password 字段需要 bcrypt 哈希值
INSERT INTO user_models (username, password, nickname, role, created_at)
VALUES ('admin', '这里放bcrypt哈希', '管理员', 1, NOW());
-- 查看已创建的用户
SELECT id, username, nickname, role, created_at FROM user_models;
4.2 生成 bcrypt 密码哈希
方法一:使用在线工具(推荐,方便快捷)
- 访问 https://bcrypt.online/
- 输入密码,生成哈希
方法二:使用 Python(如果安装了 bcrypt 库)
import bcrypt
password = b"你的密码"
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
print(hashed.decode())
方法三:使用 Node.js
const bcrypt = require('bcryptjs');
const hash = bcrypt.hashSync('你的密码', 12);
console.log(hash);
4.3 修改密码
-- 直接更新密码字段(需要 bcrypt 哈希值)
UPDATE user_models
SET password = '新的bcrypt哈希'
WHERE username = 'admin';
-- 修改用户角色
UPDATE user_models
SET role = 1
WHERE username = 'admin';
五、实用查询
5.1 项目相关查询
-- 查看所有文章
SELECT id, title, slug, category, published, created_at FROM articles
ORDER BY created_at DESC;
-- 查看某个分类的文章数
SELECT category, COUNT(*) as article_count
FROM articles GROUP BY category;
-- 查看文章标签统计
SELECT unnest(tags) as tag, COUNT(*) as cnt
FROM articles
GROUP BY tag
ORDER BY cnt DESC
LIMIT 20;
-- 查看最近评论
SELECT c.*, a.title
FROM comments c
JOIN articles a ON c.article_id = a.id
ORDER BY c.created_at DESC
LIMIT 10;
-- 查看用户登录记录
SELECT * FROM user_models
ORDER BY updated_at DESC
LIMIT 10;
5.2 数据库维护
-- 查看数据库大小
SELECT pg_size_pretty(pg_database_size('blog'));
-- 查看表大小
SELECT
relname,
pg_size_pretty(pg_total_relation_size(relid))
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;
-- 查看当前连接数
SELECT COUNT(*) FROM pg_stat_activity WHERE datname = 'blog';
-- 查看慢查询(运行超过 5 秒的查询)
SELECT
pid, now() - pg_stat_activity.query_start AS duration,
query, state
FROM pg_stat_activity
WHERE state != 'idle'
AND now() - pg_stat_activity.query_start > interval '5 seconds'
ORDER BY duration DESC;
-- 清理和分析(更新统计信息)
ANALYZE;
-- 清理死元组(类似碎片整理)
VACUUM;
VACUUM FULL; -- 更彻底,但会锁表
六、常见错误与解决
| 错误信息 | 原因 | 解决 |
|---------|------|------|
| database "xxx" does not exist | 数据库不存在 | CREATE DATABASE xxx; |
| relation "xxx" does not exist | 表不存在 | 检查表名,先运行数据库迁移 |
| column "xxx" does not exist | 字段不存在 | 检查字段名,大小写敏感 |
| violates foreign key constraint | 外键冲突 | 先插入关联表的数据 |
| duplicate key value violates unique constraint | 唯一键冲突 | 检查是否已存在相同数据 |
| invalid input syntax for type smallint | 类型不匹配 | 检查字段类型,'admin' 不能存入 smallint |
| password authentication failed | 密码错误 | 检查连接字符串的用户名密码 |
| Connection refused | 数据库未启动 | docker start blog-postgres |
七、快速参考
# 最常用命令速查
# 1. 查看所有用户
docker exec blog-postgres psql -U postgres -d blog -c "SELECT * FROM user_models;"
# 2. 创建管理员(先获取 bcrypt 哈希)
docker exec blog-postgres psql -U postgres -d blog -c "
INSERT INTO user_models (username, password, nickname, role, created_at)
VALUES ('admin', '你的bcrypt哈希', '管理员', 1, NOW());"
# 3. 查看所有文章
docker exec blog-postgres psql -U postgres -d blog -c "SELECT id, title, slug, published FROM articles;"
# 4. 进入交互式命令行
docker exec -it blog-postgres psql -U postgres -d blog
# 5. 退出交互式
\q
PostgreSQLDockerSQL数据库运维