{"record":{"id":"ba3ec834f9ab0521","repo":"apache/seatunnel","slug":"insert-sql-must-have-select-statement","errorCode":null,"errorMessage":"Insert sql must have select statement","messagePattern":"Insert sql must have select statement","errorType":"exception","errorClass":"ParserException","httpStatus":null,"severity":"error","filePath":"seatunnel-config/seatunnel-config-sql/src/main/java/org/apache/seatunnel/config/sql/SqlConfigBuilder.java","lineNumber":371,"sourceCode":"        } else {\n            throw new ParserException(String.format(\"Unsupported syntax: %s\", createTable));\n        }\n    }\n\n    private static void parseInsertSql(\n            Insert insertSql,\n            Map<String, BaseConfig> sqlTables,\n            SeaTunnelConfig seaTunnelConfig,\n            AtomicInteger tempTableIndex) {\n        if (insertSql.getColumns() != null && !insertSql.getColumns().isEmpty()) {\n            throw new ParserException(\"Insert sql must not have columns\");\n        }\n        TransformConfig transformConfig = new TransformConfig();\n        Select select = insertSql.getSelect();\n        if (select == null\n                || select.getSelectBody() == null\n                || !(select.getSelectBody() instanceof PlainSelect)) {\n            throw new ParserException(\"Insert sql must have select statement\");\n        }\n        String targetTableName = insertSql.getTable().getName();\n        if (select.getSelectBody() instanceof PlainSelect) {\n            PlainSelect plainSelect = (PlainSelect) select.getSelectBody();\n\n            String pluginInputIdentifier;\n            String pluginOutputIdentifier;\n            if (plainSelect.getFromItem() == null) {\n                List<SelectItem<?>> selectItems = plainSelect.getSelectItems();\n                if (selectItems.size() != 1) {\n                    throw new ParserException(\n                            \"Source table must be specified in SQL: \" + insertSql);\n                }\n                SelectItem<?> selectItem = selectItems.get(0);\n                Column column = (Column) selectItem.getExpression();\n                pluginInputIdentifier = column.getColumnName();\n                pluginOutputIdentifier = pluginInputIdentifier;\n            } else {","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-config/seatunnel-config-sql/src/main/java/org/apache/seatunnel/config/sql/SqlConfigBuilder.java#L353-L389","documentation":"Validation in SqlConfigBuilder.parseInsertSql: an INSERT statement in the SQL config must be INSERT INTO ... SELECT; an insert whose body does not contain a Select (e.g. INSERT ... VALUES) cannot be translated into a SeaTunnel pipeline and is rejected with ParserException.","triggerScenarios":"INSERT INTO sink_t VALUES (...); INSERT ... with a UNION/CTE select body; truncated SQL missing the SELECT entirely.","commonSituations":"Porting row-value INSERT syntax from standard SQL; using multi-table or compound select statements the simple parser rejects.","solutions":["Replace VALUES (...) with an equivalent 'SELECT ... ' from a source table or a fake/dataset source","Rewrite UNION/CTE bodies into a single plain SELECT","Ensure the INSERT statement is complete and ends with a SELECT clause"],"exampleFix":"// before\nINSERT INTO sink_t VALUES (1, 'a')\n// after\nINSERT INTO sink_t SELECT 1, 'a' FROM src","handlingStrategy":"validation","validationCode":"// ensure each INSERT has a plain SELECT body\nfor (String stmt : insertStatements(sql)) {\n    if (!stmt.matches(\"(?si)INSERT\\\\s+INTO\\\\s+\\\\w+\\\\s+SELECT\\\\s+.*\")) {\n        throw new IllegalArgumentException(\"INSERT must be followed by a plain SELECT: \" + stmt);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    SeaTunnelConfig c = SqlConfigBuilder.of(sql);\n} catch (ParserException e) {\n    if (e.getMessage().equals(\"Insert sql must have select statement\")) {\n        // replace VALUES/compound select with plain SELECT\n    }\n}","preventionTips":["Do not use INSERT ... VALUES in this dialect; generate rows via a source table","Keep INSERT queries as single plain SELECTs (no UNION/CTE)","Validate SQL with JSqlParser before submission"],"tags":["sql","parser","insert","unsupported-syntax"],"backgroundTag":"unsupported-operation","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}