MyCATApache/Mycat-Server · error · SQLNonTransientException
"joinKey not provided :" + tc.getJoinKey()+ "," + insertStmt
Error message
"joinKey not provided :" + tc.getJoinKey()+ "," + insertStmt
What it means
When inserting into a child (ER-join) table, Mycat requires the parent's join key column to be present in the INSERT column list so it can derive the child row's datanode from the parent row. If the column list lacks joinKey, parserChildTable cannot compute the route and throws.
Solutions
- Include the join key column (parent's key, e.g. order_id) explicitly in the INSERT column list and provide a value
- Verify the joinKey attribute on the child <table> in schema.xml matches a real column name
- If the join key should default (e.g. via trigger/auto-fill), instead insert with the column provided explicitly — Mycat cannot infer it
Example fix
// before INSERT INTO order_detail (id, item, price) VALUES (1, 'x', 9.9); // after INSERT INTO order_detail (id, order_id, item, price) VALUES (1, 100, 'x', 9.9);
Defensive patterns
Strategy: validation
Validate before calling
// ensure join key is present before insert into child table
List<String> declaredColumns = extractInsertColumns(sql);
String joinKey = childTableConfig.getJoinKey();
if (!declaredColumns.contains(joinKey.toUpperCase())) {
throw new IllegalArgumentException("Insert must include joinKey column: " + joinKey);
} Type guard
static boolean hasJoinKey(InsertStatement ins, TableConfig tc) {
return tc.getJoinKey() != null && ins.getColumns().stream()
.map(c -> c.toString().toUpperCase())
.anyMatch(c -> c.equals(tc.getJoinKey().toUpperCase()));
} Try / catch
try {
insert(childRows);
} catch (SQLNonTransientException e) {
if (e.getMessage().startsWith("joinKey not provided")) {
throw new IllegalArgumentException("Child-table insert must include join key column " + joinKey, e);
}
throw e;
} Prevention
- Always list columns explicitly in INSERTs into child tables, including the join key
- Review schema.xml joinKey attributes against actual column names
- Warn in code review when child-table inserts omit any columns
When it happens
Trigger: `INSERT INTO child (...) VALUES (...)` where tc.isChildTable() is true and getJoinKeyIndex(insertStmt.getColumns(), joinKey) returns -1 — i.e. the join key column declared in schema.xml (joinKey attr) is not among the explicitly listed insert columns.
Common situations: Inserting into an ER-partitioned order-detail table without supplying parent_id column; omitting columns from the INSERT column list (not using column-list-less VALUES matching full table); joinKey misconfigured in schema.xml pointing at a column never inserted.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- bad insert sql columnSize != valueSize:values:
- TODO:insert into .... select .... not supported!
- "ChildTable multi insert not provided"
- "bad insert sql (sharding column:"+ partitionColumn + " not…
- number of columns error
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/38d8336f16234fa1.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/parser/druid/impl/DruidInsertParser.java:128
/**
* 是否为批量插入:insert into ...values (),()...或 insert into ...select.....
* @param insertStmt
* @return
*/
private boolean isMultiInsert(MySqlInsertStatement insertStmt) {
return (insertStmt.getValuesList() != null && insertStmt.getValuesList().size() > 1) || insertStmt.getQuery() != null;
}
private RouteResultset parserChildTable(SchemaConfig schema, RouteResultset rrs,
String tableName, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
TableConfig tc = schema.getTables().get(tableName);
String joinKey = tc.getJoinKey();
int joinKeyIndex = getJoinKeyIndex(insertStmt.getColumns(), joinKey);
if(joinKeyIndex == -1) {
String inf = "joinKey not provided :" + tc.getJoinKey()+ "," + insertStmt;
LOGGER.warn(inf);
throw new SQLNonTransientException(inf);
}
if(isMultiInsert(insertStmt)) {
String msg = "ChildTable multi insert not provided" ;
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
String joinKeyVal = insertStmt.getValues().getValues().get(joinKeyIndex).toString();
String sql = insertStmt.toString();
// try to route by ER parent partion key
RouteResultset theRrs = RouterUtil.routeByERParentKey(null,schema, ServerParse.INSERT,sql, rrs, tc,joinKeyVal);
if (theRrs != null) {
rrs.setFinishedRoute(true);
return theRrs;
}View on GitHub (pinned to 65f8d8beb7)