MyCATApache/Mycat-Server · error · SQLNonTransientException
joinKey not provided : + tc.getJoinKey() + , + insertStmt
Error message
joinKey not provided : + tc.getJoinKey() + , + insertStmt
What it means
Thrown during child-table (ER join) INSERT routing when the INSERT statement's column list does not include the parent joinKey declared on the child table (tc.getJoinKey()). MyCat needs the join key value to compute which shard the child row belongs to, so an insert without it cannot be routed and fails with SQLNonTransientException.
Solutions
- Add the joinKey column and its parent value to the INSERT column list.
- Verify the joinKey attribute in schema.xml childTable config exactly matches a real column name.
- If the column should be auto-derived, populate it in application code or via trigger before insert.
Example fix
// before INSERT INTO order_detail (id, amount) VALUES (1, 99); // after INSERT INTO order_detail (id, order_id, amount) VALUES (1, 500, 99); -- order_id is joinKey
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the joinKey column is present before inserting into a child table
Set<String> cols = insertColumns();
String joinKey = "order_id";
if (!cols.contains(joinKey)) {
throw new IllegalStateException("child-table insert must include joinKey column: " + joinKey);
} Try / catch
try {
stmt.executeUpdate(childInsertSql);
} catch (SQLNonTransientException | SQLException e) {
if (e.getMessage().startsWith("joinKey not provided")) {
// add joinKey column and retry
} else throw e;
} Prevention
- Include the parent join key in every child-table insert
- Verify joinKey attribute spelling in schema.xml matches column names
- Configure ORM entities to always persist the FK column
When it happens
Trigger: INSERT INTO childTable (...) VALUES (...) where the column list omits the joinKey column configured as <childTable joinKey=...>; getJoinKeyIndex returns -1.
Common situations: Inserting into an ER-linked child table without supplying the parent's id column; joinKey name in schema.xml doesn't match the actual column name casing used in the INSERT; ORM-generated inserts that skip 'redundant' foreign-key columns.
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
- invalid sql
- number of columns error
- number of values and columns have to match
- schema: ,table: ,sql: is not allowed,because table is…
- can't find hint datanode
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/92c1e98f9a8cd45a.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1930
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();
//判断条件完整性,取得解析后语句列中的joinkey列的index
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);
}
//取得joinkey的值
String joinKeyVal = insertStmt.getValues().getValues().get(joinKeyIndex).toString();
//解决bug #938,当关联字段的值为char类型时,去掉前后"'"
String realVal = joinKeyVal;
if (joinKeyVal.startsWith("'") && joinKeyVal.endsWith("'") && joinKeyVal.length() > 2) {
realVal = joinKeyVal.substring(1, joinKeyVal.length() - 1);
}
// try to route by ER parent partion key
//如果是二级子表(父表不再有父表),并且分片字段正好是joinkey字段,调用routeByERParentKey
View on GitHub (pinned to 65f8d8beb7)