{"record":{"id":"af25fa45c1851bad","repo":"MyCATApache/Mycat-Server","slug":"sharding-column-can-t-be-updated-af25fa","errorCode":null,"errorMessage":"Sharding column can't be updated ->","messagePattern":"Sharding column can't be updated ->","errorType":"exception","errorClass":"SQLNonTransientException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/parser/druid/impl/DruidUpdateParser.java","lineNumber":234,"sourceCode":"    private void confirmShardColumnNotUpdated(SQLUpdateStatement update,SchemaConfig schema,String tableName,String partitionColumn,String joinKey,RouteResultset rrs) throws SQLNonTransientException {\n        List<SQLUpdateSetItem> updateSetItem = update.getItems();\n        if (updateSetItem != null && updateSetItem.size() > 0) {\n            boolean hasParent = (schema.getTables().get(tableName).getParentTC() != null);\n            for (SQLUpdateSetItem item : updateSetItem) {\n                String column = StringUtil.removeBackquote(item.getColumn().toString().toUpperCase());\n                //考虑别名，前面已经限制了update分片表的个数只能有一个，所以这里别名只能是分片表的\n                if (column.contains(StringUtil.TABLE_COLUMN_SEPARATOR)) {\n                    column = column.substring(column.indexOf(\".\") + 1).trim().toUpperCase();\n                }\n                if (partitionColumn != null && partitionColumn.equals(column)) {\n                    boolean canUpdate;\n                    canUpdate = ((update.getWhere() != null) && shardColCanBeUpdated(update.getWhere(),\n                            partitionColumn, item.getValue(), false));\n\n                    if (!canUpdate) {\n                        String msg = \"Sharding column can't be updated \" + tableName + \"->\" + partitionColumn;\n                        LOGGER.warn(msg);\n                        throw new SQLNonTransientException(msg);\n                    }\n                }\n                if (hasParent) {\n                    if (column.equals(joinKey)) {\n                        String msg = \"Parent relevant column can't be updated \" + tableName + \"->\" + joinKey;\n                        LOGGER.warn(msg);\n                        throw new SQLNonTransientException(msg);\n                    }\n                    rrs.setCacheAble(true);\n                }\n            }\n        }\n    }\n}\n","sourceCodeStart":216,"sourceCodeEnd":249,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/parser/druid/impl/DruidUpdateParser.java#L216-L249","documentation":"Mycat forbids UPDATE statements that change a table's sharding (partition) column, since moving a row to another shard cannot be routed atomically. If confirmShardColumnNotUpdated detects the partition column in the SET clause and the new value does not provably equal the WHERE-filtered value in the same statement, it throws this error naming the table and column.","triggerScenarios":"UPDATE on a sharded table where a SET item targets the partitionColumn and the value is not confirmed identical to the value used in the WHERE condition (shardColCanBeUpdated returns false, including when the column appears in an OR/XOR clause).","commonSituations":"Changing a user_id/tenant_id/order date that happens to be the sharding key; migrating data by reassigning the shard key through UPDATE; ORMs that blindly include the key in SET.","solutions":["Remove the sharding column from the SET clause if its value is not actually changing","Migrate the row instead: DELETE from the old shard and INSERT into the new one (application-managed)","Reshard by changing the partition key data model or re-partitioning offline, not via UPDATE","If the value is identical, write the statement so WHERE value exactly matches the SET value with no OR clauses"],"exampleFix":"// before\nUPDATE orders SET user_id=42 WHERE order_id=100;\n// after (user_id is the sharding column)\nDELETE FROM orders WHERE order_id=100;\nINSERT INTO orders(order_id,user_id,...) VALUES(100,42,...);","handlingStrategy":"validation","validationCode":"Set<String> setCols = extractSetColumns(updateStmt);\nif (setCols.contains(partitionColumn)) {\n    throw new IllegalArgumentException(\"sharding column \" + partitionColumn + \" must not be updated\");\n}","typeGuard":null,"tryCatchPattern":"try { router.route(...) } catch (SQLNonTransientException e) { if (e.getMessage().startsWith(\"Sharding column can't be updated\")) { convertToUpdateDeleteInsert(); } }","preventionTips":["Treat the sharding key as immutable in the data model","Use delete+insert to change shard ownership","Exclude shard keys from ORM-generated SET lists"],"tags":["mysql","sharding","partition-key"],"backgroundTag":"unsupported-operation","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}