MyCATApache/Mycat-Server · error · SQLNonTransientException

can't find table define in schema + tableName + schema: +…

Error message

can't find table define in schema  + tableName +  schema: + schema.getName()

What it means

RouterUtil iterates over tablesAndConditions (table -> column conditions) during multi-table route calculation and looks up each table's TableConfig in the schema. Any table not declared in schema.xml (lookup is done on the uppercased name) causes a SQLNonTransientException, since MyCat cannot route tables it has no definition for.

Solutions

  1. Declare every table referenced in the query in schema.xml and reload MyCat
  2. Match table-name case with the schema.xml declaration (MyCat uppercases for lookup)
  3. Add a schema-level default dataNode as fallback for undeclared tables
  4. Verify the connection's logical schema contains all tables your SQL references

Example fix

// before
SELECT * FROM orders o JOIN items i ON ...; // 'items' undeclared
// after (schema.xml)
<table name="items" dataNode="dn1"/>
Defensive patterns

Strategy: validation

Validate before calling

// verify all tables referenced by a join are declared in MyCat
for (String t : List.of("ORDERS","ITEMS")) {
    ResultSet rs = stmt.executeQuery("SHOW TABLES LIKE '" + t + "'");
    if (!rs.next()) throw new IllegalStateException("Table not in MyCat schema: " + t);
}

Try / catch

try {
    execute(joinSql);
} catch (SQLNonTransientException e) {
    if (e.getMessage().startsWith("can't find table define in schema"))
        throw new IllegalStateException("Declare all joined tables in schema.xml", e);
    throw e;
}

Prevention

When it happens

Trigger: Executing a JOIN/multi-table query where at least one referenced table has no <table> entry in the current MyCat schema; lookup key is the uppercased table name from the parsed SQL.

Common situations: Joining against a table present only in backend MySQL; case mismatch between SQL table name and schema.xml declaration; wrong schema selected; table added to DB but config never reloaded.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/cc3416c528187975. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1611

		return nodes;
	}

	/**
	 * 处理分库表路由
	 */
	public static void findRouteWithcConditionsForTables(SchemaConfig schema, RouteResultset rrs,
			Map<String, Map<String, Set<ColumnRoutePair>>> tablesAndConditions,
			Map<String, Set<String>> tablesRouteMap, String sql, LayerCachePool cachePool, boolean isSelect)
			throws SQLNonTransientException {

		//为分库表找路由
		for(Map.Entry<String, Map<String, Set<ColumnRoutePair>>> entry : tablesAndConditions.entrySet()) {
			String tableName = entry.getKey().toUpperCase();
			TableConfig tableConfig = schema.getTables().get(tableName);
			if(tableConfig == null) {
				String msg = "can't find table define in schema "
						+ tableName + " schema:" + schema.getName();
				LOGGER.warn(msg);
				throw new SQLNonTransientException(msg);
			}
			if(tableConfig.getDistTables()!=null && tableConfig.getDistTables().size()>0){
			    routeToDistTableNode(schema,rrs,sql, tablesAndConditions, cachePool,isSelect, entry);
			}
			//全局表或者不分库的表略过(全局表后面再计算)
			if(tableConfig.isGlobalTable() || schema.getTables().get(tableName).getDataNodes().size() == 1) {
				continue;
			} else {//非全局表:分库表、childTable、其他
				Map<String, Set<ColumnRoutePair>> columnsMap = entry.getValue();
				String joinKey = tableConfig.getJoinKey();
				String partionCol = tableConfig.getPartitionColumn();
				String primaryKey = tableConfig.getPrimaryKey();
				boolean isFoundPartitionValue = partionCol != null && entry.getValue().get(partionCol) != null;
				boolean isLoadData=false;
				if (LOGGER.isDebugEnabled()
						&& sql.startsWith(LoadData.loadDataHint)||rrs.isLoadData()) {
					//由于load data一次会计算很多路由数据,如果输出此日志会极大降低load data的性能

View on GitHub (pinned to 65f8d8beb7)