MyCATApache/Mycat-Server · error · SQLNonTransientException

joinKey not provided :

Error message

joinKey not provided :

What it means

When inserting into an ER (child) table, Mycat locates the parent row's storage node via the joinKey. getJoinKeyIndex scans the INSERT's column list for the joinKey; if the join key column is absent (index -1), routing is impossible and a SQLNonTransientException is thrown naming the joinKey and the statement.

Solutions

  1. Include the joinKey column in the INSERT column list with the parent's key value.
  2. Verify the joinKey attribute in schema.xml exactly matches (uppercased) the column name used in the SQL.
  3. If the row genuinely has no parent link, define the table as a normal sharded table instead of a childTable.

Example fix

// before
INSERT INTO order_items (item_id, qty) VALUES (9, 2);
// after (joinKey = order_id)
INSERT INTO order_items (item_id, order_id, qty) VALUES (9, 1001, 2);
Defensive patterns

Strategy: validation

Validate before calling

// Check the joinKey column is present before child-table insert
function validateChildInsert(columns, joinKey) {
  if (!columns.map(c => c.toUpperCase()).includes(joinKey.toUpperCase())) {
    throw new Error("child-table insert must include joinKey column: " + joinKey);
  }
}

Prevention

When it happens

Trigger: INSERT into a childTable (childTable="..." joinKey="...") whose column list does not include the configured joinKey column, e.g. INSERT INTO order_items (item_id, qty) VALUES (...) where joinKey is order_id.

Common situations: Child-table inserts that omit the foreign-key column; joinKey in schema.xml misspelled or different case than the SQL column; ORMs doing partial-column inserts.

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


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/1635bd81fe288f60. 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)