{"record":{"id":"ec96e9f00004df54","repo":"baomidou/mybatis-plus","slug":"sql-sql-table-columnname","errorCode":null,"errorMessage":"非法SQL，SQL未使用到索引, table:{}, columnName:{}","messagePattern":"非法SQL，SQL未使用到索引, table:(.+?), columnName:(.+?)","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":249,"sourceCode":"    private void validUseIndex(Table table, String columnName, Connection connection) {\n        //是否使用索引\n        boolean useIndexFlag = false;\n        if (StringUtils.isNotBlank(columnName)) {\n            String tableName = table.getName();\n            //表存在的索引\n            String dbName = getPartItemValue(table, 1);\n            String catalogName = getPartItemValue(table, 2);\n            columnName = SqlParserUtils.removeWrapperSymbol(columnName);\n            List<IndexInfo> indexInfos = getIndexInfos(catalogName, dbName, tableName, connection);\n            for (IndexInfo indexInfo : indexInfos) {\n                if (indexInfo.getColumnName().equalsIgnoreCase(columnName)) {\n                    useIndexFlag = true;\n                    break;\n                }\n            }\n        }\n        if (!useIndexFlag) {\n            throw new MybatisPlusException(\"非法SQL，SQL未使用到索引, table:\" + table.getName() + \", columnName:\" + columnName);\n        }\n    }\n\n    private String getPartItemValue(Table table, int index) {\n        return index < table.getNameParts().size() ? table.getNameParts().get(index) : null;\n    }\n\n    /**\n     * 验证where条件的字段，是否有not、or等等，并且where的第一个字段，必须使用索引\n     *\n     * @param expression ignore\n     * @param table      ignore\n     * @param connection ignore\n     */\n    private void validWhere(Expression expression, Table table, Connection connection) {\n        validWhere(expression, table, null, connection);\n    }\n","sourceCodeStart":231,"sourceCodeEnd":267,"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#L231-L267","documentation":"IllegalSQLInnerInterceptor (jsqlparser 4.9) index check: after loading the table's index metadata via JDBC DatabaseMetaData, if the first WHERE column does not match any indexed column, it throws MybatisPlusException naming the table and column. The policy requires the leading predicate column to be covered by an index.","triggerScenarios":"Executing a query whose first WHERE column has no index (WHERE unindexed_col = ?) against a table while the interceptor is registered; index metadata is fetched per catalog/schema via getIndexInfos, so an empty/failed metadata load also results in useIndexFlag=false.","commonSituations":"Querying on a newly added column before an index was created; DB user lacking metadata/index privileges so the index list comes back empty; multi-part table names (catalog.schema.table) where getPartItemValue mis-resolves the parts against your database.","solutions":["Add an index on the offending column (message names table + column exactly): CREATE INDEX idx ON t(col).","Reorder the WHERE so the indexed column comes first if another predicate is selective and indexed.","Grant the DB user INDEX metadata visibility or verify the index exists from the same account the app uses.","Opt the statement out with @InterceptorIgnore(illegalSql = \"true\") when the unindexed access is intentional (small table, report query)."],"exampleFix":"-- before\nSELECT * FROM orders WHERE remark = ?; -- remark unindexed\n\n-- after\nCREATE INDEX idx_orders_remark ON orders(remark);\nSELECT * FROM orders WHERE remark = ?;","handlingStrategy":"validation","validationCode":"// Pre-flight in CI/dev: assert the first WHERE column of each mapped query has an index\n// Example with information_schema (MySQL):\n// SELECT 1 FROM information_schema.statistics\n//  WHERE table_schema = ? AND table_name = ? AND index_columns... CONTAINS first_where_column;\n// Fail the build when the leading predicate column is not indexed.","typeGuard":null,"tryCatchPattern":"try {\n    mapper.selectList(wrapper);\n} catch (MybatisPlusException e) {\n    if (String.valueOf(e.getMessage()).contains(\"SQL未使用到索引\")) {\n        log.error(\"create index for the named table/column in message: {}\", e.getMessage());\n    }\n}","preventionTips":["Add an index whenever a new WHERE column enters production SQL (schema-migration checklist).","Order predicates so an indexed, selective column leads the WHERE clause.","Ensure the app's DB account can read index metadata; otherwise the check always fails."],"tags":["mybatis-plus","sql-parsing","interceptor","index","policy","jsqlparser"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}