目录
一、数据库与对象管理
二、数据操作 (CRUD)
三、查询优化与执行计划分析
四、事务控制
五、数据类型与高级特性应用
六、系统查询与维护
研发中的重要注意事项
在 PostgreSQL 研发中,以下这些 SQL 应用是极其常见且核心的操作,涵盖了数据库设计、数据操作、查询优化和系统维护的关键方面:
创建/修改表:
CREATE TABLE employees (
id SERIAL PRIMARY KEY, -- 自增主键
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
department_id INTEGER REFERENCES departments(id), -- 外键
salary NUMERIC(10, 2),
hire_date DATE DEFAULT CURRENT_DATE,
is_active BOOLEAN DEFAULT true,
skills TEXT[] -- 数组类型
profile JSONB -- JSONB 类型存储灵活数据
);
-- 添加索引
CREATE INDEX idx_employees_department ON employees(department_id);
CREATE INDEX idx_employees_name ON employees(name);
CREATE INDEX idx_employees_profile_email ON employees USING gin ((profile->>'email')); -- JSONB 字段索引
-- 修改表 (添加列、修改列类型、添加约束等)
ALTER TABLE employees ADD COLUMN phone VARCHAR(20);
ALTER TABLE employees ALTER COLUMN salary TYPE DECIMAL(12, 2);
ALTER TABLE employees ADD CONSTRAINT salary_check CHECK (salary > 0);
创建视图:
CREATE VIEW active_employees AS
SELECT id, name, email, department_id
FROM employees
WHERE is_active = true;
-- 物化视图 (定期刷新)
CREATE MATERIALIZED VIEW department_salary_summary AS
SELECT department_id, AVG(salary) AS avg_salary, SUM(salary) AS total_salary
FROM employees
GROUP BY department_id
WITH DATA;
REFRESH MATERIALIZED VIEW department_salary_summary; -- 手动刷新
创建函数/存储过程:
CREATE OR REPLACE FUNCTION get_employee_count(dept_id INTEGER)
RETURNS INTEGER AS $$
DECLARE
emp_count INTEGER;
BEGIN
SELECT COUNT(*) INTO emp_count
FROM employees
WHERE department_id = dept_id AND is_active = true;
RETURN emp_count;
END;
$$ LANGUAGE plpgsql;
-- 调用函数
SELECT get_employee_count(5);
插入数据:
INSERT INTO employees (name, email, department_id, salary)
VALUES ('Alice Smith', '[email protected]', 3, 75000.00),
('Bob Johnson', '[email protected]', 3, 82000.00);
-- 插入来自查询的结果
INSERT INTO archived_employees (id, name, email, leave_date)
SELECT id, name, email, CURRENT_DATE
FROM employees
WHERE is_active = false;
查询数据:
SELECT id, name, salary FROM employees WHERE department_id = 3 AND salary > 80000;
SELECT e.name, d.name AS department_name, e.salary
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;
-- LEFT JOIN, RIGHT JOIN, FULL JOIN 也很常用
SELECT department_id, COUNT(*) AS num_employees, AVG(salary) AS avg_salary
FROM employees
WHERE is_active = true
GROUP BY department_id
HAVING AVG(salary) > 60000;
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
SELECT name, department_id, salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dept_salary_rank,
salary - LAG(salary) OVER (PARTITION BY department_id ORDER BY hire_date) AS salary_diff
FROM employees;
SELECT name, profile->>'address' AS address -- 提取文本
FROM employees
WHERE profile @> '{"skills": ["PostgreSQL"]}'; -- 包含特定键值对
更新数据:
UPDATE employees
SET salary = salary * 1.05 -- 涨薪5%
WHERE department_id = 3 AND performance_rating >= 4;
-- 基于子查询更新
UPDATE employees e
SET manager_id = (SELECT manager_id FROM departments d WHERE d.id = e.department_id)
WHERE e.manager_id IS NULL;
删除数据:
DELETE FROM employees
WHERE is_active = false AND hire_date < '2020-01-01';
-- 使用事务确保操作原子性
BEGIN;
-- 先存档再删除
INSERT INTO deleted_employees_log SELECT *, CURRENT_TIMESTAMP FROM employees WHERE id = 123;
DELETE FROM employees WHERE id = 123;
COMMIT;
EXPLAIN
/ EXPLAIN ANALYZE
:
EXPLAIN ANALYZE
SELECT * FROM orders
WHERE customer_id = 456 AND order_date BETWEEN '2023-01-01' AND '2023-12-31'
ORDER BY total_amount DESC
LIMIT 10;
强制使用索引 (通常不推荐,优化器通常更聪明):
SET enable_seqscan = off; -- 临时关闭顺序扫描 (测试用,勿在生产库长期开启)
-- ... 运行查询 ...
SET enable_seqscan = on;
创建/优化索引:
CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);
CREATE INDEX idx_active_high_salary ON employees(salary) WHERE is_active = true AND salary > 100000;
CREATE INDEX idx_employee_lower_name ON employees(LOWER(name));
CREATE INDEX idx_order_summary ON orders(customer_id, order_date) INCLUDE (total_amount);
(PG 11+)GIN
/GiST
索引: 用于全文搜索(tsvector
)、数组、JSONB、几何类型等。显式事务:
BEGIN;
-- 一系列操作 (INSERT, UPDATE, DELETE, SELECT ... FOR UPDATE)
UPDATE accounts SET balance = balance - 100.00 WHERE id = 1;
UPDATE accounts SET balance = balance + 100.00 WHERE id = 2;
-- 根据业务逻辑决定提交或回滚
COMMIT; -- 或 ROLLBACK;
事务隔离级别:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 默认级别
-- 或 REPEATABLE READ, SERIALIZABLE
BEGIN;
... -- 在指定隔离级别下执行事务
COMMIT;
SELECT ... FOR UPDATE
/ SELECT ... FOR SHARE
:
BEGIN;
SELECT * FROM inventory WHERE product_id = 789 FOR UPDATE; -- 锁定该行,防止其他事务并发修改
-- 检查库存、扣减库存...
UPDATE inventory SET stock = stock - 1 WHERE product_id = 789;
COMMIT;
JSONB
操作:
-- 插入
INSERT INTO products (id, name, attributes)
VALUES (1, 'T-Shirt', '{"color": "red", "size": ["S", "M", "L"], "material": "cotton"}');
-- 查询
SELECT name, attributes->'size' AS available_sizes
FROM products
WHERE attributes @> '{"color": "red"}'; -- 包含 color=red
-- 更新
UPDATE products
SET attributes = jsonb_set(attributes, '{price}', '19.99') -- 添加/更新 price 键
WHERE id = 1;
UPDATE products
SET attributes = attributes || '{"discount": 0.1}' -- 合并添加 discount 键
WHERE id = 1;
数组操作:
SELECT name FROM employees WHERE 'PostgreSQL' = ANY(skills); -- 包含特定技能
UPDATE employees SET skills = array_append(skills, 'Docker') WHERE id = 456; -- 添加技能
SELECT unnest(skills) AS skill, COUNT(*) FROM employees GROUP BY skill; -- 展开数组统计
全文搜索:
-- 创建 tsvector 列和索引
ALTER TABLE articles ADD COLUMN search_vector tsvector;
UPDATE articles SET search_vector = to_tsvector('english', title || ' ' || body);
CREATE INDEX idx_articles_search ON articles USING gin(search_vector);
-- 搜索
SELECT title, snippet(search_vector, query) AS highlight
FROM articles, plainto_tsquery('english', 'database performance') query
WHERE search_vector @@ query
ORDER BY ts_rank(search_vector, query) DESC;
查看表/索引信息:
\d employees -- psql 元命令
SELECT * FROM pg_tables WHERE schemaname = 'public'; -- 系统表
SELECT * FROM pg_indexes WHERE tablename = 'employees'; -- 索引信息
SELECT pg_size_pretty(pg_total_relation_size('employees')); -- 表大小 (含索引)
查看连接/锁:
SELECT * FROM pg_stat_activity; -- 当前活动连接/查询
SELECT * FROM pg_locks; -- 当前锁信息
权限管理:
GRANT SELECT, INSERT, UPDATE ON employees TO developer_role;
REVOKE DELETE ON employees FROM public;
JOIN
或批量查询 (WHERE ... IN (...)
) 代替在循环中执行单个查询。pg_stat_all_indexes
)。COPY
命令、批量 INSERT ... VALUES (...), (...), ...
或 INSERT ... SELECT ...
,比循环单条插入高效得多。EXPLAIN ANALYZE
分析慢查询。监控数据库性能指标(连接数、锁、CPU、IO)。使用 pg_stat_statements
扩展找出高频/高消耗 SQL。掌握这些常规 SQL 应用并结合 PostgreSQL 的强大特性(如 JSONB、数组、GIN/GiST 索引、窗口函数、CTE、强大的 PL/pgSQL),能够高效、安全地进行应用研发,构建高性能、可扩展的后端系统。
这篇博客到这里就接近尾声了,希望我的分享能给您带来一些启发和帮助,别忘了点赞、收藏。您的每一次互动、鼓励是我持续创作的动力!期待与您再次相遇,共同探索更广阔的世界!