{"record":{"id":"5743986b2abe3589","repo":"pagehelper-org/Mybatis-PageHelper","slug":"the-pagination-statement-must-be-a-select-query","errorCode":null,"errorMessage":"the pagination statement must be a select query!","messagePattern":"the pagination statement must be a select query!","errorType":"exception","errorClass":"PageException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/github/pagehelper/parser/defaults/DefaultSqlServerSqlParser.java","lineNumber":110,"sourceCode":"\n    /**\n     * 转换为分页语句\n     *\n     * @param sql\n     * @param offset\n     * @param limit\n     * @return\n     */\n    public String convertToPageSql(String sql, Integer offset, Integer limit) {\n        //解析SQL\n        Statement stmt;\n        try {\n            stmt = SqlParserUtil.parse(sql);\n        } catch (Throwable e) {\n            throw new PageException(\"The SQL statement cannot be converted to a pagination query!\", e);\n        }\n        if (!(stmt instanceof Select)) {\n            throw new PageException(\"the pagination statement must be a select query!\");\n        }\n        //获取分页查询的select\n        Select pageSelect = getPageSelect((Select) stmt);\n        String pageSql = pageSelect.toString();\n        //缓存移到外面了，所以不替换参数\n        if (offset != null) {\n            pageSql = pageSql.replace(START_ROW, String.valueOf(offset));\n        }\n        if (limit != null) {\n            pageSql = pageSql.replace(PAGE_SIZE, String.valueOf(limit));\n        }\n        return pageSql;\n    }\n\n    /**\n     * 获取一个外层包装的TOP查询\n     *\n     * @param select","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/pagehelper-org/Mybatis-PageHelper/blob/c692616c5bc95b41aa779b502f991825c8e5acbc/src/main/java/com/github/pagehelper/parser/defaults/DefaultSqlServerSqlParser.java#L92-L128","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nPageHelper.startPage(1, 10);\nuserMapper.deleteAll(); // not a select -> throws\n// after\nPageHelper.clearPage();\nPageHelper.startPage(1, 10);\nList<User> users = userMapper.selectUsers();","handlingStrategy":"type-guard","validationCode":"Statement stmt = JSqlParserUtil.parse(sql);\nif (!(stmt instanceof Select)) {\n    throw new IllegalArgumentException(\"pagination requires SELECT, got: \" + stmt.getClass().getSimpleName());\n}","typeGuard":"boolean isPaginatable(Statement stmt) { return stmt instanceof Select; }","tryCatchPattern":"try { PageHelper.startPage(page, size); return mapper.selectX(); } catch (PageException e) {\n    PageHelper.clearPage(); throw e;\n}","preventionTips":["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"],"tags":["java","pagehelper","sqlserver","unsupported-statement"],"backgroundTag":"invalid-argument-value","analyzedSha":"c692616c5bc95b41aa779b502f991825c8e5acbc","analyzedAt":"2026-09-08T03:50:49.192Z","contentChangedAt":"2026-09-08T03:50:49.192Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}