在数据库运维和开发过程中。特别是在达梦数据库中,VARCHAR(10)究竟能存储多少个字符,答案并不唯一——它取决于两个关键初始化参数:LENGTH_IN_CHAR和CHARSET。
如果从MySQL迁移到达梦,可能会遇到这样的场景:原有业务中VARCHAR(10)明明可以存储10个汉字,到达梦后却只能存3个,导致应用报错、数据截断。
2.1 LENGTH_IN_CHAR
这个参数的是想让开发人员能够更直观地定义字符串长度,特别是在处理多字节字符集时。但历史版本中,它的实际行为存在一些容易混淆的细节——当LENGTH_IN_CHAR=1时,VARCHAR的实际容量并非简单地变成"以字符计数",而是在定义长度基础上进行倍数放大。
2.2 CHARSET:字符集的选择
参数说明:指定数据库使用的字符集。
字符集决定了每个字符占用多少字节,这是理解字符串存储容量的基础。
3.1 场景一:GB18030字符集 + 字节模式(LENGTH_IN_CHAR=0)
这是默认配置。
| 字符类型 | 单字符字节数 | VARCHAR(10)实际可存数量 |
|---|---|---|
| 英文字母 | 1字节 | 10个 |
| 中文字符 | 2字节 | 5个 |
3.2 场景二:UTF-8字符集 + 字节模式(LENGTH_IN_CHAR=0)
| 字符类型 | 单字符字节数 | VARCHAR(10)实际可存数量 |
|---|---|---|
| 英文字母 | 1字节 | 10个 |
| 中文字符 | 3字节 | 3个 |
3.3 场景三:UTF-8字符集 + 字符模式(LENGTH_IN_CHAR=1)——旧版本行为
这里的"字符模式"与直觉不同,它并非严格按字符数限制,而是进行了精度放大。
在UTF-8字符集下,VARCHAR(10)实际可用容量被放大为10×4=40字节。这意味着:
可存储约40个英文字母
可存储约13个中文字符(40÷3≈13)
早期版本测试数据佐证:在LENGTH_IN_CHAR=1且UTF-8配置下,部分用户发现VARCHAR(32)能存储超过32个字符的字符串,原因正是实际精度被放大了4倍。
3.4 结论:不同参数下的存储能力对比
| 字符集 | LENGTH_IN_CHAR | 英文存储能力 | 中文存储能力(VARCHAR(10)) |
|---|---|---|---|
| GB18030 | 0(字节) | 10个 | 5个 |
| GB18030 | 1(字符) | 约20个 | 约10个 |
| UTF-8 | 0(字节) | 10个 | 3个 |
| UTF-8 | 1(字符) | 约40个 | 约13个 |
注:GB18030中每个中文字符占2字节,UTF-8中每个中文字符占3字节。
4.1 变化说明
自2024年第二季度(Q2)版本起,LENGTH_IN_CHAR参数已被正式废弃。默认值固定为0,所有数据库均按字节为单位初始化。
这意味着:
4.2 版本确认方法
如果你不确定当前使用的达梦版本是否支持该参数,可以通过以下方式确认:
既然参数已废弃,如何在新版本中满足"按字符存储"的业务需求?以下是三种实用方案:
5.1 方案一:使用VARCHAR(n CHAR)语法
达梦支持在字段定义时直接指定"按字符计数":
CREATE TABLE test (
name VARCHAR(10 CHAR) -- 明确表示可存储10个字符(无论中英文)
);
这种方式不依赖全局参数,表级字段定义即可生效。
5.2 方案二:修改表结构,手动扩充精度
如果已有表结构需要适配,可以通过ALTER TABLE修改字段定义,根据字符集特点合理放大精度:
-- 原定义:VARCHAR(10)
-- GB18030建议改为:VARCHAR(20 CHAR)
-- UTF-8建议改为:VARCHAR(30 CHAR)
ALTER TABLE your_table MODIFY your_column VARCHAR(30 CHAR);
在迁移场景中,可通过查询系统表批量生成修改语句:
5.3 方案三:数据迁移工具(DTS)映射转换
在数据迁移场景下,达梦数据迁移工具(DTS)支持设置字符长度放大倍数,可在迁移过程中自动将源端的字符长度转换为达梦的字节长度(建议UTF-8设置3倍,GB18030设置2倍)。
5.4 方案四:开启超长记录
对于个别需要超长存储的特殊字段,可考虑开启表的超长记录功能,但这属于特殊情况下的兜底方案,建议谨慎评估。
文章
阅读量
获赞
