MyCATApache/Mycat-Server · error · java.sql.SQLNonTransientException
无效的SQL语句
Error message
无效的SQL语句:%s
What it means
Mycat's batch-insert/ER routing entry (routeByER) parses the SQL with Druid's MySqlStatementParser and requires at least one parsed statement. If the parser yields null or an empty list — i.e. the input isn't a parsable MySQL statement — it throws SQLNonTransientException with '无效的SQL语句' (invalid SQL statement) plus the original text.
Solutions
- Log and inspect the exact origSQL sent to Mycat; fix the client to send a valid, non-empty INSERT statement
- Strip comments and empty segments before sending multi-statement batches
- Verify the SQL syntax is valid MySQL and supported by the bundled Druid parser version
- Check for encoding issues (e.g. BOM or binary garbage) that empty the parse result
Example fix
// before String sql = "; ; -- just a comment"; sendToMycat(sql); // 无效的SQL语句 // after String sql = "INSERT INTO t(id,name) VALUES (1,'a')";
Defensive patterns
Strategy: try-catch
Validate before calling
// Client-side guard: ensure a non-empty, comment-free statement before sending
String trimmed = sql.replaceAll("(--[^\\n]*|/\\*.*?\\*/)", " ").trim();
if (trimmed.isEmpty() || trimmed.equals(";")) throw new IllegalArgumentException("empty SQL"); Try / catch
catch (SQLNonTransientException e) { if (e.getMessage().startsWith("无效的SQL语句")) { log.error("unparsable SQL sent to Mycat: {}", sql, e); } throw e; } Prevention
- Strip comments and empty statements from multi-statement batches client-side
- Test generated SQL against the bundled Druid parser version
- Guard against empty/null SQL strings in DB-access wrappers
When it happens
Trigger: Calling RouterUtil's multi-statement/batch insert routing path with a string that parses to no statements: empty/whitespace SQL, only comments, or syntax the Druid parser rejects so parseStatementList returns nothing.
Common situations: Client sending empty statements separated by ';'; SQL containing only comments or a trailing comment; drivers stripping the statement before send; non-INSERT statements reaching the insert-routing path; charset/encoding corruption mangling the text.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- ER_PARSE_ERROR
- schema: ,table: ,sql: is not allowed,because table is…
- can't find hint datanode
- can't find hint schema
- Multi statements is not supported,use single statement…
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/f48c52b59f28658d.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1907
* @param origSQL
* @param sc
* @return
* @throws SQLNonTransientException
*
* 备注说明:
* edit by ding.w at 2017.4.28, 主要处理 CLIENT_MULTI_STATEMENTS(insert into ; insert into)的情况
* 目前仅支持mysql,并COM_QUERY请求包中的所有insert语句要么全部是er表,要么全部不是
*
*
*/
public static boolean processERChildTable(final SchemaConfig schema, final String origSQL,
final ServerConnection sc) throws SQLNonTransientException {
MySqlStatementParser parser = new MySqlStatementParser(origSQL);
List<SQLStatement> statements = parser.parseStatementList();
if(statements == null || statements.isEmpty() ) {
throw new SQLNonTransientException(String.format("无效的SQL语句:%s", origSQL));
}
boolean erFlag = false; //是否是er表
for(SQLStatement stmt : statements ) {
MySqlInsertStatement insertStmt = (MySqlInsertStatement) stmt;
String tableName = insertStmt.getTableName().getSimpleName().toUpperCase();
final TableConfig tc = schema.getTables().get(tableName);
if (null != tc && tc.isChildTable()) {
erFlag = true;
String sql = insertStmt.toString();
final RouteResultset rrs = new RouteResultset(sql, ServerParse.INSERT);
String joinKey = tc.getJoinKey();
//因为是Insert语句,用MySqlInsertStatement进行parse
// MySqlInsertStatement insertStmt = (MySqlInsertStatement) (new MySqlStatementParser(origSQL)).parseInsert();
View on GitHub (pinned to 65f8d8beb7)