baomidou/mybatis-plus · error · MybatisPlusException
非法SQL,SQL未使用到索引, table:{}, columnName:{}
Error message
非法SQL,SQL未使用到索引, table:{}, columnName:{} What it means
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.
Source
Thrown at mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java:249
private void validUseIndex(Table table, String columnName, Connection connection) {
//是否使用索引
boolean useIndexFlag = false;
if (StringUtils.isNotBlank(columnName)) {
String tableName = table.getName();
//表存在的索引
String dbName = getPartItemValue(table, 1);
String catalogName = getPartItemValue(table, 2);
columnName = SqlParserUtils.removeWrapperSymbol(columnName);
List<IndexInfo> indexInfos = getIndexInfos(catalogName, dbName, tableName, connection);
for (IndexInfo indexInfo : indexInfos) {
if (indexInfo.getColumnName().equalsIgnoreCase(columnName)) {
useIndexFlag = true;
break;
}
}
}
if (!useIndexFlag) {
throw new MybatisPlusException("非法SQL,SQL未使用到索引, table:" + table.getName() + ", columnName:" + columnName);
}
}
private String getPartItemValue(Table table, int index) {
return index < table.getNameParts().size() ? table.getNameParts().get(index) : null;
}
/**
* 验证where条件的字段,是否有not、or等等,并且where的第一个字段,必须使用索引
*
* @param expression ignore
* @param table ignore
* @param connection ignore
*/
private void validWhere(Expression expression, Table table, Connection connection) {
validWhere(expression, table, null, connection);
}
View on GitHub (pinned to bf67d90747)
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).
Example fix
-- before SELECT * FROM orders WHERE remark = ?; -- remark unindexed -- after CREATE INDEX idx_orders_remark ON orders(remark); SELECT * FROM orders WHERE remark = ?;
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight in CI/dev: assert the first WHERE column of each mapped query has an index // Example with information_schema (MySQL): // SELECT 1 FROM information_schema.statistics // WHERE table_schema = ? AND table_name = ? AND index_columns... CONTAINS first_where_column; // Fail the build when the leading predicate column is not indexed.
Try / catch
try {
mapper.selectList(wrapper);
} catch (MybatisPlusException e) {
if (String.valueOf(e.getMessage()).contains("SQL未使用到索引")) {
log.error("create index for the named table/column in message: {}", e.getMessage());
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- 非法SQL,where条件中不能使用数据库函数,错误函数信息:{}
- 非法SQL,where条件中不能使用【or】关键字,错误or信息:{}
- 非法SQL,where条件中不能使用【!=】关键字,错误!=信息:{}
- 非法SQL,where条件中不能使用子查询,错误子查询SQL信息:{}
- 非法SQL,where条件中不能使用【or】关键字,错误or信息:{}
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/ec96e9f00004df54.
Report an issue: GitHub.