{"record":{"id":"6e1d16d786a8f550","repo":"baomidou/mybatis-plus","slug":"sql-where-sql","errorCode":null,"errorMessage":"非法SQL，where条件中不能使用子查询，错误子查询SQL信息：{}","messagePattern":"非法SQL，where条件中不能使用子查询，错误子查询SQL信息：(.+?)","errorType":"exception","errorClass":"MybatisPlusException","httpStatus":null,"severity":"error","filePath":"mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java","lineNumber":192,"sourceCode":"        if (expression instanceof OrExpression) {\n            OrExpression orExpression = (OrExpression) expression;\n            throw new MybatisPlusException(\"非法SQL，where条件中不能使用【or】关键字，错误or信息：\" + orExpression.toString());\n        } else if (expression instanceof NotEqualsTo) {\n            NotEqualsTo notEqualsTo = (NotEqualsTo) expression;\n            throw new MybatisPlusException(\"非法SQL，where条件中不能使用【!=】关键字，错误!=信息：\" + notEqualsTo.toString());\n        } else if (expression instanceof BinaryExpression) {\n            BinaryExpression binaryExpression = (BinaryExpression) expression;\n            // TODO 升级 jsqlparser 后待实现\n//            if (binaryExpression.isNot()) {\n//                throw new MybatisPlusException(\"非法SQL，where条件中不能使用【not】关键字，错误not信息：\" + binaryExpression.toString());\n//            }\n            if (binaryExpression.getLeftExpression() instanceof Function) {\n                Function function = (Function) binaryExpression.getLeftExpression();\n                throw new MybatisPlusException(\"非法SQL，where条件中不能使用数据库函数，错误函数信息：\" + function.toString());\n            }\n            if (binaryExpression.getRightExpression() instanceof Subtraction) {\n                Subtraction subSelect = (Subtraction) binaryExpression.getRightExpression();\n                throw new MybatisPlusException(\"非法SQL，where条件中不能使用子查询，错误子查询SQL信息：\" + subSelect.toString());\n            }\n        } else if (expression instanceof InExpression) {\n            InExpression inExpression = (InExpression) expression;\n            if (inExpression.getRightExpression() instanceof Subtraction) {\n                Subtraction subSelect = (Subtraction) inExpression.getRightExpression();\n                throw new MybatisPlusException(\"非法SQL，where条件中不能使用子查询，错误子查询SQL信息：\" + subSelect.toString());\n            }\n        }\n\n    }\n\n    /**\n     * 如果SQL用了 left Join，验证是否有or、not等等，并且验证是否使用了索引\n     *\n     * @param joins      ignore\n     * @param table      ignore\n     * @param connection ignore\n     */","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/baomidou/mybatis-plus/blob/bf67d907478c724120bf76292da54abf9e73c2b3/mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java#L174-L210","documentation":"IllegalSQLInnerInterceptor (jsqlparser 4.9) throws when the RIGHT side of a binary WHERE condition is a Subtraction node. The interceptor treats an arithmetic expression on the value side (col = a - b, a pattern that often appears with subquery rewrites or dynamic SQL) as a forbidden subquery-like construct and rejects it with the expression text appended. Note: this check keys on jsqlparser's Subtraction class, so it actually fires for '-' expressions on the right side.","triggerScenarios":"SQL like WHERE amount = price - discount (or a subselect rewritten/normalized as subtraction) in a binary comparison, executed with the interceptor registered.","commonSituations":"Wrapper .apply(\"amount = price - discount\") fragments; hand-written SQL with arithmetic on the right of a comparison; jsqlparser's model making this branch overlap with subquery detection after version changes.","solutions":["Compute the arithmetic in application code and bind the result as a parameter: WHERE amount = ?.","If the expression must stay in SQL, annotate the mapper method with @InterceptorIgnore(illegalSql = \"true\").","If you genuinely need a scalar subquery there, it is disallowed by policy — refactor to two statements or a JOIN."],"exampleFix":"-- before\nWHERE amount = price - discount\n\n-- after\n-- compute (price - discount) in Java, then\nWHERE amount = #{computedValue}","handlingStrategy":"validation","validationCode":"// CI guard: reject arithmetic/subquery-like right-hand expressions in WHERE\n// git grep -nE \"=\\\\s*\\\\w+\\\\s*-\\\\s*\\\\w+\" -- src/main/resources/mapper\n// prefer parameter placeholders: WHERE amount = #{computed}","typeGuard":null,"tryCatchPattern":"try {\n    mapper.selectList(wrapper);\n} catch (MybatisPlusException e) {\n    if (String.valueOf(e.getMessage()).contains(\"不能使用子查询\")) {\n        log.error(\"move computation/subquery to application side: {}\", e.getMessage());\n    }\n}","preventionTips":["Bind computed values as parameters instead of inline arithmetic in SQL.","Avoid .apply() with raw expressions; compute in Java.","Mark intentional exceptions with @InterceptorIgnore and document why."],"tags":["mybatis-plus","sql-parsing","interceptor","policy","jsqlparser"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}