`MySql` 更新列时字符集/排序规则处理有误,导致 `utf8mb4` 列无法正确改列或显式修改字符集失败 返回
## Issue 标题
`MySql` 更新列时字符集/排序规则处理有误,导致 `utf8mb4` 列无法正确改列或显式修改字符集失败
## 问题描述
在 `SqlSugar` 的 `MySqlDbMaintenance.GetUpdateColumnSql` / `GetUpdateColumnCharacterSetSql` 逻辑中,更新列时对字符集与排序规则的处理存在边界问题。
### 现象 1
当目标字段存储 `utf8mb4` 内容,而更新列 SQL 未显式携带字符集/排序规则时,MySQL 会报错。
例如,直接生成的 SQL 可能类似:
```sql
alter table `user_aichat_records` change column `Text` `Text` VARCHAR(250) DEFAULT NULL
```
在表中已有 `utf8mb4` 数据时,这类 SQL 可能失败。
### 现象 2
即使业务侧希望显式把字段改成新的字符集,当前实现也会优先读取**数据库里已有列**的 `CharacterSetName` / `CollationName`,然后直接复用,导致:
- 无法通过 CodeFirst 显式修改字段字符集
- 新配置会被旧值覆盖
---
## 复现步骤
1. MySQL 表中已有 `utf8mb4` 字段或数据
2. 通过 `CodeFirst` / `DbMaintenance.UpdateColumn` 更新该列
3. 观察生成的 `ALTER TABLE ... CHANGE COLUMN ...` SQL
4. 发现字符集/排序规则没有正确处理,或无法按配置更新
---
## 期望行为
- 更新列时,如果业务显式指定了 `CharacterSetName` / `CollationName`,应优先使用业务配置
- 如果没有显式指定,则回退到数据库当前列的字符集/排序规则,避免 `utf8mb4` 数据更新失败
- 最终生成 SQL 应支持类似:
```sql
alter table `user_aichat_records`
change column `Text` `Text` VARCHAR(250)
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci
DEFAULT NULL
```
---
## 实际行为
- `GetUpdateColumnCharacterSetSql` 先取数据库已有列的字符集
- 导致更新逻辑只能“保留旧值”,不能“显式修改新值”
- 在 `utf8mb4` 场景下可能出现更新失败
---
## 根因分析
当前逻辑优先级不合理:
1. 先读取旧列信息
2. 若旧列存在字符集,则直接使用旧值
3. 业务侧传入的新字符集无法生效
这会让“更新列”退化成“保留原列字符集”,与修改列的语义不符。
---
## 建议修复方案
### 方案一:优先使用显式传入值,回退旧值
更新列时应按以下优先级处理:
1. `DbColumnInfo.CharacterSetName` / `CollationName`
2. 当前数据库中已有列的 `CharacterSetName` / `CollationName`
3. 都没有则不输出字符集 SQL
### 方案二:补充字段链路
如果要支持业务显式配置字符集,建议同时补齐以下链路:
- `EntityColumnInfo`
- `CodeFirstProvider.EntityColumnToDbColumn`
- `DbColumnInfo`
- MySQL `Create/Add/Update` 列 SQL 生成逻辑
这样可以在实体配置层直接写:
```csharp
c.CharacterSetName = "utf8mb4";
c.CollationName = "utf8mb4_unicode_ci";
```
---
## 推荐的修复结果
`MySqlDbMaintenance.GetUpdateColumnCharacterSetSql` 应改为:
- 优先使用 `columnInfo` 传入值
- 仅在未显式指定时,才回退到数据库当前列的 charset/collation
这样可以同时满足:
- 防止 `utf8mb4` 更新失败
- 支持显式修改字段字符集
热忱回答(1)
-
梦里—情丝乱 VIP0
2周前如果确认是BUG,我就提交修复后的代码
如果是使用问题,期望给一个正确的使用方式
0 回复