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

  1. Log and inspect the exact origSQL sent to Mycat; fix the client to send a valid, non-empty INSERT statement
  2. Strip comments and empty segments before sending multi-statement batches
  3. Verify the SQL syntax is valid MySQL and supported by the bundled Druid parser version
  4. 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

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


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)