# PostgreSQL 使用文档 ## 目录 1. [安装 PostgreSQL](#一安装-postgresql) 2. [基本操作](#二基本操作) 3. [数据库操作](#三数据库操作) 4. [表操作](#四表操作) 5. [数据操作(CRUD)](#五数据操作crud) 6. [索引操作](#六索引操作) 7. [高级查询](#七高级查询) 8. [事务管理](#八事务管理) 9. [常用函数](#九常用函数) 10. [实用技巧](#十实用技巧) --- ## 一、安装 PostgreSQL ### 1.1 macOS 安装 #### 方法一:使用 Homebrew(推荐) ```bash # 安装 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(图形化工具) 1. 访问 https://postgresapp.com/ 2. 下载并安装 Postgres.app 3. 打开应用,点击 "Initialize" 初始化数据库 #### 方法三:使用官方安装包 1. 访问 https://www.postgresql.org/download/macosx/ 2. 下载官方安装包 3. 按照安装向导完成安装 ### 1.2 Linux 安装 #### Ubuntu/Debian ```bash # 更新包列表 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 ```bash # 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 ```bash # 安装 sudo pacman -S postgresql # 初始化数据库 sudo -u postgres initdb -D /var/lib/postgres/data # 启动服务 sudo systemctl start postgresql sudo systemctl enable postgresql ``` ### 1.3 验证安装 ```bash # 检查 PostgreSQL 版本 psql --version # 或者 postgres --version # 检查服务状态(Linux) sudo systemctl status postgresql ``` ### 1.4 初始配置 #### 设置 postgres 用户密码 ```bash # 切换到 postgres 用户(Linux) sudo -u postgres psql # 或者直接连接(macOS) psql -U postgres # 在 psql 中设置密码 ALTER USER postgres PASSWORD 'your_password'; ``` #### 创建新用户和数据库 ```bash # 使用 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 连接数据库 ```bash # 使用默认用户连接默认数据库 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 常用命令 ```sql -- 查看所有数据库 \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 创建数据库 ```sql -- 基本语法 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 查看数据库 ```sql -- 查看所有数据库 SELECT datname FROM pg_database; -- 查看数据库详细信息 \l -- 或者 \list -- 查看当前数据库 SELECT current_database(); ``` ### 3.3 删除数据库 ```sql -- 删除数据库(需要先断开所有连接) DROP DATABASE database_name; -- 强制删除(终止所有连接) -- 首先终止所有连接 SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'database_name'; -- 然后删除 DROP DATABASE database_name; ``` ### 3.4 修改数据库 ```sql -- 重命名数据库 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 备份和恢复 ```bash # 备份数据库 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 创建表 #### 基本语法 ```sql CREATE TABLE table_name ( column1 datatype constraint, column2 datatype constraint, ... ); ``` #### 数据类型 **数值类型:** ```sql 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 -- 大自增整数 ``` **字符串类型:** ```sql VARCHAR(n) -- 可变长度字符串,最大n字符 CHAR(n) -- 固定长度字符串,n字符 TEXT -- 无限长度字符串 ``` **日期时间类型:** ```sql DATE -- 日期(年-月-日) TIME -- 时间(时:分:秒) TIMESTAMP -- 日期和时间 TIMESTAMPTZ -- 带时区的时间戳 INTERVAL -- 时间间隔 ``` **布尔类型:** ```sql BOOLEAN -- true/false ``` **JSON 类型:** ```sql JSON -- JSON 数据 JSONB -- 二进制 JSON(推荐,性能更好) ``` #### 约束 ```sql -- 主键约束 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 ``` #### 完整示例 ```sql -- 创建用户表 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 查看表 ```sql -- 查看所有表 \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 修改表 ```sql -- 添加列 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 删除表 ```sql -- 删除表 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) #### 基本语法 ```sql -- 插入单行数据 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; ``` #### 示例 ```sql -- 插入用户 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) #### 基本语法 ```sql -- 查询所有列 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; ``` #### 示例 ```sql -- 查询所有用户 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) #### 基本语法 ```sql UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition; ``` #### 示例 ```sql -- 更新单列 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) #### 基本语法 ```sql DELETE FROM table_name WHERE condition; ``` #### 示例 ```sql -- 删除指定记录 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) ```sql -- 内连接 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 子查询 ```sql -- 标量子查询 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 创建索引 #### 基本语法 ```sql -- 创建单列索引 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); ``` #### 示例 ```sql -- 基本索引 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 查看索引 ```sql -- 查看表的所有索引 \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 删除索引 ```sql -- 删除索引 DROP INDEX index_name; -- 删除索引(如果存在) DROP INDEX IF EXISTS index_name; -- 级联删除 DROP INDEX index_name CASCADE; ``` ### 6.5 重建索引 ```sql -- 重建索引(释放空间,提高性能) REINDEX INDEX index_name; -- 重建表的所有索引 REINDEX TABLE table_name; -- 重建数据库的所有索引 REINDEX DATABASE database_name; ``` ### 6.6 索引类型 ```sql -- 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 索引维护 ```sql -- 分析表(更新统计信息,帮助查询优化器) 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 窗口函数 ```sql -- 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) ```sql -- 基本 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 集合操作 ```sql -- 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 条件表达式 ```sql -- 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 事务操作 ```sql -- 开始事务 BEGIN; -- 或者 START TRANSACTION; -- 提交事务 COMMIT; -- 回滚事务 ROLLBACK; -- 保存点 SAVEPOINT savepoint_name; -- 回滚到保存点 ROLLBACK TO SAVEPOINT savepoint_name; -- 释放保存点 RELEASE SAVEPOINT savepoint_name; ``` ### 8.3 事务示例 ```sql -- 基本事务 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 事务隔离级别 ```sql -- 设置事务隔离级别 SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 查看当前隔离级别 SHOW transaction_isolation; -- 隔离级别: -- READ UNCOMMITTED(PostgreSQL 不支持) -- READ COMMITTED(默认) -- REPEATABLE READ -- SERIALIZABLE ``` --- ## 九、常用函数 ### 9.1 字符串函数 ```sql -- 连接字符串 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 数值函数 ```sql -- 绝对值 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 日期时间函数 ```sql -- 当前日期时间 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 聚合函数 ```sql -- 计数 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 函数 ```sql -- 创建 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 性能优化 ```sql -- 使用 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 数据导入导出 ```sql -- 导出为 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 查看数据库信息 ```sql -- 查看数据库大小 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 权限管理 ```sql -- 授予权限 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 序列操作 ```sql -- 查看当前序列值 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 常用配置 ```sql -- 查看配置 SHOW ALL; SHOW shared_buffers; SHOW max_connections; -- 设置配置(会话级别) SET work_mem = '256MB'; -- 查看时区 SHOW timezone; SET timezone = 'Asia/Shanghai'; ``` --- ## 十一、常见问题 ### 11.1 连接问题 ```bash # 问题:无法连接到数据库 # 解决:检查 PostgreSQL 服务是否运行 sudo systemctl status postgresql # Linux brew services list # macOS # 问题:认证失败 # 解决:检查 pg_hba.conf 配置文件 sudo nano /etc/postgresql/15/main/pg_hba.conf ``` ### 11.2 性能问题 ```sql -- 问题:查询慢 -- 解决:创建索引 CREATE INDEX idx_column ON table_name (column_name); -- 问题:表膨胀 -- 解决:VACUUM VACUUM ANALYZE table_name; -- 问题:统计信息过期 -- 解决:更新统计信息 ANALYZE table_name; ``` ### 11.3 数据备份恢复 ```bash # 定期备份脚本 #!/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+