{"record":{"id":"f48c52b59f28658d","repo":"MyCATApache/Mycat-Server","slug":"sql-s","errorCode":null,"errorMessage":"无效的SQL语句:%s","messagePattern":"无效的SQL语句:(.+?)","errorType":"exception","errorClass":"java.sql.SQLNonTransientException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/util/RouterUtil.java","lineNumber":1907,"sourceCode":"\t * @param origSQL\r\n\t * @param sc\r\n\t * @return\r\n\t * @throws SQLNonTransientException\r\n\t *\r\n\t * 备注说明：\r\n\t *     edit by ding.w at 2017.4.28, 主要处理 CLIENT_MULTI_STATEMENTS(insert into ; insert into)的情况\r\n\t *     目前仅支持mysql,并COM_QUERY请求包中的所有insert语句要么全部是er表，要么全部不是\r\n\t *\r\n\t *\r\n\t */\r\n\tpublic static boolean processERChildTable(final SchemaConfig schema, final String origSQL,\r\n\t\t\tfinal ServerConnection sc) throws SQLNonTransientException {\r\n\r\n\t\tMySqlStatementParser parser = new MySqlStatementParser(origSQL);\r\n\t\tList<SQLStatement> statements = parser.parseStatementList();\r\n\r\n\t\tif(statements == null || statements.isEmpty() ) {\r\n\t\t\tthrow new SQLNonTransientException(String.format(\"无效的SQL语句:%s\", origSQL));\r\n\t\t}\r\n\r\n\r\n\t\tboolean erFlag = false; //是否是er表\r\n\t\tfor(SQLStatement stmt : statements ) {\r\n\t\t\tMySqlInsertStatement insertStmt = (MySqlInsertStatement) stmt;\r\n\t\t\tString tableName = insertStmt.getTableName().getSimpleName().toUpperCase();\r\n\t\t\tfinal TableConfig tc = schema.getTables().get(tableName);\r\n\r\n\t\t\tif (null != tc && tc.isChildTable()) {\r\n\t\t\t\terFlag = true;\r\n\r\n\t\t\t\tString sql = insertStmt.toString();\r\n\r\n\t\t\t\tfinal RouteResultset rrs = new RouteResultset(sql, ServerParse.INSERT);\r\n\t\t\t\tString joinKey = tc.getJoinKey();\r\n\t\t\t\t//因为是Insert语句，用MySqlInsertStatement进行parse\r\n//\t\t\t\tMySqlInsertStatement insertStmt = (MySqlInsertStatement) (new MySqlStatementParser(origSQL)).parseInsert();\r","sourceCodeStart":1889,"sourceCodeEnd":1925,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/util/RouterUtil.java#L1889-L1925","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nString sql = \"; ; -- just a comment\";\nsendToMycat(sql); // 无效的SQL语句\n// after\nString sql = \"INSERT INTO t(id,name) VALUES (1,'a')\";","handlingStrategy":"try-catch","validationCode":"// Client-side guard: ensure a non-empty, comment-free statement before sending\nString trimmed = sql.replaceAll(\"(--[^\\\\n]*|/\\\\*.*?\\\\*/)\", \" \").trim();\nif (trimmed.isEmpty() || trimmed.equals(\";\")) throw new IllegalArgumentException(\"empty SQL\");","typeGuard":null,"tryCatchPattern":"catch (SQLNonTransientException e) { if (e.getMessage().startsWith(\"无效的SQL语句\")) { log.error(\"unparsable SQL sent to Mycat: {}\", sql, e); } throw e; }","preventionTips":["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"],"tags":["sql","parse-error","druid","routing","invalid-sql"],"backgroundTag":"sql-query-failed","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}