1. 为什么你需要这份SQL速查表?
作为一名常年与数据库打交道的开发者,我深知在不同数据库间切换的痛苦。记得有一次项目紧急切换数据库,我在MySQL中流畅使用的分页语法到了Oracle里完全失效,整整浪费了两小时排查问题。这种经历促使我整理出这份多数据库适配的SQL速查表。
提示:好的速查表应该像瑞士军刀一样,在关键时刻能快速解决特定问题,而不是把所有功能都堆砌在一起。
传统速查表最大的问题是"一刀切"——它们要么只针对单一数据库,要么对多数据库的支持停留在表面。而实际开发中,我们经常需要:
- 快速确认不同数据库的语法差异(比如分页查询)
- 查找特定场景的最佳实践(比如递归查询组织架构)
- 避免常见的性能陷阱(如索引失效的情况)
2. 速查表设计哲学
2.1 模块化设计
我把速查表划分为6个核心模块:
- 基础查询(SELECT)
- 数据操作(INSERT/UPDATE/DELETE)
- 表结构管理(DDL)
- 事务控制
- 高级分析(窗口函数、CTE)
- 性能优化技巧
每个模块都采用"语法格式+最小示例+差异对比"的结构。例如在分页查询部分:
sql复制-- MySQL/PostgreSQL
SELECT * FROM products ORDER BY price DESC LIMIT 10 OFFSET 20;
-- SQL Server
SELECT * FROM products ORDER BY price DESC OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
-- Oracle (12c+)
SELECT * FROM products ORDER BY price DESC FETCH FIRST 10 ROWS ONLY OFFSET 20 ROWS;
2.2 差异可视化
我用三种标记来区分内容:
- 🔴 关键差异:必须注意的语法区别
- 🟡 行为差异:相同语法但表现不同
- 🟢 通用语法:所有数据库通用
对于复杂的差异,使用对比表格:
| 功能 | MySQL | PostgreSQL | Oracle |
|---|---|---|---|
| 字符串连接 | CONCAT() | || 或 CONCAT() | || 或 CONCAT() |
| 当前时间 | NOW() | NOW() | SYSDATE |
| 自增字段 | AUTO_INCREMENT | SERIAL | SEQUENCE+TRIGGER |
3. 核心内容精要
3.1 基础查询的隐藏技巧
3.1.1 WHERE条件的优化写法
很多开发者不知道,WHERE条件的顺序会影响性能:
sql复制-- 较差写法(先处理OR)
SELECT * FROM orders
WHERE status = 'shipped' OR customer_id = 100 AND amount > 500;
-- 优化写法(明确优先级)
SELECT * FROM orders
WHERE (status = 'shipped') OR (customer_id = 100 AND amount > 500);
3.1.2 分页查询的陷阱
分页查询时最容易犯的两个错误:
- 忘记ORDER BY导致结果随机
- OFFSET过大时性能骤降
解决方案:
sql复制-- 优化大偏移量分页(使用游标)
SELECT * FROM products
WHERE id > last_seen_id -- 记住上一页最后一条记录的ID
ORDER BY id
LIMIT 10;
3.2 数据操作的进阶用法
3.2.1 批量更新的艺术
不同数据库的批量更新语法差异很大:
sql复制-- MySQL多表更新
UPDATE users u
JOIN user_updates tmp ON u.id = tmp.user_id
SET u.name = tmp.new_name;
-- PostgreSQL的CTE更新
WITH updates AS (
SELECT user_id, new_name FROM user_updates
)
UPDATE users
SET name = updates.new_name
FROM updates
WHERE users.id = updates.user_id;
-- Oracle的MERGE语法
MERGE INTO users u
USING user_updates tmp
ON (u.id = tmp.user_id)
WHEN MATCHED THEN
UPDATE SET u.name = tmp.new_name;
3.2.2 删除数据的正确姿势
删除数据时常见的坑:
- 忘记加WHERE条件(全表删除!)
- 大表删除导致锁表
安全做法:
sql复制-- 先查询确认
SELECT COUNT(*) FROM orders WHERE status = 'cancelled';
-- 分批删除
DELETE FROM orders
WHERE status = 'cancelled' AND id < 10000
LIMIT 1000; -- MySQL语法
4. 高级查询实战
4.1 窗口函数的魔法
窗口函数是数据分析的利器,但语法晦涩。我整理了几个经典模式:
sql复制-- 计算移动平均(过去7天)
SELECT
date,
sales,
AVG(sales) OVER (ORDER BY date RANGE BETWEEN 6 PRECEDING AND CURRENT ROW) AS moving_avg
FROM daily_sales;
-- 排名与分组排名
SELECT
product_id,
category,
sales,
RANK() OVER (ORDER BY sales DESC) AS overall_rank,
RANK() OVER (PARTITION BY category ORDER BY sales DESC) AS category_rank
FROM products;
4.2 递归查询解决层级数据
处理树形数据是SQL的难点,递归CTE可以优雅解决:
sql复制-- 查询组织架构(PostgreSQL/Oracle/SQL Server)
WITH RECURSIVE org_tree AS (
-- 基础查询:找到根节点
SELECT id, name, parent_id, 1 AS level
FROM organization
WHERE parent_id IS NULL
UNION ALL
-- 递归查询:连接子节点
SELECT o.id, o.name, o.parent_id, t.level + 1
FROM organization o
JOIN org_tree t ON o.parent_id = t.id
)
SELECT * FROM org_tree ORDER BY level, id;
5. 性能优化锦囊
5.1 索引使用原则
创建索引的黄金法则:
- 为WHERE、JOIN、ORDER BY的列建索引
- 避免过度索引(影响写入性能)
- 注意复合索引的顺序
sql复制-- 好的复合索引(最常用字段在前)
CREATE INDEX idx_user_region_age ON users(region, age);
-- 差的索引设计
CREATE INDEX idx_user_age_region ON users(age, region); -- 如果很少单独按age查询
5.2 执行计划分析
学会看执行计划是进阶必备技能:
sql复制-- MySQL
EXPLAIN SELECT * FROM users WHERE age > 30;
-- PostgreSQL
EXPLAIN ANALYZE SELECT * FROM users WHERE age > 30;
-- Oracle
EXPLAIN PLAN FOR SELECT * FROM users WHERE age > 30;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
关键指标:
- type/index(访问类型)
- rows(预估行数)
- Extra(额外信息)
6. 团队协作建议
6.1 命名规范模板
统一的命名规范能大幅提高可维护性:
| 对象类型 | 前缀 | 示例 |
|---|---|---|
| 表 | t_ (可选) | t_order / order |
| 视图 | v_ | v_sales_report |
| 索引 | idx_字段名 | idx_user_email |
| 序列 | seq_ | seq_order_id |
6.2 常用脚本模板
把团队常用脚本标准化:
sql复制-- 数据库备份脚本模板
CREATE TABLE backup_${date}_${table} AS SELECT * FROM ${table};
-- 数据清洗模板
WITH dirty_data AS (
SELECT * FROM raw_data WHERE ${quality_condition}
)
INSERT INTO clean_data
SELECT ${columns} FROM dirty_data
WHERE ${business_rules};
7. 维护与更新策略
7.1 版本控制
把速查表放在Git仓库中,按数据库版本分支管理:
code复制/sql-cheatsheet
├── main.md # 通用内容
├── mysql-8.0.md # MySQL特有
├── pg-14.md # PostgreSQL特有
└── oracle-19c.md # Oracle特有
7.2 更新机制
建立更新触发条件:
- 新项目引入新数据库时
- 数据库版本升级后
- 发现现有内容错误时
- 团队新增常用脚本时
8. 实战案例分享
8.1 多数据库迁移方案
最近帮客户从SQL Server迁移到PostgreSQL时,我们整理了这样的转换表:
| 原语法(SQL Server) | 目标语法(PostgreSQL) | 注意事项 |
|---|---|---|
| TOP 10 | LIMIT 10 | 必须配合ORDER BY |
| ISNULL() | COALESCE() | 参数完全兼容 |
| GETDATE() | NOW() | 精度略有不同 |
8.2 性能问题排查
曾遇到一个分页查询在测试环境很快,生产环境却超时的问题。最终发现是Oracle的ROWNUM在子查询中的特殊行为:
sql复制-- 错误写法(性能差)
SELECT * FROM (
SELECT t.*, ROWNUM rn FROM big_table t
WHERE ROWNUM <= 10000
) WHERE rn > 9000;
-- 优化写法
SELECT * FROM (
SELECT /*+ FIRST_ROWS(100) */ t.*, ROWNUM rn
FROM (
SELECT * FROM big_table ORDER BY create_time DESC
) t
WHERE ROWNUM <= 10000
) WHERE rn > 9000;
9. 资源推荐
9.1 官方文档精华
每个数据库都有独特的宝藏功能,值得从官方文档挖掘:
- MySQL的优化器提示(/*+ HINT */)
- PostgreSQL的JSONB功能
- Oracle的分析函数扩展
9.2 工具推荐
我的日常SQL工具箱:
- 数据库客户端:DBeaver(多数据库支持)
- 性能分析:Percona Toolkit(MySQL)、pgBadger(PostgreSQL)
- 差异比对:SchemaCrawler(跨数据库元数据比较)
10. 最后建议
根据我多年使用速查表的经验,最重要的不是记住所有语法,而是:
- 知道常见任务的实现模式
- 快速定位关键差异点
- 理解背后的原理(为什么这样设计)
建议把这份速查表打印出来贴在工位,但更重要的是在实际项目中不断补充自己的经验笔记。每次解决一个棘手的SQL问题后,花5分钟把解决方案添加到个人速查表中,长期积累下来,你会拥有最适合自己的终极参考指南。