在数据库查询中,分页(Pagination) 是一项基本且关键的技术,特别是在Web应用、数据分析和大规模数据查询场景中。合理的分页查询可以显著提升性能,减少不必要的数据传输,并优化用户体验。
本文将从 SQL分页的基础语法 讲起,逐步深入探讨 不同数据库的分页实现方式,并给出 最佳实践建议,帮助开发者高效、安全地实现分页功能。
最常见的分页方式是使用 LIMIT 子句,有两种写法:
LIMIT offset, countSELECT * FROM users
ORDER BY id
LIMIT 10, 20; -- 跳过前10条,返回接下来的20条LIMIT count OFFSET offset(更清晰)SELECT * FROM users
ORDER BY id
LIMIT 20 OFFSET 10; -- 同上,但可读性更好在实际开发中,分页参数通常是动态传入的(如前端传递 page 和 pageSize)。例如,在 MyBatis 或 JDBC 中,可以这样写:
SELECT * FROM products
ORDER BY create_time DESC
LIMIT #{offset}, #{pageSize};其中:
offset = (page - 1) * pageSize(如果 page 从 1 开始计数)pageSize 是每页记录数不同数据库对分页的支持略有不同,以下是几种主流数据库的分页语法对比。
-- 方式1
SELECT * FROM table LIMIT 10, 20;
-- 方式2(推荐)
SELECT * FROM table LIMIT 20 OFFSET 10;SQL Server 使用 OFFSET-FETCH 语法:
SELECT * FROM table
ORDER BY id
OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY;Oracle 12c 开始支持 OFFSET-FETCH:
SELECT * FROM table
ORDER BY id
OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY;-- 第一页(1-20条)
SELECT * FROM (
SELECT t.*, ROWNUM rn FROM (
SELECT * FROM table ORDER BY id
) t WHERE ROWNUM <= 20
) WHERE rn > 0;
-- 第二页(21-40条)
SELECT * FROM (
SELECT t.*, ROWNUM rn FROM (
SELECT * FROM table ORDER BY id
) t WHERE ROWNUM <= 40
) WHERE rn > 20;ORDER BY 使用分页查询必须指定排序规则,否则数据可能随机返回,导致分页混乱:
-- ✅ 正确
SELECT * FROM users ORDER BY id LIMIT 10, 20;
-- ❌ 错误(数据可能不一致)
SELECT * FROM users LIMIT 10, 20;当 offset 很大时(如 LIMIT 100000, 20),数据库仍然需要扫描前 100000 条记录,性能极差。
优化方案:
WHERE + 索引列SELECT * FROM users
WHERE id > 100000 -- 假设id是自增主键
ORDER BY id
LIMIT 20;JOIN 优化SELECT t.* FROM users t
JOIN (SELECT id FROM users ORDER BY id LIMIT 100000, 20) tmp
ON t.id = tmp.id;方案 | 优点 | 缺点 |
|---|---|---|
前端分页(一次性加载所有数据) | 减少HTTP请求 | 数据量大时内存占用高 |
后端分页(每次请求部分数据) | 节省带宽,适合大数据 | 需要多次请求 |
推荐:
通常需要先查询总记录数:
SELECT COUNT(*) FROM users;然后在代码中计算:
int totalPages = (totalRecords + pageSize - 1) / pageSize;避免SQL注入,应使用 参数化查询(PreparedStatement):
// Java(JDBC)
String sql = "SELECT * FROM users LIMIT ?, ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, offset);
stmt.setInt(2, pageSize);如果 offset 超过总记录数,应返回空列表,而不是报错。
关键点 | 说明 |
|---|---|
基础语法 | LIMIT offset, count 或 LIMIT count OFFSET offset |
数据库差异 | MySQL/PostgreSQL 用 LIMIT,SQL Server/Oracle 用 OFFSET-FETCH |
优化大偏移量 | 使用 WHERE 或 JOIN 减少扫描行数 |
排序关键 | 必须搭配 ORDER BY,否则分页可能混乱 |
安全分页 | 使用参数化查询,避免SQL注入 |
最佳实践推荐:
LIMIT #{pageSize} OFFSET #{offset} 语法(更清晰)。LIMIT 100000, 20 这样的深分页,改用 WHERE id > last_id。希望本文能帮助你掌握SQL分页的核心技术,并在实际项目中灵活运用! �