PostgreSQL教程FG196-PG SQL命令实战:高频命令组合使用技巧
本文档详细介绍PostgreSQL SQL命令的组合使用技巧,包括DDL、DML、DQL和DCL命令的高频组合使用方法,风哥教程参考PostgreSQL官方文档内容,适合数据库管理员和开发人员在生产环境中使用这些命令进行数据库管理和开发。
Part01-基础概念与理论知识
1.1 PostgreSQL SQL命令概述
PostgreSQL支持标准的SQL命令,主要分为以下几类:DDL(数据定义语言)、DML(数据操作语言)、DQL(数据查询语言)和DCL(数据控制语言)。这些命令是PostgreSQL数据库操作的基础,掌握它们的使用方法对于数据库管理和开发非常重要。更多视频教程www.fgedu.net.cn
- DDL(数据定义语言):用于定义数据库结构,如CREATE、ALTER、DROP等
- DML(数据操作语言):用于操作数据,如INSERT、UPDATE、DELETE等
- DQL(数据查询语言):用于查询数据,如SELECT等
- DCL(数据控制语言):用于控制数据访问权限,如GRANT、REVOKE等
1.2 SQL命令组合使用的优势
SQL命令组合使用的优势:
- 提高效率:通过命令组合,可以在一个事务中完成多个操作,减少网络往返次数
- 保证一致性:在一个事务中执行多个命令,可以保证数据的一致性
- 简化代码:通过命令组合,可以简化应用代码,减少代码量
- 提高性能:合理的命令组合可以减少数据库的负担,提高查询性能
1.3 SQL命令使用最佳实践
— 1. 使用事务
BEGIN;
— 执行多个SQL命令
COMMIT;
— 2. 使用参数化查询
PREPARE stmt1 (int, text) AS
INSERT INTO fgedu_users (id, username) VALUES ($1, $2);
EXECUTE stmt1 (1, ‘admin’);
DEALLOCATE stmt1;
— 3. 使用批量操作
INSERT INTO fgedu_users (username, email) VALUES
(‘user1’, ‘user1@fgedu.net.cn’),
(‘user2’, ‘user2@fgedu.net.cn’),
(‘user3’, ‘user3@fgedu.net.cn’);
— 4. 使用索引
CREATE INDEX idx_fgedu_users_username ON fgedu_users(username);
— 5. 避免全表扫描
SELECT * FROM fgedu_users WHERE id = 1; — 使用主键索引
— 6. 定期维护
VACUUM ANALYZE fgedu_users;
Part02-生产环境规划与建议
2.1 SQL性能优化建议
— 1. 索引优化
— – 为频繁查询的列创建索引
— – 避免创建过多索引
— – 定期重建索引
— 2. 查询优化
— – 使用EXPLAIN分析查询计划
— – 避免SELECT *
— – 使用LIMIT限制结果集
— – 合理使用JOIN
— 3. 事务优化
— – 保持事务简短
— – 避免在事务中执行长时间操作
— – 使用合适的隔离级别
— 4. 批量操作
— – 使用批量INSERT
— – 使用COPY命令导入数据
— – 避免单行操作
— 5. 配置优化
— – 调整shared_buffers
— – 调整work_mem
— – 调整maintenance_work_mem
2.2 SQL安全使用建议
SQL安全使用建议:
- 使用参数化查询:避免SQL注入攻击
- 最小权限原则:只授予必要的权限
- 定期审计:定期检查权限设置
- 使用加密:对敏感数据进行加密
- 避免明文密码:使用密码哈希存储
2.3 SQL维护建议
SQL维护建议:
- 定期VACUUM:清理死元组,回收空间
- 定期ANALYZE:更新统计信息,优化查询计划
- 定期REINDEX:重建索引,提高索引性能
- 定期备份:保障数据安全
- 监控查询性能:及时发现和优化慢查询
Part03-生产环境项目实施方案
3.1 DDL命令组合使用
3.1.1 创建表和索引
— 1. 创建表
CREATE TABLE fgedu_users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
— 2. 创建索引
CREATE INDEX idx_fgedu_users_email ON fgedu_users(email);
— 3. 创建表空间
CREATE TABLESPACE fgedutbs LOCATION ‘/postgresql/tablespace’;
— 4. 在指定表空间创建表
CREATE TABLE fgedu_orders (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES fgedu_users(id),
total_amount DECIMAL(10,2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) TABLESPACE fgedutbs;
3.1.2 修改表结构
— 1. 添加列
ALTER TABLE fgedu_users ADD COLUMN phone VARCHAR(20);
— 2. 修改列类型
ALTER TABLE fgedu_users ALTER COLUMN phone TYPE VARCHAR(30);
— 3. 修改列默认值
ALTER TABLE fgedu_users ALTER COLUMN phone SET DEFAULT ‘N/A’;
— 4. 添加约束
ALTER TABLE fgedu_users ADD CONSTRAINT fgedu_users_phone_check CHECK (phone ~ ‘^[0-9]{10,15}$’);
— 5. 删除列
ALTER TABLE fgedu_users DROP COLUMN phone;
3.2 DML命令组合使用
3.2.1 插入和更新数据
— 1. 批量插入
INSERT INTO fgedu_users (username, email) VALUES
(‘user1’, ‘user1@fgedu.net.cn’),
(‘user2’, ‘user2@fgedu.net.cn’),
(‘user3’, ‘user3@fgedu.net.cn’);
— 2. 插入并返回
INSERT INTO fgedu_users (username, email) VALUES (‘user4’, ‘user4@fgedu.net.cn’) RETURNING id, username;
— 3. 更新数据
UPDATE fgedu_users SET email = ‘user1_update@fgedu.net.cn’ WHERE username = ‘user1’;
— 4. 批量更新
UPDATE fgedu_users SET created_at = CURRENT_TIMESTAMP WHERE id IN (1, 2, 3);
— 5. 删除数据
DELETE FROM fgedu_users WHERE id = 4;
— 6. 删除并返回
DELETE FROM fgedu_users WHERE username = ‘user3’ RETURNING id, username;
3.2.2 事务中的DML操作
— 1. 开始事务
BEGIN;
— 2. 插入订单
INSERT INTO fgedu_orders (user_id, total_amount) VALUES (1, 100.00) RETURNING id;
— 3. 假设返回的订单ID为100
— 插入订单商品
INSERT INTO fgedu_order_items (order_id, product_id, quantity, price) VALUES
(100, 1, 2, 50.00);
— 4. 提交事务
COMMIT;
— 5. 回滚事务(如果出错)
— ROLLBACK;
3.3 DQL命令组合使用
3.3.1 基本查询
— 1. 简单查询
SELECT * FROM fgedu_users;
— 2. 条件查询
SELECT * FROM fgedu_users WHERE id > 5;
— 3. 排序
SELECT * FROM fgedu_users ORDER BY created_at DESC;
— 4. 分页
SELECT * FROM fgedu_users LIMIT 10 OFFSET 20;
— 5. 聚合
SELECT COUNT(*) FROM fgedu_users;
SELECT AVG(total_amount) FROM fgedu_orders;
SELECT MAX(total_amount) FROM fgedu_orders;
SELECT MIN(total_amount) FROM fgedu_orders;
SELECT SUM(total_amount) FROM fgedu_orders;
3.3.2 复杂查询
— 1. 连接查询
SELECT u.id, u.username, o.id AS order_id, o.total_amount
FROM fgedu_users u
JOIN fgedu_orders o ON u.id = o.user_id;
— 2. 子查询
SELECT * FROM fgedu_users WHERE id IN (
SELECT user_id FROM fgedu_orders WHERE total_amount > 500
);
— 3. 分组查询
SELECT u.id, u.username, COUNT(o.id) AS order_count
FROM fgedu_users u
LEFT JOIN fgedu_orders o ON u.id = o.user_id
GROUP BY u.id, u.username
HAVING COUNT(o.id) > 0
ORDER BY order_count DESC;
— 4. 窗口函数
SELECT
id, username, email, created_at,
ROW_NUMBER() OVER (ORDER BY created_at) AS row_num,
RANK() OVER (ORDER BY created_at) AS rank_num
FROM fgedu_users;
3.4 DCL命令组合使用
3.4.1 权限管理
— 1. 创建角色
CREATE ROLE fgedu_read;
CREATE ROLE fgedu_write;
— 2. 授予权限
GRANT CONNECT ON DATABASE fgedudb TO fgedu_read;
GRANT USAGE ON SCHEMA public TO fgedu_read;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO fgedu_read;
GRANT CONNECT ON DATABASE fgedudb TO fgedu_write;
GRANT USAGE ON SCHEMA public TO fgedu_write;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO fgedu_write;
— 3. 创建用户并分配角色
CREATE USER fgedu_user1 WITH PASSWORD ‘Fgedu123@’;
GRANT fgedu_read TO fgedu_user1;
CREATE USER fgedu_user2 WITH PASSWORD ‘Fgedu456@’;
GRANT fgedu_write TO fgedu_user2;
— 4. 撤销权限
REVOKE DELETE ON fgedu_users FROM fgedu_write;
— 5. 删除角色
DROP ROLE fgedu_read;
DROP ROLE fgedu_write;
Part04-生产案例与实战讲解
4.1 DDL命令组合案例
— 1. 创建表空间
CREATE TABLESPACE fgedutbs LOCATION ‘/postgresql/tablespace’;
— 2. 创建用户表
CREATE TABLE fgedu_users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
— 3. 创建商品表
CREATE TABLE fgedu_products (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
price DECIMAL(10,2) NOT NULL,
stock INTEGER NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) TABLESPACE fgedutbs;
— 4. 创建订单表
CREATE TABLE fgedu_orders (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES fgedu_users(id),
total_amount DECIMAL(10,2) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT ‘pending’,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) TABLESPACE fgedutbs;
— 5. 创建订单商品表
CREATE TABLE fgedu_order_items (
id SERIAL PRIMARY KEY,
order_id INTEGER REFERENCES fgedu_orders(id),
product_id INTEGER REFERENCES fgedu_products(id),
quantity INTEGER NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) TABLESPACE fgedutbs;
— 6. 创建索引
CREATE INDEX idx_fgedu_users_email ON fgedu_users(email);
CREATE INDEX idx_fgedu_products_name ON fgedu_products(name);
CREATE INDEX idx_fgedu_orders_user_id ON fgedu_orders(user_id);
CREATE INDEX idx_fgedu_orders_status ON fgedu_orders(status);
CREATE INDEX idx_fgedu_order_items_order_id ON fgedu_order_items(order_id);
CREATE INDEX idx_fgedu_order_items_product_id ON fgedu_order_items(product_id);
4.2 DML命令组合案例
— 1. 插入用户数据
INSERT INTO fgedu_users (username, email, password) VALUES
(‘admin’, ‘admin@fgedu.net.cn’, ‘admin123’),
(‘user1’, ‘user1@fgedu.net.cn’, ‘user123’),
(‘user2’, ‘user2@fgedu.net.cn’, ‘user123’);
— 2. 插入商品数据
INSERT INTO fgedu_products (name, description, price, stock) VALUES
(‘iPhone 15’, ‘Apple iPhone 15’, 5999.99, 100),
(‘MacBook Pro’, ‘Apple MacBook Pro’, 12999.99, 50),
(‘AirPods Pro’, ‘Apple AirPods Pro’, 1999.99, 200);
— 3. 插入订单和订单商品(使用事务)
BEGIN;
— 插入订单
INSERT INTO fgedu_orders (user_id, total_amount, status) VALUES (2, 7999.98, ‘completed’) RETURNING id;
— 假设返回的订单ID为1
— 插入订单商品
INSERT INTO fgedu_order_items (order_id, product_id, quantity, price) VALUES
(1, 1, 1, 5999.99),
(1, 3, 1, 1999.99);
— 更新商品库存
UPDATE fgedu_products SET stock = stock – 1 WHERE id = 1;
UPDATE fgedu_products SET stock = stock – 1 WHERE id = 3;
— 提交事务
COMMIT;
— 4. 更新订单状态
UPDATE fgedu_orders SET status = ‘shipped’ WHERE id = 1;
— 5. 删除过期订单
DELETE FROM fgedu_order_items WHERE order_id IN (
SELECT id FROM fgedu_orders WHERE created_at < NOW() - INTERVAL '30 days'
);
DELETE FROM fgedu_orders WHERE created_at < NOW() - INTERVAL '30 days';
4.3 DQL命令组合案例
— 1. 查询用户订单数和总消费
SELECT
u.id, u.username, u.email,
COUNT(o.id) AS order_count,
SUM(o.total_amount) AS total_spent
FROM fgedu_users u
LEFT JOIN fgedu_orders o ON u.id = o.user_id
GROUP BY u.id, u.username, u.email
ORDER BY total_spent DESC;
— 2. 查询热销商品
SELECT
p.id, p.name, p.price,
SUM(oi.quantity) AS total_quantity,
SUM(oi.quantity * oi.price) AS total_sales
FROM fgedu_products p
JOIN fgedu_order_items oi ON p.id = oi.product_id
JOIN fgedu_orders o ON oi.order_id = o.id
WHERE o.status = ‘completed’
GROUP BY p.id, p.name, p.price
ORDER BY total_sales DESC
LIMIT 10;
— 3. 查询月度销售统计
SELECT
TO_CHAR(o.created_at, ‘YYYY-MM’) AS month,
COUNT(o.id) AS order_count,
SUM(o.total_amount) AS total_sales
FROM fgedu_orders o
WHERE o.status = ‘completed’
GROUP BY TO_CHAR(o.created_at, ‘YYYY-MM’)
ORDER BY month;
— 4. 查询用户最近订单
SELECT
u.username,
o.id AS order_id,
o.total_amount,
o.status,
o.created_at
FROM fgedu_users u
JOIN fgedu_orders o ON u.id = o.user_id
WHERE o.created_at > NOW() – INTERVAL ‘7 days’
ORDER BY o.created_at DESC;
4.4 DCL命令组合案例
— 1. 创建角色
CREATE ROLE fgedu_admin;
CREATE ROLE fgedu_customer;
CREATE ROLE fgedu_analyst;
— 2. 授予权限
— 管理员权限
GRANT ALL PRIVILEGES ON DATABASE fgedudb TO fgedu_admin;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO fgedu_admin;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO fgedu_admin;
— 客户权限
GRANT CONNECT ON DATABASE fgedudb TO fgedu_customer;
GRANT USAGE ON SCHEMA public TO fgedu_customer;
GRANT SELECT ON fgedu_products TO fgedu_customer;
GRANT INSERT, SELECT ON fgedu_orders TO fgedu_customer;
GRANT INSERT, SELECT ON fgedu_order_items TO fgedu_customer;
GRANT SELECT ON fgedu_users TO fgedu_customer;
GRANT UPDATE ON fgedu_users TO fgedu_customer;
— 分析师权限
GRANT CONNECT ON DATABASE fgedudb TO fgedu_analyst;
GRANT USAGE ON SCHEMA public TO fgedu_analyst;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO fgedu_analyst;
— 3. 创建用户并分配角色
CREATE USER admin_user WITH PASSWORD ‘Admin123@’;
GRANT fgedu_admin TO admin_user;
CREATE USER customer_user WITH PASSWORD ‘Customer123@’;
GRANT fgedu_customer TO customer_user;
CREATE USER analyst_user WITH PASSWORD ‘Analyst123@’;
GRANT fgedu_analyst TO analyst_user;
— 4. 测试权限
— 以customer_user身份登录
— 可以查询商品
SELECT * FROM fgedu_products;
— 可以下单
INSERT INTO fgedu_orders (user_id, total_amount, status) VALUES (2, 100.00, ‘pending’);
— 不能删除商品
DELETE FROM fgedu_products WHERE id = 1; — 会失败
Part05-风哥经验总结与分享
5.1 SQL命令使用技巧
SQL命令使用技巧:
- DDL技巧:
- 使用事务包装DDL操作,确保原子性
- 创建表时合理设计索引,提高查询性能
- 使用表空间分离不同类型的数据,优化存储
- 定期检查和维护表结构,避免冗余字段
- DML技巧:
- 使用批量操作减少网络往返
- 使用RETURNING子句获取操作结果
- 合理使用事务,确保数据一致性
- 避免在循环中执行SQL,使用批量处理
- DQL技巧:
- 使用EXPLAIN分析查询计划
- 合理使用索引,避免全表扫描
- 使用LIMIT限制结果集,提高查询速度
- 合理使用JOIN,避免笛卡尔积
- 使用窗口函数简化复杂查询
- DCL技巧:
- 使用角色管理权限,简化权限管理
- 遵循最小权限原则,只授予必要的权限
- 定期审计权限设置,确保安全
- 使用GRANT ALL PRIVILEGES谨慎,避免过度授权
5.2 SQL命令常见问题解决
— 1. 死锁
— 问题:事务死锁
— 解决:
— – 保持事务简短
— – 以相同的顺序访问表
— – 使用适当的隔离级别
— – 监控并及时终止长时间运行的事务
— 2. 慢查询
— 问题:查询执行时间过长
— 解决:
— – 使用EXPLAIN分析查询计划
— – 创建合适的索引
— – 优化查询语句
— – 调整配置参数
— 3. 索引失效
— 问题:索引未被使用
— 解决:
— – 检查索引是否存在
— – 检查查询条件是否使用索引列
— – 检查索引统计信息是否最新
— – 重建索引
— 4. 权限错误
— 问题:权限不足
— 解决:
— – 检查用户权限
— – 授予必要的权限
— – 检查角色继承关系
— – 检查对象所有权
— 5. 语法错误
— 问题:SQL语法错误
— 解决:
— – 检查SQL语句语法
— – 检查引号和括号
— – 检查关键字拼写
— – 使用参数化查询
5.3 SQL命令性能优化
— 1. 查询优化
— – 使用索引覆盖查询
SELECT id, username FROM fgedu_users WHERE email = ‘user@fgedu.net.cn’;
— – 避免使用函数在索引列上
— 不好的例子:SELECT * FROM fgedu_users WHERE UPPER(username) = ‘ADMIN’;
— 好的例子:SELECT * FROM fgedu_users WHERE username = ‘admin’;
— – 避免使用LIKE ‘%xxx’
— 不好的例子:SELECT * FROM fgedu_users WHERE username LIKE ‘%admin%’;
— 好的例子:SELECT * FROM fgedu_users WHERE username LIKE ‘admin%’;
— 2. 插入优化
— – 使用批量插入
INSERT INTO fgedu_users (username, email) VALUES
(‘user1’, ‘user1@fgedu.net.cn’),
(‘user2’, ‘user2@fgedu.net.cn’);
— – 使用COPY命令导入大量数据
COPY fgedu_users (username, email) FROM ‘/data/users.csv’ DELIMITER ‘,’ CSV HEADER;
— 3. 更新优化
— – 只更新必要的列
UPDATE fgedu_users SET email = ‘newemail@fgedu.net.cn’ WHERE id = 1;
— – 使用条件更新,避免全表更新
UPDATE fgedu_users SET status = ‘active’ WHERE last_login > NOW() – INTERVAL ’30 days’;
— 4. 删除优化
— – 使用批量删除,避免全表删除
DELETE FROM fgedu_users WHERE id IN (1, 2, 3);
— – 使用TRUNCATE替代DELETE删除全表
TRUNCATE TABLE fgedu_users;
— 5. 事务优化
— – 保持事务简短
BEGIN;
— 执行少量操作
COMMIT;
— – 使用合适的隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
