29 KiB
29 KiB
PostgreSQL 使用文档
目录
一、安装 PostgreSQL
1.1 macOS 安装
方法一:使用 Homebrew(推荐)
# 安装 Homebrew(如果还没有)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安装 PostgreSQL
brew install postgresql@15
# 启动 PostgreSQL 服务
brew services start postgresql@15
# 或者手动启动
pg_ctl -D /usr/local/var/postgresql@15 start
方法二:使用 Postgres.app(图形化工具)
- 访问 https://postgresapp.com/
- 下载并安装 Postgres.app
- 打开应用,点击 "Initialize" 初始化数据库
方法三:使用官方安装包
- 访问 https://www.postgresql.org/download/macosx/
- 下载官方安装包
- 按照安装向导完成安装
1.2 Linux 安装
Ubuntu/Debian
# 更新包列表
sudo apt update
# 安装 PostgreSQL
sudo apt install postgresql postgresql-contrib
# 启动服务
sudo systemctl start postgresql
# 设置开机自启
sudo systemctl enable postgresql
# 查看服务状态
sudo systemctl status postgresql
CentOS/RHEL/Fedora
# CentOS/RHEL 7+
sudo yum install postgresql-server postgresql-contrib
# 或者使用 dnf (Fedora/CentOS 8+)
sudo dnf install postgresql-server postgresql-contrib
# 初始化数据库
sudo postgresql-setup --initdb
# 启动服务
sudo systemctl start postgresql
sudo systemctl enable postgresql
Arch Linux
# 安装
sudo pacman -S postgresql
# 初始化数据库
sudo -u postgres initdb -D /var/lib/postgres/data
# 启动服务
sudo systemctl start postgresql
sudo systemctl enable postgresql
1.3 验证安装
# 检查 PostgreSQL 版本
psql --version
# 或者
postgres --version
# 检查服务状态(Linux)
sudo systemctl status postgresql
1.4 初始配置
设置 postgres 用户密码
# 切换到 postgres 用户(Linux)
sudo -u postgres psql
# 或者直接连接(macOS)
psql -U postgres
# 在 psql 中设置密码
ALTER USER postgres PASSWORD 'your_password';
创建新用户和数据库
# 使用 postgres 用户登录
psql -U postgres
# 创建新用户
CREATE USER myuser WITH PASSWORD 'mypassword';
# 创建数据库
CREATE DATABASE mydb OWNER myuser;
# 授予权限
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
# 退出
\q
二、基本操作
2.1 连接数据库
# 使用默认用户连接默认数据库
psql
# 指定用户和数据库
psql -U username -d database_name
# 指定主机和端口
psql -h localhost -p 5432 -U username -d database_name
# 使用连接字符串
psql postgresql://username:password@localhost:5432/database_name
2.2 psql 常用命令
-- 查看所有数据库
\l
-- 或者
\list
-- 连接到指定数据库
\c database_name
-- 或者
\connect database_name
-- 查看当前数据库
SELECT current_database();
-- 查看所有表
\dt
-- 查看表结构
\d table_name
-- 查看表详细信息(包括索引、约束等)
\d+ table_name
-- 查看所有用户
\du
-- 查看当前用户
SELECT current_user;
-- 查看帮助
\?
-- 查看 SQL 命令帮助
\h
-- 查看特定命令帮助
\h SELECT
-- 退出 psql
\q
-- 或者
exit
-- 清屏
\! clear -- Linux
\! cls -- Windows
-- 执行外部 SQL 文件
\i /path/to/file.sql
-- 将查询结果导出到文件
\o /path/to/output.txt
SELECT * FROM users;
\o
-- 显示执行时间
\timing
-- 显示查询结果(表格格式)
\x -- 切换显示模式(横向/纵向)
-- 查看命令历史
\s
-- 保存命令历史到文件
\s /path/to/history.sql
三、数据库操作
3.1 创建数据库
-- 基本语法
CREATE DATABASE database_name;
-- 指定所有者
CREATE DATABASE database_name OWNER username;
-- 指定编码
CREATE DATABASE database_name
WITH ENCODING 'UTF8';
-- 完整示例
CREATE DATABASE vestmind
OWNER myuser
ENCODING 'UTF8'
LC_COLLATE 'zh_CN.UTF-8'
LC_CTYPE 'zh_CN.UTF-8'
TEMPLATE template0;
3.2 查看数据库
-- 查看所有数据库
SELECT datname FROM pg_database;
-- 查看数据库详细信息
\l
-- 或者
\list
-- 查看当前数据库
SELECT current_database();
3.3 删除数据库
-- 删除数据库(需要先断开所有连接)
DROP DATABASE database_name;
-- 强制删除(终止所有连接)
-- 首先终止所有连接
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'database_name';
-- 然后删除
DROP DATABASE database_name;
3.4 修改数据库
-- 重命名数据库
ALTER DATABASE old_name RENAME TO new_name;
-- 修改所有者
ALTER DATABASE database_name OWNER TO new_owner;
-- 修改连接限制
ALTER DATABASE database_name WITH CONNECTION LIMIT 10;
3.5 备份和恢复
# 备份数据库
pg_dump -U username -d database_name > backup.sql
# 备份为自定义格式(压缩)
pg_dump -U username -d database_name -F c -f backup.dump
# 备份所有数据库
pg_dumpall -U username > all_databases.sql
# 恢复数据库
psql -U username -d database_name < backup.sql
# 恢复自定义格式备份
pg_restore -U username -d database_name backup.dump
# 只恢复表结构
pg_dump -U username -d database_name -s > schema_only.sql
# 只恢复数据
pg_dump -U username -d database_name -a > data_only.sql
四、表操作
4.1 创建表
基本语法
CREATE TABLE table_name (
column1 datatype constraint,
column2 datatype constraint,
...
);
数据类型
数值类型:
SMALLINT -- 2字节,-32768 到 32767
INTEGER -- 4字节,-2147483648 到 2147483647
BIGINT -- 8字节,大整数
DECIMAL(p,s) -- 精确数值,p=精度,s=小数位数
NUMERIC(p,s) -- 同 DECIMAL
REAL -- 4字节,单精度浮点数
DOUBLE PRECISION -- 8字节,双精度浮点数
SERIAL -- 自增整数(1 到 2147483647)
BIGSERIAL -- 大自增整数
字符串类型:
VARCHAR(n) -- 可变长度字符串,最大n字符
CHAR(n) -- 固定长度字符串,n字符
TEXT -- 无限长度字符串
日期时间类型:
DATE -- 日期(年-月-日)
TIME -- 时间(时:分:秒)
TIMESTAMP -- 日期和时间
TIMESTAMPTZ -- 带时区的时间戳
INTERVAL -- 时间间隔
布尔类型:
BOOLEAN -- true/false
JSON 类型:
JSON -- JSON 数据
JSONB -- 二进制 JSON(推荐,性能更好)
约束
-- 主键约束
id INTEGER PRIMARY KEY
-- 或者
id INTEGER,
PRIMARY KEY (id)
-- 外键约束
user_id INTEGER REFERENCES users(id)
-- 或者
user_id INTEGER,
FOREIGN KEY (user_id) REFERENCES users(id)
-- 唯一约束
email VARCHAR(100) UNIQUE
-- 或者
email VARCHAR(100),
UNIQUE (email)
-- 非空约束
name VARCHAR(50) NOT NULL
-- 检查约束
age INTEGER CHECK (age > 0 AND age < 150)
-- 默认值
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-- 自增(使用 SERIAL)
id SERIAL PRIMARY KEY
完整示例
-- 创建用户表
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE,
phone VARCHAR(20) UNIQUE,
password_hash VARCHAR(255) NOT NULL,
nickname VARCHAR(50),
avatar_url VARCHAR(255),
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
last_login_at TIMESTAMP,
CHECK (status IN ('active', 'inactive', 'deleted'))
);
-- 创建账户表
CREATE TABLE accounts (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
type VARCHAR(20) NOT NULL,
currency VARCHAR(10) NOT NULL DEFAULT 'CNY',
description TEXT,
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CHECK (type IN ('stock', 'fund', 'cash', 'mixed')),
CHECK (status IN ('active', 'archived', 'deleted'))
);
-- 创建持仓表
CREATE TABLE positions (
id BIGSERIAL PRIMARY KEY,
account_id BIGINT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
symbol VARCHAR(20) NOT NULL,
name VARCHAR(100) NOT NULL,
market VARCHAR(20) NOT NULL,
shares DECIMAL(18, 4) NOT NULL DEFAULT 0,
cost_price DECIMAL(18, 4) NOT NULL,
current_price DECIMAL(18, 4),
currency VARCHAR(10) NOT NULL DEFAULT 'CNY',
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(account_id, symbol, market),
CHECK (shares >= 0),
CHECK (status IN ('active', 'suspended', 'delisted'))
);
4.2 查看表
-- 查看所有表
\dt
-- 查看表结构
\d table_name
-- 查看表详细信息
\d+ table_name
-- 查看表的所有列
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = 'users';
-- 查看表的约束
SELECT constraint_name, constraint_type
FROM information_schema.table_constraints
WHERE table_name = 'users';
4.3 修改表
-- 添加列
ALTER TABLE table_name
ADD COLUMN column_name datatype;
-- 示例
ALTER TABLE users
ADD COLUMN age INTEGER;
-- 删除列
ALTER TABLE table_name
DROP COLUMN column_name;
-- 修改列类型
ALTER TABLE table_name
ALTER COLUMN column_name TYPE new_datatype;
-- 示例
ALTER TABLE users
ALTER COLUMN age TYPE SMALLINT;
-- 重命名列
ALTER TABLE table_name
RENAME COLUMN old_name TO new_name;
-- 添加约束
ALTER TABLE table_name
ADD CONSTRAINT constraint_name constraint_definition;
-- 示例:添加外键
ALTER TABLE accounts
ADD CONSTRAINT fk_user
FOREIGN KEY (user_id) REFERENCES users(id);
-- 删除约束
ALTER TABLE table_name
DROP CONSTRAINT constraint_name;
-- 重命名表
ALTER TABLE old_table_name
RENAME TO new_table_name;
-- 设置列的默认值
ALTER TABLE table_name
ALTER COLUMN column_name SET DEFAULT default_value;
-- 删除列的默认值
ALTER TABLE table_name
ALTER COLUMN column_name DROP DEFAULT;
-- 设置列非空
ALTER TABLE table_name
ALTER COLUMN column_name SET NOT NULL;
-- 取消列非空
ALTER TABLE table_name
ALTER COLUMN column_name DROP NOT NULL;
4.4 删除表
-- 删除表
DROP TABLE table_name;
-- 删除表(如果存在)
DROP TABLE IF EXISTS table_name;
-- 级联删除(删除表及其依赖对象)
DROP TABLE table_name CASCADE;
-- 清空表数据(保留表结构)
TRUNCATE TABLE table_name;
-- 清空表数据并重置自增序列
TRUNCATE TABLE table_name RESTART IDENTITY;
五、数据操作(CRUD)
5.1 插入数据(INSERT)
基本语法
-- 插入单行数据
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);
-- 插入多行数据
INSERT INTO table_name (column1, column2, ...)
VALUES
(value1, value2, ...),
(value3, value4, ...),
(value5, value6, ...);
-- 插入所有列(按表定义顺序)
INSERT INTO table_name
VALUES (value1, value2, ...);
-- 从查询结果插入
INSERT INTO table_name (column1, column2, ...)
SELECT column1, column2, ...
FROM other_table
WHERE condition;
示例
-- 插入用户
INSERT INTO users (username, email, password_hash, nickname)
VALUES ('john_doe', 'john@example.com', 'hashed_password', 'John');
-- 插入多用户
INSERT INTO users (username, email, password_hash, nickname)
VALUES
('alice', 'alice@example.com', 'hash1', 'Alice'),
('bob', 'bob@example.com', 'hash2', 'Bob'),
('charlie', 'charlie@example.com', 'hash3', 'Charlie');
-- 使用 RETURNING 返回插入的数据
INSERT INTO users (username, email, password_hash)
VALUES ('david', 'david@example.com', 'hash4')
RETURNING id, username, created_at;
-- 插入时处理冲突(ON CONFLICT)
INSERT INTO users (username, email, password_hash)
VALUES ('john_doe', 'john@example.com', 'new_hash')
ON CONFLICT (username)
DO UPDATE SET
email = EXCLUDED.email,
password_hash = EXCLUDED.password_hash,
updated_at = CURRENT_TIMESTAMP;
5.2 查询数据(SELECT)
基本语法
-- 查询所有列
SELECT * FROM table_name;
-- 查询指定列
SELECT column1, column2, ... FROM table_name;
-- 条件查询
SELECT * FROM table_name WHERE condition;
-- 排序
SELECT * FROM table_name ORDER BY column_name ASC/DESC;
-- 限制结果数量
SELECT * FROM table_name LIMIT number;
-- 跳过结果
SELECT * FROM table_name OFFSET number;
-- 组合使用
SELECT * FROM table_name
WHERE condition
ORDER BY column_name DESC
LIMIT 10 OFFSET 20;
示例
-- 查询所有用户
SELECT * FROM users;
-- 查询指定列
SELECT id, username, email, created_at FROM users;
-- 条件查询
SELECT * FROM users WHERE status = 'active';
-- 多条件查询
SELECT * FROM users
WHERE status = 'active' AND created_at > '2024-01-01';
-- 模糊查询
SELECT * FROM users WHERE username LIKE 'john%';
-- IN 查询
SELECT * FROM users WHERE id IN (1, 2, 3, 4, 5);
-- BETWEEN 查询
SELECT * FROM users
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';
-- 排序
SELECT * FROM users ORDER BY created_at DESC;
-- 多列排序
SELECT * FROM users
ORDER BY status ASC, created_at DESC;
-- 限制数量
SELECT * FROM users LIMIT 10;
-- 分页查询
SELECT * FROM users
ORDER BY id
LIMIT 10 OFFSET 0; -- 第1页
SELECT * FROM users
ORDER BY id
LIMIT 10 OFFSET 10; -- 第2页
-- 去重
SELECT DISTINCT status FROM users;
-- 聚合函数
SELECT
COUNT(*) as total_users,
COUNT(DISTINCT status) as status_count,
MAX(created_at) as latest_user,
MIN(created_at) as earliest_user
FROM users;
-- 分组查询
SELECT status, COUNT(*) as count
FROM users
GROUP BY status;
-- HAVING 子句
SELECT status, COUNT(*) as count
FROM users
GROUP BY status
HAVING COUNT(*) > 10;
5.3 更新数据(UPDATE)
基本语法
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
示例
-- 更新单列
UPDATE users
SET nickname = 'Johnny'
WHERE id = 1;
-- 更新多列
UPDATE users
SET
nickname = 'Johnny',
email = 'newemail@example.com',
updated_at = CURRENT_TIMESTAMP
WHERE id = 1;
-- 使用表达式更新
UPDATE positions
SET current_price = current_price * 1.1
WHERE symbol = '600519';
-- 基于子查询更新
UPDATE accounts
SET status = 'archived'
WHERE user_id IN (
SELECT id FROM users WHERE status = 'deleted'
);
-- 更新时返回结果
UPDATE users
SET nickname = 'NewName'
WHERE id = 1
RETURNING id, username, nickname;
5.4 删除数据(DELETE)
基本语法
DELETE FROM table_name WHERE condition;
示例
-- 删除指定记录
DELETE FROM users WHERE id = 1;
-- 删除多条记录
DELETE FROM users WHERE status = 'deleted';
-- 删除所有记录(危险!)
DELETE FROM table_name;
-- 使用子查询删除
DELETE FROM accounts
WHERE user_id IN (
SELECT id FROM users WHERE status = 'deleted'
);
-- 删除时返回结果
DELETE FROM users
WHERE id = 1
RETURNING id, username;
5.5 连接查询(JOIN)
-- 内连接
SELECT u.username, a.name as account_name
FROM users u
INNER JOIN accounts a ON u.id = a.user_id;
-- 左连接
SELECT u.username, a.name as account_name
FROM users u
LEFT JOIN accounts a ON u.id = a.user_id;
-- 右连接
SELECT u.username, a.name as account_name
FROM users u
RIGHT JOIN accounts a ON u.id = a.user_id;
-- 全外连接
SELECT u.username, a.name as account_name
FROM users u
FULL OUTER JOIN accounts a ON u.id = a.user_id;
-- 多表连接
SELECT
u.username,
a.name as account_name,
p.symbol,
p.shares
FROM users u
INNER JOIN accounts a ON u.id = a.user_id
INNER JOIN positions p ON a.id = p.account_id
WHERE u.status = 'active';
5.6 子查询
-- 标量子查询
SELECT
username,
(SELECT COUNT(*) FROM accounts WHERE user_id = users.id) as account_count
FROM users;
-- EXISTS 子查询
SELECT * FROM users u
WHERE EXISTS (
SELECT 1 FROM accounts a WHERE a.user_id = u.id
);
-- IN 子查询
SELECT * FROM users
WHERE id IN (
SELECT DISTINCT user_id FROM accounts
);
-- 相关子查询
SELECT
u.*,
(SELECT COUNT(*) FROM accounts WHERE user_id = u.id) as account_count
FROM users u;
六、索引操作
6.1 索引的作用
- 提高查询速度
- 加速排序和分组
- 强制唯一性约束
- 加速表连接
6.2 创建索引
基本语法
-- 创建单列索引
CREATE INDEX index_name ON table_name (column_name);
-- 创建多列索引
CREATE INDEX index_name ON table_name (column1, column2, ...);
-- 创建唯一索引
CREATE UNIQUE INDEX index_name ON table_name (column_name);
-- 创建部分索引(带条件)
CREATE INDEX index_name ON table_name (column_name)
WHERE condition;
-- 创建表达式索引
CREATE INDEX index_name ON table_name (expression);
示例
-- 基本索引
CREATE INDEX idx_users_email ON users (email);
-- 唯一索引
CREATE UNIQUE INDEX idx_users_username ON users (username);
-- 多列索引
CREATE INDEX idx_transactions_user_date ON transactions (user_id, date);
-- 降序索引
CREATE INDEX idx_users_created_desc ON users (created_at DESC);
-- 部分索引(只索引活跃用户)
CREATE INDEX idx_users_active_email ON users (email)
WHERE status = 'active';
-- 表达式索引
CREATE INDEX idx_users_lower_email ON users (LOWER(email));
-- 文本搜索索引(GIN)
CREATE INDEX idx_transaction_thoughts_content
ON transaction_thoughts
USING gin(to_tsvector('jiebacfg', content));
6.3 查看索引
-- 查看表的所有索引
\d table_name
-- 或者
\di
-- 查看索引详细信息
SELECT
indexname,
indexdef
FROM pg_indexes
WHERE tablename = 'users';
-- 查看索引使用情况
SELECT
schemaname,
tablename,
indexname,
idx_scan as index_scans,
idx_tup_read as tuples_read,
idx_tup_fetch as tuples_fetched
FROM pg_stat_user_indexes
WHERE tablename = 'users';
6.4 删除索引
-- 删除索引
DROP INDEX index_name;
-- 删除索引(如果存在)
DROP INDEX IF EXISTS index_name;
-- 级联删除
DROP INDEX index_name CASCADE;
6.5 重建索引
-- 重建索引(释放空间,提高性能)
REINDEX INDEX index_name;
-- 重建表的所有索引
REINDEX TABLE table_name;
-- 重建数据库的所有索引
REINDEX DATABASE database_name;
6.6 索引类型
-- B-tree 索引(默认,最常用)
CREATE INDEX idx_name ON table_name (column_name);
-- Hash 索引(只支持等值查询)
CREATE INDEX idx_name ON table_name USING HASH (column_name);
-- GIN 索引(全文搜索、数组、JSONB)
CREATE INDEX idx_name ON table_name USING GIN (jsonb_column);
-- GiST 索引(几何数据、全文搜索)
CREATE INDEX idx_name ON table_name USING GIST (geometry_column);
-- BRIN 索引(大表,有序数据)
CREATE INDEX idx_name ON table_name USING BRIN (column_name);
6.7 索引维护
-- 分析表(更新统计信息,帮助查询优化器)
ANALYZE table_name;
-- 分析所有表
ANALYZE;
-- 查看索引大小
SELECT
pg_size_pretty(pg_relation_size('index_name')) as index_size;
-- 查看表和索引总大小
SELECT
pg_size_pretty(pg_total_relation_size('table_name')) as total_size;
七、高级查询
7.1 窗口函数
-- ROW_NUMBER:行号
SELECT
id,
username,
ROW_NUMBER() OVER (ORDER BY created_at) as row_num
FROM users;
-- RANK:排名(相同值相同排名,跳过后续排名)
SELECT
id,
username,
RANK() OVER (ORDER BY created_at DESC) as rank
FROM users;
-- DENSE_RANK:密集排名(相同值相同排名,不跳过)
SELECT
id,
username,
DENSE_RANK() OVER (ORDER BY created_at DESC) as dense_rank
FROM users;
-- 分组窗口函数
SELECT
user_id,
date,
amount,
SUM(amount) OVER (PARTITION BY user_id ORDER BY date) as running_total
FROM transactions;
7.2 公共表表达式(CTE)
-- 基本 CTE
WITH active_users AS (
SELECT * FROM users WHERE status = 'active'
)
SELECT * FROM active_users;
-- 递归 CTE
WITH RECURSIVE category_tree AS (
-- 基础查询
SELECT id, name, parent_id, 1 as level
FROM categories
WHERE parent_id IS NULL
UNION ALL
-- 递归查询
SELECT c.id, c.name, c.parent_id, ct.level + 1
FROM categories c
INNER JOIN category_tree ct ON c.parent_id = ct.id
)
SELECT * FROM category_tree;
7.3 集合操作
-- UNION:合并结果(去重)
SELECT column1 FROM table1
UNION
SELECT column1 FROM table2;
-- UNION ALL:合并结果(不去重)
SELECT column1 FROM table1
UNION ALL
SELECT column1 FROM table2;
-- INTERSECT:交集
SELECT column1 FROM table1
INTERSECT
SELECT column1 FROM table2;
-- EXCEPT:差集
SELECT column1 FROM table1
EXCEPT
SELECT column1 FROM table2;
7.4 条件表达式
-- CASE 表达式
SELECT
username,
CASE
WHEN status = 'active' THEN '活跃'
WHEN status = 'inactive' THEN '非活跃'
ELSE '未知'
END as status_text
FROM users;
-- COALESCE:返回第一个非空值
SELECT
username,
COALESCE(nickname, username) as display_name
FROM users;
-- NULLIF:如果两个值相等返回 NULL
SELECT NULLIF(column1, column2) FROM table_name;
-- GREATEST/LEAST:返回最大/最小值
SELECT
GREATEST(price1, price2, price3) as max_price,
LEAST(price1, price2, price3) as min_price
FROM products;
八、事务管理
8.1 事务基本概念
事务的 ACID 特性:
- 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败
- 一致性(Consistency):事务执行前后数据库保持一致状态
- 隔离性(Isolation):并发事务之间相互隔离
- 持久性(Durability):事务提交后,数据永久保存
8.2 事务操作
-- 开始事务
BEGIN;
-- 或者
START TRANSACTION;
-- 提交事务
COMMIT;
-- 回滚事务
ROLLBACK;
-- 保存点
SAVEPOINT savepoint_name;
-- 回滚到保存点
ROLLBACK TO SAVEPOINT savepoint_name;
-- 释放保存点
RELEASE SAVEPOINT savepoint_name;
8.3 事务示例
-- 基本事务
BEGIN;
INSERT INTO users (username, email, password_hash)
VALUES ('user1', 'user1@example.com', 'hash1');
INSERT INTO accounts (user_id, name, type)
VALUES (currval('users_id_seq'), '主账户', 'mixed');
COMMIT;
-- 带错误处理的事务
BEGIN;
INSERT INTO users (username, email, password_hash)
VALUES ('user2', 'user2@example.com', 'hash2');
-- 如果出错,自动回滚
SAVEPOINT before_account;
INSERT INTO accounts (user_id, name, type)
VALUES (currval('users_id_seq'), '主账户', 'mixed');
-- 如果账户创建失败,回滚到保存点
ROLLBACK TO SAVEPOINT before_account;
COMMIT;
8.4 事务隔离级别
-- 设置事务隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 查看当前隔离级别
SHOW transaction_isolation;
-- 隔离级别:
-- READ UNCOMMITTED(PostgreSQL 不支持)
-- READ COMMITTED(默认)
-- REPEATABLE READ
-- SERIALIZABLE
九、常用函数
9.1 字符串函数
-- 连接字符串
SELECT CONCAT('Hello', ' ', 'World');
SELECT 'Hello' || ' ' || 'World';
-- 长度
SELECT LENGTH('Hello');
SELECT CHAR_LENGTH('Hello');
-- 大小写转换
SELECT UPPER('hello');
SELECT LOWER('HELLO');
-- 截取
SELECT SUBSTRING('Hello World', 1, 5);
SELECT LEFT('Hello World', 5);
SELECT RIGHT('Hello World', 5);
-- 替换
SELECT REPLACE('Hello World', 'World', 'PostgreSQL');
-- 去除空格
SELECT TRIM(' Hello ');
SELECT LTRIM(' Hello');
SELECT RTRIM('Hello ');
-- 分割字符串
SELECT SPLIT_PART('a,b,c', ',', 2); -- 返回 'b'
9.2 数值函数
-- 绝对值
SELECT ABS(-10);
-- 四舍五入
SELECT ROUND(3.14159, 2); -- 3.14
-- 向上取整
SELECT CEIL(3.14); -- 4
-- 向下取整
SELECT FLOOR(3.14); -- 3
-- 幂运算
SELECT POWER(2, 3); -- 8
-- 平方根
SELECT SQRT(16); -- 4
-- 随机数
SELECT RANDOM();
SELECT FLOOR(RANDOM() * 100) + 1; -- 1-100 随机整数
9.3 日期时间函数
-- 当前日期时间
SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
SELECT CURRENT_TIMESTAMP;
SELECT NOW();
-- 提取日期部分
SELECT EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
SELECT EXTRACT(MONTH FROM CURRENT_TIMESTAMP);
SELECT EXTRACT(DAY FROM CURRENT_TIMESTAMP);
-- 日期加减
SELECT CURRENT_DATE + INTERVAL '1 day';
SELECT CURRENT_DATE + INTERVAL '1 month';
SELECT CURRENT_DATE - INTERVAL '1 year';
-- 日期格式化
SELECT TO_CHAR(CURRENT_TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS');
SELECT TO_CHAR(CURRENT_DATE, 'YYYY年MM月DD日');
-- 日期差
SELECT CURRENT_DATE - '2024-01-01'::DATE;
SELECT AGE('2024-12-31'::DATE, '2024-01-01'::DATE);
9.4 聚合函数
-- 计数
SELECT COUNT(*) FROM users;
SELECT COUNT(DISTINCT status) FROM users;
-- 求和
SELECT SUM(amount) FROM transactions;
-- 平均值
SELECT AVG(price) FROM positions;
-- 最大值/最小值
SELECT MAX(created_at) FROM users;
SELECT MIN(created_at) FROM users;
-- 分组聚合
SELECT
status,
COUNT(*) as count,
AVG(EXTRACT(YEAR FROM AGE(CURRENT_DATE, created_at))) as avg_age
FROM users
GROUP BY status;
9.5 JSON 函数
-- 创建 JSON
SELECT '{"name": "John", "age": 30}'::JSON;
SELECT JSON_BUILD_OBJECT('name', 'John', 'age', 30);
-- 提取 JSON 值
SELECT '{"name": "John"}'::JSON->>'name';
SELECT '{"user": {"name": "John"}}'::JSON->'user'->>'name';
-- JSON 数组
SELECT JSON_ARRAY_LENGTH('[1,2,3]'::JSON);
-- JSONB 操作符
SELECT '{"name": "John"}'::JSONB @> '{"name": "John"}'::JSONB; -- 包含
SELECT '{"name": "John"}'::JSONB ? 'name'; -- 键存在
十、实用技巧
10.1 性能优化
-- 使用 EXPLAIN 分析查询计划
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
-- 详细分析(包含实际执行时间)
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
-- 查看慢查询
SELECT
query,
calls,
total_time,
mean_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
10.2 数据导入导出
-- 导出为 CSV
COPY users TO '/tmp/users.csv' WITH CSV HEADER;
-- 从 CSV 导入
COPY users FROM '/tmp/users.csv' WITH CSV HEADER;
-- 导出为文本
COPY users TO '/tmp/users.txt';
-- 从文本导入
COPY users FROM '/tmp/users.txt';
10.3 查看数据库信息
-- 查看数据库大小
SELECT pg_size_pretty(pg_database_size('database_name'));
-- 查看表大小
SELECT pg_size_pretty(pg_total_relation_size('table_name'));
-- 查看所有表大小
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- 查看连接数
SELECT count(*) FROM pg_stat_activity;
-- 查看当前连接
SELECT * FROM pg_stat_activity;
10.4 权限管理
-- 授予权限
GRANT SELECT, INSERT, UPDATE ON table_name TO username;
GRANT ALL PRIVILEGES ON DATABASE database_name TO username;
-- 撤销权限
REVOKE SELECT ON table_name FROM username;
-- 查看权限
\dp table_name
10.5 序列操作
-- 查看当前序列值
SELECT currval('users_id_seq');
-- 查看下一个序列值
SELECT nextval('users_id_seq');
-- 设置序列值
SELECT setval('users_id_seq', 100);
-- 重置序列
ALTER SEQUENCE users_id_seq RESTART WITH 1;
10.6 常用配置
-- 查看配置
SHOW ALL;
SHOW shared_buffers;
SHOW max_connections;
-- 设置配置(会话级别)
SET work_mem = '256MB';
-- 查看时区
SHOW timezone;
SET timezone = 'Asia/Shanghai';
十一、常见问题
11.1 连接问题
# 问题:无法连接到数据库
# 解决:检查 PostgreSQL 服务是否运行
sudo systemctl status postgresql # Linux
brew services list # macOS
# 问题:认证失败
# 解决:检查 pg_hba.conf 配置文件
sudo nano /etc/postgresql/15/main/pg_hba.conf
11.2 性能问题
-- 问题:查询慢
-- 解决:创建索引
CREATE INDEX idx_column ON table_name (column_name);
-- 问题:表膨胀
-- 解决:VACUUM
VACUUM ANALYZE table_name;
-- 问题:统计信息过期
-- 解决:更新统计信息
ANALYZE table_name;
11.3 数据备份恢复
# 定期备份脚本
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
pg_dump -U postgres database_name > /backup/db_$DATE.sql
# 自动清理旧备份(保留30天)
find /backup -name "db_*.sql" -mtime +30 -delete
十二、参考资源
- 官方文档:https://www.postgresql.org/docs/
- 中文文档:https://www.postgresql.org/docs/current/index.html
- psql 命令参考:https://www.postgresql.org/docs/current/app-psql.html
- SQL 语法参考:https://www.postgresql.org/docs/current/sql.html
文档版本:v1.0
创建日期:2024年
适用版本:PostgreSQL 12+