pagehelper-org/Mybatis-PageHelper · error · PageException
the pagination statement must be a select query!
Error message
the pagination statement must be a select query!
What it means
Thrown when the SQL Server pagination parser receives SQL that parses successfully but is not a SELECT statement. Only SELECT queries can be converted to the ROW_NUMBER-based pagination form; other statements are rejected.
Solutions
- Ensure PageHelper.startPage is called immediately before the SELECT and the very next statement is the query
- Clear/avoid leaked ThreadLocal PageContext (PageHelper.clearPage()) when a query is skipped
- Only apply the sqlserver dialect to SELECT statements; paginate updates differently
- Check mapper call order so startPage is never followed by a non-select
Example fix
// before PageHelper.startPage(1, 10); userMapper.deleteAll(); // not a select -> throws // after PageHelper.clearPage(); PageHelper.startPage(1, 10); List<User> users = userMapper.selectUsers();
Defensive patterns
Strategy: type-guard
Validate before calling
Statement stmt = JSqlParserUtil.parse(sql);
if (!(stmt instanceof Select)) {
throw new IllegalArgumentException("pagination requires SELECT, got: " + stmt.getClass().getSimpleName());
} Type guard
boolean isPaginatable(Statement stmt) { return stmt instanceof Select; } Try / catch
try { PageHelper.startPage(page, size); return mapper.selectX(); } catch (PageException e) {
PageHelper.clearPage(); throw e;
} Prevention
- Always call startPage immediately before the SELECT it applies to
- Call PageHelper.clearPage() in finally/error paths to avoid leaked context
- Never paginate INSERT/UPDATE/DELETE/EXEC statements
- Configure the plugin only on select-statement intercept paths
When it happens
Trigger: Calling pagination with the sqlserver dialect on a non-SELECT statement such as INSERT, UPDATE, DELETE, EXEC, or CALL, e.g. accidentally invoking startPage before an update.
Common situations: startPage() left in effect from a previous call and then an UPDATE executes; pagination applied to stored-procedure calls; helper configured globally so non-select statements hit the converter.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- The SQL statement cannot be converted to a pagination query!
- The pagination statement already contains the top, and can…
- Make sure the Dialect implementation class configured by…
- The order by in the original SQL
- order by [ ] has a risk of SQL injection, if you want to…
AI-assisted analysis of pagehelper-org/Mybatis-PageHelper@c692616c5b (2026-09-08).
Data as JSON: /api/errors/5743986b2abe3589.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/com/github/pagehelper/parser/defaults/DefaultSqlServerSqlParser.java:110
/**
* 转换为分页语句
*
* @param sql
* @param offset
* @param limit
* @return
*/
public String convertToPageSql(String sql, Integer offset, Integer limit) {
//解析SQL
Statement stmt;
try {
stmt = SqlParserUtil.parse(sql);
} catch (Throwable e) {
throw new PageException("The SQL statement cannot be converted to a pagination query!", e);
}
if (!(stmt instanceof Select)) {
throw new PageException("the pagination statement must be a select query!");
}
//获取分页查询的select
Select pageSelect = getPageSelect((Select) stmt);
String pageSql = pageSelect.toString();
//缓存移到外面了,所以不替换参数
if (offset != null) {
pageSql = pageSql.replace(START_ROW, String.valueOf(offset));
}
if (limit != null) {
pageSql = pageSql.replace(PAGE_SIZE, String.valueOf(limit));
}
return pageSql;
}
/**
* 获取一个外层包装的TOP查询
*
* @param selectView on GitHub (pinned to c692616c5b)