`MySql` 更新列时字符集/排序规则处理有误,导致 `utf8mb4` 列无法正确改列或显式修改字符集失败 返回

SqlSugar
1 143

## 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

  • 如果确认是BUG,我就提交修复后的代码

    如果是使用问题,期望给一个正确的使用方式

    0 回复