常用SQL整理
一.单表查询
1.基础查询
sql
-- 查询所有列
SELECT * FROM table_name;
-- 查询指定列
SELECT column1, column2, column3 FROM table_name;
-- 查询表达式和别名
SELECT column1, column2 * 2 AS double_col FROM table_name;
-- 去重查询
SELECT DISTINCT column1 FROM table_name;
-- 排序查询,支持多列排序
SELECT * FROM table_name ORDER BY column1 ASC, column2 DESC;
-- 分页查询(MySQL)
SELECT * FROM table_name ORDER BY id LIMIT 10 OFFSET 20;
-- 分页查询(SQL Server)
SELECT * FROM table_name ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
-- 查询别名
SELECT column1 AS alias1, column2 AS alias2 FROM table_name;
2.数据过滤
sql
-- 等值过滤
SELECT * FROM table_name WHERE column1 = 'value';
-- 多条件过滤(AND、OR)
SELECT * FROM table_name WHERE column1 = 'value' AND (column2 > 10 OR column3 IS NULL);
-- 模糊匹配
SELECT * FROM table_name WHERE column1 LIKE '%abc%';
-- 正则匹配(MySQL)
SELECT * FROM table_name WHERE column1 REGEXP '^abc';
-- 范围查询
SELECT * FROM table_name WHERE column2 BETWEEN 10 AND 20;
-- 空值判断
SELECT * FROM table_name WHERE column3 IS NULL;
SELECT * FROM table_name WHERE column3 IS NOT NULL;
-- IN和NOT IN
SELECT * FROM table_name WHERE column1 IN ('a', 'b', 'c');
SELECT * FROM table_name WHERE column1 NOT IN ('a', 'b', 'c');
-- EXISTS子查询
SELECT * FROM table_name t WHERE EXISTS (SELECT 1 FROM other_table o WHERE o.id = t.id);
-- 复杂条件示例
SELECT * FROM table_name WHERE (column1 = 'a' OR column1 = 'b') AND column2 BETWEEN 5 AND 10;
3.聚合函数
sql
-- 计数
SELECT COUNT(*) FROM table_name;
SELECT COUNT(DISTINCT column1) FROM table_name;
-- 求和、平均、最大、最小
SELECT SUM(column2), AVG(column2), MAX(column2), MIN(column2) FROM table_name;
-- 分组统计
SELECT column1, COUNT(*) AS cnt, AVG(column2) AS avg_val FROM table_name GROUP BY column1;
-- 分组过滤(HAVING)
SELECT column1, COUNT(*) AS cnt FROM table_name GROUP BY column1 HAVING cnt > 5;
-- GROUP BY ROLLUP(分组汇总)
SELECT column1, column2, SUM(column3) FROM table_name GROUP BY ROLLUP(column1, column2);
4.高级窗口函数
sql
-- 行号
SELECT column1, ROW_NUMBER() OVER (ORDER BY column2 DESC) AS rn FROM table_name;
-- 排名
SELECT column1, RANK() OVER (ORDER BY column2 DESC) AS rnk FROM table_name;
-- 密集排名
SELECT column1, DENSE_RANK() OVER (ORDER BY column2 DESC) AS drnk FROM table_name;
-- 累计和
SELECT column1, SUM(column2) OVER (ORDER BY column3 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_sum FROM table_name;
-- 分区排名
SELECT column1, RANK() OVER (PARTITION BY column3 ORDER BY column2 DESC) AS partition_rank FROM table_name;
二.多表查询
1.表连接操作
sql
-- 内连接
SELECT a.*, b.* FROM table_a a INNER JOIN table_b b ON a.id = b.a_id;
-- 左连接
SELECT a.*, b.* FROM table_a a LEFT JOIN table_b b ON a.id = b.a_id;
-- 右连接
SELECT a.*, b.* FROM table_a a RIGHT JOIN table_b b ON a.id = b.a_id;
-- 全连接(部分数据库支持)
SELECT a.*, b.* FROM table_a a FULL OUTER JOIN table_b b ON a.id = b.a_id;
-- 自连接
SELECT a1.*, a2.* FROM table_a a1 JOIN table_a a2 ON a1.parent_id = a2.id;
-- 交叉连接
SELECT a.*, b.* FROM table_a a CROSS JOIN table_b b;
2.子查询
sql
-- 标量子查询
SELECT column1, (SELECT MAX(column2) FROM table_b) AS max_val FROM table_a;
-- IN子查询
SELECT * FROM table_a WHERE id IN (SELECT a_id FROM table_b);
-- EXISTS子查询
SELECT * FROM table_a WHERE EXISTS (SELECT 1 FROM table_b WHERE table_b.a_id = table_a.id);
-- 相关子查询
SELECT * FROM table_a a WHERE column1 > (SELECT AVG(column1) FROM table_a WHERE category = a.category);
-- 子查询作为表
SELECT a.*, b.total FROM table_a a JOIN (SELECT a_id, COUNT(*) AS total FROM table_b GROUP BY a_id) b ON a.id = b.a_id;
3.联合查询
sql
-- UNION去重
SELECT column1 FROM table_a UNION SELECT column1 FROM table_b;
-- UNION ALL不去重
SELECT column1 FROM table_a UNION ALL SELECT column1 FROM table_b;
-- ORDER BY排序
SELECT column1 FROM table_a UNION ALL SELECT column1 FROM table_b ORDER BY column1 DESC;
三.常用函数
1.字符串处理
sql
-- 拼接字符串
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM table_name;
-- 字符串长度
SELECT LENGTH(column1) FROM table_name; -- MySQL
SELECT LEN(column1) FROM table_name; -- SQL Server
-- 子串截取
SELECT SUBSTRING(column1, 1, 5) FROM table_name;
-- 大小写转换
SELECT LOWER(column1), UPPER(column1) FROM table_name;
-- 去空格
SELECT TRIM(column1) FROM table_name;
-- 替换字符串
SELECT REPLACE(column1, 'old', 'new') FROM table_name;
-- 查找字符串位置
SELECT INSTR(column1, 'sub') FROM table_name; -- MySQL
SELECT CHARINDEX('sub', column1) FROM table_name; -- SQL Server
2.时间日期函数
sql
-- 当前时间
SELECT NOW(); -- MySQL
SELECT GETDATE(); -- SQL Server
-- 日期提取
SELECT YEAR(date_col), MONTH(date_col), DAY(date_col) FROM table_name;
-- 日期加减
SELECT DATE_ADD(date_col, INTERVAL 7 DAY) FROM table_name; -- MySQL
SELECT DATE_SUB(date_col, INTERVAL 1 MONTH) FROM table_name;
SELECT DATEADD(DAY, 7, date_col) FROM table_name; -- SQL Server
SELECT DATEADD(MONTH, -1, date_col) FROM table_name;
-- 日期差
SELECT DATEDIFF(day, '2023-01-01', '2023-01-10'); -- SQL Server
SELECT DATEDIFF('day', '2023-01-01', '2023-01-10'); -- PostgreSQL
-- 格式化日期
SELECT DATE_FORMAT(date_col, '%Y-%m-%d') FROM table_name; -- MySQL
SELECT FORMAT(date_col, 'yyyy-MM-dd') FROM table_name; -- SQL Server
四.常用操作
1.数据操作
sql
-- 插入
INSERT INTO table_name (col1, col2) VALUES ('val1', 123);
-- 批量插入
INSERT INTO table_name (col1, col2) VALUES ('v1', 1), ('v2', 2);
-- 更新
UPDATE table_name SET col1 = 'new_val' WHERE id = 10;
-- 删除
DELETE FROM table_name WHERE id = 10;
-- 清空表
TRUNCATE TABLE table_name;
2.表操作
sql
-- 创建表
CREATE TABLE table_name (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
age INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 添加列
ALTER TABLE table_name ADD COLUMN email VARCHAR(255);
-- 修改列类型
ALTER TABLE table_name MODIFY COLUMN age SMALLINT;
-- 重命名列
ALTER TABLE table_name RENAME COLUMN old_name TO new_name;
-- 删除列
ALTER TABLE table_name DROP COLUMN email;
-- 删除表
DROP TABLE table_name;
-- 重命名表
RENAME TABLE old_table TO new_table;
3.约束与索引
sql
-- 添加主键
ALTER TABLE table_name ADD PRIMARY KEY (id);
-- 添加唯一约束
ALTER TABLE table_name ADD UNIQUE (column1);
-- 添加外键
ALTER TABLE table_name ADD CONSTRAINT fk_name FOREIGN KEY (column2) REFERENCES other_table(id);
-- 创建索引
CREATE INDEX idx_name ON table_name(column1);
-- 创建唯一索引
CREATE UNIQUE INDEX idx_unique_name ON table_name(column1);
-- 删除索引
DROP INDEX idx_name ON table_name;
4.视图
sql
-- 创建视图
CREATE VIEW view_name AS SELECT col1, col2 FROM table_name WHERE col3 > 100;
-- 查询视图
SELECT * FROM view_name;
-- 更新视图
CREATE OR REPLACE VIEW view_name AS SELECT col1, col2 FROM table_name WHERE col3 > 200;
-- 删除视图
DROP VIEW view_name;
5.事务控制
sql
BEGIN TRANSACTION; -- 开始事务
COMMIT; -- 提交事务
ROLLBACK; -- 回滚事务
SAVEPOINT sp1; -- 设置保存点
ROLLBACK TO sp1; -- 回滚到保存点
6.权限管理
sql
GRANT SELECT, INSERT ON db.table TO 'user'@'host';
REVOKE INSERT ON db.table FROM 'user'@'host';
SHOW GRANTS FOR 'user'@'host';
四.其他操作
1.数据库管理
sql
-- 创建数据库
CREATE DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 删除数据库
DROP DATABASE database_name;
-- 查看当前数据库
SELECT DATABASE();
-- 切换数据库
USE database_name;
-- 查看所有数据库
SHOW DATABASES;
-- 查看当前连接用户
SELECT USER();
-- 查看当前连接信息
SELECT CONNECTION_ID();
2. 表结构与元数据查询
sql
-- 查看表结构(字段、类型、默认值等)
DESCRIBE table_name;
SHOW COLUMNS FROM table_name;
-- 查看表的创建语句
SHOW CREATE TABLE table_name;
-- 查看表大小(MySQL)
SELECT table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables
WHERE table_schema = 'database_name' AND table_name = 'table_name';
-- 查看所有表
SHOW TABLES;
-- 查看表的索引信息
SHOW INDEX FROM table_name;
-- 查看表的约束信息(MySQL 8+)
SELECT * FROM information_schema.table_constraints WHERE table_name = 'table_name';
3. 性能监控与优化
sql
-- 查看当前运行的查询(MySQL)
SHOW PROCESSLIST;
-- 查看慢查询日志(需开启慢查询日志)
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'slow_query_log_file';
-- EXPLAIN查询计划
EXPLAIN SELECT * FROM table_name WHERE column1 = 'value';
-- ANALYZE查询计划(部分数据库支持)
ANALYZE SELECT * FROM table_name WHERE column1 = 'value';
-- 优化表(MySQL)
OPTIMIZE TABLE table_name;
-- 修复表(MySQL)
REPAIR TABLE table_name;
4. 数据备份与恢复
sql
-- MySQL备份整个数据库(命令行)
mysqldump -u username -p database_name > backup.sql
-- 备份指定表
mysqldump -u username -p database_name table_name > table_backup.sql
-- 备份结构不含数据
mysqldump -u username -p -d database_name > structure_backup.sql
-- 备份数据不含结构
mysqldump -u username -p -t database_name > data_backup.sql
-- 恢复数据库
mysql -u username -p database_name < backup.sql
5. 数据导入导出
sql
-- 导出查询结果到CSV(MySQL)
SELECT * INTO OUTFILE '/tmp/result.csv'
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM table_name;
-- 从CSV导入数据(MySQL)
LOAD DATA INFILE '/tmp/result.csv'
INTO TABLE table_name
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES; -- 忽略表头
-- SQL Server导出数据
bcp database_name.schema.table_name out datafile.csv -c -t, -S servername -U username -P password
-- SQL Server导入数据
bcp database_name.schema.table_name in datafile.csv -c -t, -S servername -U username -P password
6. 事务与锁管理
sql
-- 查看当前锁信息(MySQL)
SHOW ENGINE INNODB STATUS;
-- 查看当前事务
SELECT * FROM information_schema.innodb_trx;
-- 查看锁等待
SELECT * FROM information_schema.innodb_lock_waits;
-- 设置事务隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 查看当前隔离级别
SELECT @@tx_isolation;
-- 显示锁定的表
SHOW OPEN TABLES WHERE In_use > 0;
7. 用户与权限管理
sql
-- 创建用户(MySQL)
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
-- 删除用户
DROP USER 'username'@'host';
-- 授权权限
GRANT SELECT, INSERT, UPDATE ON database_name.* TO 'username'@'host';
-- 撤销权限
REVOKE UPDATE ON database_name.* FROM 'username'@'host';
-- 查看用户权限
SHOW GRANTS FOR 'username'@'host';
-- 修改用户密码
ALTER USER 'username'@'host' IDENTIFIED BY 'new_password';
-- 刷新权限
FLUSH PRIVILEGES;
8. 系统信息查询
sql
-- 查看服务器版本
SELECT VERSION();
-- 查看当前时间
SELECT NOW();
-- 查看当前连接数
SHOW STATUS LIKE 'Threads_connected';
-- 查看最大连接数
SHOW VARIABLES LIKE 'max_connections';
-- 查看字符集
SHOW VARIABLES LIKE 'character_set%';
-- 查看排序规则
SHOW VARIABLES LIKE 'collation%';
9. 临时表与变量
sql
-- 创建临时表
CREATE TEMPORARY TABLE temp_table AS SELECT * FROM table_name WHERE 1=0;
-- 插入临时表
INSERT INTO temp_table SELECT * FROM table_name WHERE column1 = 'value';
-- 使用变量(MySQL)
SET @var_name = 100;
SELECT @var_name;
-- 变量在查询中使用
SELECT * FROM table_name WHERE id > @var_name;
10. 存储过程与函数
sql
-- 创建存储过程(MySQL示例)
DELIMITER //
CREATE PROCEDURE GetUserCount(OUT userCount INT)
BEGIN
SELECT COUNT(*) INTO userCount FROM users;
END //
DELIMITER ;
-- 调用存储过程
CALL GetUserCount(@count);
SELECT @count;
-- 创建函数
DELIMITER //
CREATE FUNCTION GetDiscount(price DECIMAL(10,2)) RETURNS DECIMAL(10,2)
BEGIN
DECLARE discount DECIMAL(10,2);
SET discount = price * 0.9;
RETURN discount;
END //
DELIMITER ;
-- 使用函数
SELECT GetDiscount(100);
11. 触发器
sql
-- 创建触发器(MySQL示例)
CREATE TRIGGER before_insert_user
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
SET NEW.created_at = NOW();
END;
-- 删除触发器
DROP TRIGGER before_insert_user;
12. 备份与恢复自动化脚本示例(Linux Shell)
sql
#!/bin/bash
# 自动备份MySQL数据库
DATE=$(date +%F)
BACKUP_DIR="/backup/mysql"
DB_NAME="your_database"
USER="your_user"
PASS="your_password"
mkdir -p $BACKUP_DIR/$DATE
mysqldump -u $USER -p$PASS $DB_NAME > $BACKUP_DIR/$DATE/$DB_NAME.sql
# 删除7天前备份
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} \;
总结优化方式:
1. 索引优化
1.1 合理使用索引
选择性高的列建索引,避免低选择性列(如性别)单独建索引。
联合索引按查询条件顺序创建,遵循最左前缀原则。
覆盖索引:索引包含查询所需所有列,避免回表。
sql
-- 创建联合索引(列顺序重要)
CREATE INDEX idx_name ON table_name(col1, col2);
-- 使用覆盖索引示例
SELECT col1, col2 FROM table_name WHERE col1 = 'value';
1.2 避免索引失效
避免对索引列进行函数操作或隐式类型转换。
避免在索引列上使用<>, NOT IN, IS NULL等导致全表扫描的操作。
避免OR条件导致索引失效,改用UNION。
sql
-- 不要这样,索引失效
SELECT * FROM table WHERE DATE(col_date) = '2023-01-01';
-- 改写为
SELECT * FROM table WHERE col_date >= '2023-01-01' AND col_date < '2023-01-02';
2. 查询重写
*2.1 避免SELECT **
明确列出需要查询的字段,减少IO和网络传输。
sql
-- 不推荐
SELECT * FROM orders WHERE status = 'completed';
-- 推荐
SELECT order_id, customer_id, order_date FROM orders WHERE status = 'completed';
2.2 使用 EXISTS 替代 IN
对于子查询,EXISTS通常比IN性能更好,尤其是子查询结果大时。
sql
-- IN 子查询
SELECT * FROM customers WHERE customer_id IN (SELECT customer_id FROM orders);
-- EXISTS 子查询
SELECT * FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id);
2.3 避免不必要的DISTINCT
DISTINCT会增加排序开销,确认是否真的需要去重。
2.4 使用JOIN代替子查询
子查询有时性能较差,改用JOIN提高效率。
sql
-- 子查询
SELECT name FROM customers WHERE id IN (SELECT customer_id FROM orders WHERE amount > 100);
-- JOIN
SELECT DISTINCT c.name FROM customers c JOIN orders o ON c.id = o.customer_id WHERE o.amount > 100;
3. 执行计划分析
使用EXPLAIN查看SQL执行计划,重点关注:
是否使用索引(key列)
扫描行数(rows列)
连接类型(type列,最好是ref、const,避免ALL)
是否有临时表和文件排序
sql
EXPLAIN SELECT * FROM orders WHERE customer_id = 123;
根据执行计划调整索引和SQL结构。
4. 分区表优化
大表使用分区(按范围、列表、哈希)减少单次扫描数据量。
查询时利用分区裁剪,提升查询效率。
sql
-- MySQL范围分区示例
CREATE TABLE orders (
order_id INT,
order_date DATE,
amount DECIMAL(10,2)
)
PARTITION BY RANGE (YEAR(order_date)) (
PARTITION p2019 VALUES LESS THAN (2020),
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
5. 物化视图(Materialized View)
预计算复杂查询结果,减少实时计算压力。
支持定期刷新。
sql
-- Oracle示例
CREATE MATERIALIZED VIEW mv_sales_summary
REFRESH FAST ON COMMIT
AS
SELECT product_id, SUM(amount) total_amount FROM sales GROUP BY product_id;
6. 并行查询
利用数据库并行执行能力,提升大数据量查询性能。
需配置数据库参数支持。
sql
-- Oracle示例
SELECT /*+ parallel(t,4) */ * FROM large_table t WHERE condition;
7. 缓存利用
利用数据库缓存机制,避免频繁访问磁盘。
通过合理设计SQL和索引,提升缓存命中率。
8. 避免大事务和长事务
大事务会占用大量锁资源,影响并发。
拆分大事务,减少锁等待。
9. 参数化查询与预编译
避免SQL注入,提高执行效率。
sql
-- 伪代码示例
PREPARE stmt FROM 'SELECT * FROM users WHERE id = ?';
EXECUTE stmt USING @user_id;
10. 统计信息及时更新
保证优化器有准确统计信息,避免错误执行计划。
sql
-- MySQL
ANALYZE TABLE table_name;
-- Oracle
EXEC DBMS_STATS.GATHER_TABLE_STATS('schema', 'table_name');
11. 示例综合优化
sql
-- 原始查询(可能全表扫描)
SELECT * FROM orders WHERE DATE(order_date) = '2023-01-01' AND status = 'completed';
-- 优化后
SELECT order_id, customer_id, amount FROM orders
WHERE order_date >= '2023-01-01' AND order_date < '2023-01-02' AND status = 'completed'
AND status = 'completed'
AND customer_id IN (SELECT customer_id FROM customers WHERE vip_flag = 1);
12. 其他实用技巧
避免SELECT DISTINCT + ORDER BY,改用GROUP BY。
避免使用NOT IN,改用LEFT JOIN IS NULL或NOT EXISTS。
避免函数索引列,改写为范围查询。
合理使用覆盖索引,减少回表。
避免过多JOIN,拆分复杂查询。
使用批量插入替代多条单条插入。
合理设置连接池和缓存参数。