以下是 PostgreSQL 数据库的典型操作分类及代码案例:
一、数据库管理操作
1. 数据库创建与连接
sql
-- 创建数据库
CREATE DATABASE company_db
WITH ENCODING='UTF8'
OWNER=admin
CONNECTION LIMIT 100;
-- 连接数据库
\c company_db;
-- 查看所有数据库
\l
-- 查看当前数据库
SELECT current_database();
2. 表空间管理
sql
-- 创建表空间
CREATE TABLESPACE fast_space
LOCATION '/var/lib/postgresql/data/fast';
-- 在表空间创建表
CREATE TABLE orders (
id SERIAL,
order_date DATE
) TABLESPACE fast_space;
二、表结构操作
1. 创建表
sql
-- 基础表创建
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
salary DECIMAL(10,2) CHECK (salary > 0),
hire_date DATE DEFAULT CURRENT_DATE,
department_id INTEGER,
created_at TIMESTAMP DEFAULT NOW(),
data JSONB
);
-- 创建分区表(PostgreSQL 13+)
CREATE TABLE sales (
id SERIAL,
sale_date DATE NOT NULL,
amount DECIMAL(10,2)
) PARTITION BY RANGE (sale_date);
-- 创建子分区
CREATE TABLE sales_2023_q1 PARTITION OF sales
FOR VALUES FROM ('2023-01-01') TO ('2023-04-01');
2. 修改表结构
sql
-- 添加列
ALTER TABLE employees ADD COLUMN phone VARCHAR(20);
-- 修改列类型
ALTER TABLE employees ALTER COLUMN phone TYPE VARCHAR(30);
-- 添加约束
ALTER TABLE employees
ADD CONSTRAINT fk_department
FOREIGN KEY (department_id)
REFERENCES departments(id);
-- 创建索引
CREATE INDEX idx_employees_name ON employees(name);
CREATE INDEX idx_employees_department ON employees(department_id);
CREATE INDEX idx_employees_hire_date ON employees(hire_date DESC);
-- 添加部分索引
CREATE INDEX idx_high_salary ON employees(salary)
WHERE salary > 100000;
-- 添加表达式索引
CREATE INDEX idx_lower_email ON employees(LOWER(email));
三、数据操作(CRUD)
1. 插入数据
sql
-- 插入单行
INSERT INTO employees (name, email, salary, department_id)
VALUES ('张三', 'zhangsan@company.com', 50000.00, 1);
-- 插入多行
INSERT INTO employees (name, email, salary)
VALUES
('李四', 'lisi@company.com', 45000.00),
('王五', 'wangwu@company.com', 60000.00),
('赵六', 'zhaoliu@company.com', 55000.00);
-- 插入并返回结果
INSERT INTO employees (name, email)
VALUES ('孙七', 'sunqi@company.com')
RETURNING id, name;
-- 插入JSON数据
INSERT INTO employees (name, data)
VALUES ('钱八', '{"skills": ["Python", "PostgreSQL"], "level": "Senior"}');
2. 查询数据
sql
-- 基础查询
SELECT * FROM employees;
-- 条件查询
SELECT name, salary
FROM employees
WHERE salary > 50000
AND hire_date > '2023-01-01';
-- 连接查询
SELECT e.name, d.department_name, e.salary
FROM employees e
INNER JOIN departments d ON e.department_id = d.id
WHERE d.location = '上海';
-- 聚合查询
SELECT
department_id,
COUNT(*) as employee_count,
AVG(salary) as avg_salary,
MAX(salary) as max_salary
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5
ORDER BY avg_salary DESC;
-- 窗口函数
SELECT
name,
salary,
department_id,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) as salary_rank,
AVG(salary) OVER (PARTITION BY department_id) as dept_avg_salary
FROM employees;
-- JSON查询
SELECT
name,
data->>'level' as level,
data->'skills' as skills
FROM employees
WHERE data @> '{"level": "Senior"}';
-- 递归查询(CTE)
WITH RECURSIVE employee_hierarchy AS (
-- 基础查询:找到顶级经理
SELECT id, name, manager_id, 1 as level
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- 递归查询:找到下属
SELECT e.id, e.name, e.manager_id, eh.level + 1
FROM employees e
INNER JOIN employee_hierarchy eh ON e.manager_id = eh.id
)
SELECT * FROM employee_hierarchy
ORDER BY level, name;
3. 更新数据
sql
-- 普通更新
UPDATE employees
SET salary = salary * 1.1
WHERE hire_date < '2020-01-01';
-- 基于子查询更新
UPDATE employees e
SET salary = salary * 1.05
FROM departments d
WHERE e.department_id = d.id
AND d.department_name = '研发部';
-- 更新JSON字段
UPDATE employees
SET data = jsonb_set(data, '{skills}', '["Java", "PostgreSQL", "Redis"]')
WHERE id = 1;
-- 更新并返回结果
UPDATE employees
SET salary = salary + 5000
WHERE department_id = 2
RETURNING id, name, salary;
4. 删除数据
sql
-- 条件删除
DELETE FROM employees
WHERE hire_date < '2018-01-01';
-- 关联删除
DELETE FROM employees e
USING departments d
WHERE e.department_id = d.id
AND d.department_name = '已解散部门';
-- 清空表(速度快,不可回滚)
TRUNCATE TABLE audit_log;
-- 删除并返回结果
DELETE FROM employees
WHERE id = 100
RETURNING *;
四、事务控制
sql
-- 事务示例
BEGIN;
-- 检查账户余额
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
-- 转账操作
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- 记录流水
INSERT INTO transactions (from_account, to_account, amount)
VALUES (1, 2, 1000);
-- 提交或回滚
COMMIT;
-- 或 ROLLBACK;
五、视图与物化视图
sql
-- 创建视图
CREATE VIEW employee_summary AS
SELECT
d.department_name,
COUNT(e.id) as employee_count,
AVG(e.salary) as avg_salary
FROM employees e
JOIN departments d ON e.department_id = d.id
GROUP BY d.department_name;
-- 使用视图
SELECT * FROM employee_summary WHERE employee_count > 10;
-- 创建物化视图
CREATE MATERIALIZED VIEW monthly_sales_summary AS
SELECT
DATE_TRUNC('month', sale_date) as month,
SUM(amount) as total_sales,
COUNT(*) as transaction_count
FROM sales
GROUP BY DATE_TRUNC('month', sale_date);
-- 刷新物化视图
REFRESH MATERIALIZED VIEW monthly_sales_summary;
六、存储过程与函数
sql
-- 创建函数
CREATE OR REPLACE FUNCTION get_employee_count(dept_id INT)
RETURNS INT AS $$
DECLARE
emp_count INT;
BEGIN
SELECT COUNT(*) INTO emp_count
FROM employees
WHERE department_id = dept_id;
RETURN emp_count;
END;
$$ LANGUAGE plpgsql;
-- 调用函数
SELECT get_employee_count(1);
-- 创建带参数的函数
CREATE OR REPLACE FUNCTION update_salary(
emp_id INT,
increase_percent DECIMAL
) RETURNS DECIMAL AS $$
DECLARE
old_salary DECIMAL;
new_salary DECIMAL;
BEGIN
-- 获取当前工资
SELECT salary INTO old_salary
FROM employees
WHERE id = emp_id;
-- 计算新工资
new_salary := old_salary * (1 + increase_percent/100);
-- 更新工资
UPDATE employees
SET salary = new_salary
WHERE id = emp_id;
RETURN new_salary;
END;
$$ LANGUAGE plpgsql;
-- 调用带参数的函数
SELECT update_salary(1, 10);
七、触发器示例
sql
-- 创建审计表
CREATE TABLE employee_audit (
id SERIAL PRIMARY KEY,
employee_id INT,
changed_field VARCHAR(50),
old_value TEXT,
new_value TEXT,
changed_at TIMESTAMP DEFAULT NOW(),
changed_by VARCHAR(100)
);
-- 创建触发器函数
CREATE OR REPLACE FUNCTION log_employee_changes()
RETURNS TRIGGER AS $$
BEGIN
IF (TG_OP = 'UPDATE') THEN
IF OLD.salary != NEW.salary THEN
INSERT INTO employee_audit (employee_id, changed_field, old_value, new_value)
VALUES (OLD.id, 'salary', OLD.salary::TEXT, NEW.salary::TEXT);
END IF;
IF OLD.department_id != NEW.department_id THEN
INSERT INTO employee_audit (employee_id, changed_field, old_value, new_value)
VALUES (OLD.id, 'department_id', OLD.department_id::TEXT, NEW.department_id::TEXT);
END IF;
ELSIF (TG_OP = 'DELETE') THEN
INSERT INTO employee_audit (employee_id, changed_field, old_value, new_value)
VALUES (OLD.id, 'status', '在职', '离职');
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO employee_audit (employee_id, changed_field, old_value, new_value)
VALUES (NEW.id, 'status', NULL, '新入职');
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 创建触发器
CREATE TRIGGER tr_employee_audit
AFTER INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW
EXECUTE FUNCTION log_employee_changes();
八、备份与恢复
sql
-- 逻辑备份单个数据库
-- 在命令行执行,不是SQL
-- pg_dump -U username -d database_name -f backup.sql
-- 备份所有数据库
-- pg_dumpall -U username -f all_backup.sql
-- 备份特定表
-- pg_dump -U username -d database_name -t table_name -f table_backup.sql
-- 恢复数据库
-- psql -U username -d database_name -f backup.sql
-- 创建物理备份点
SELECT pg_start_backup('before_migration', true);
-- 执行文件系统备份...
SELECT pg_stop_backup();
九、性能监控与维护
sql
-- 查看表大小
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as total_size,
pg_size_pretty(pg_relation_size(schemaname||'.'||tablename)) as table_size,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename) -
pg_relation_size(schemaname||'.'||tablename)) as index_size
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- 查看索引使用情况
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
ORDER BY idx_scan DESC;
-- 手动收集统计信息
ANALYZE employees;
-- 清理和优化表
VACUUM ANALYZE employees;
-- 重建索引
REINDEX INDEX idx_employees_name;
十、权限管理
sql
-- 创建角色
CREATE ROLE analyst WITH LOGIN PASSWORD 'secure_password';
CREATE ROLE readonly WITH NOLOGIN;
-- 授予权限
GRANT CONNECT ON DATABASE company_db TO analyst;
GRANT USAGE ON SCHEMA public TO analyst;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
GRANT SELECT, INSERT, UPDATE ON employees TO analyst;
-- 创建只读用户
CREATE USER viewer WITH PASSWORD 'view_only';
GRANT readonly TO viewer;
-- 查看权限
\dp employees
这些操作覆盖了 PostgreSQL 日常使用中的典型场景。在实际使用中,建议结合具体业务需求进行调整和优化。对于生产环境的重要操作,请务必先在测试环境验证,并做好备份。