数据库字段差异
为什么VARCHAR(1000)没法存1000个汉字
字符与字节
在计算机中,字符和字节是两个不同的概念:
- 字节(Byte):计算机存储的基本单位,1字节 = 8位(bit)
- 字符(Character):人类可读的文本单位,如字母、数字、汉字等
关键点:一个字符可能占用多个字节,这取决于使用的字符编码方式。
常见字符的字节占用
- ASCII字符(英文字母、数字、标点):1字节/字符
- 汉字(中文字符):
- UTF-8编码:通常3字节/字符(部分4字节)
- GBK编码:2字节/字符
- UTF-16编码:2或4字节/字符
编码方式
UTF-8编码
UTF-8是一种变长编码方式,使用1-4个字节表示一个字符:
- ASCII字符(0x00-0x7F):1字节
- 拉丁字符(0x80-0x7FF):2字节
- 中文、日文、韩文等(0x800-0xFFFF):3字节
- 其他字符(0x10000-0x10FFFF):4字节
示例:
- 英文字母 “A”:1字节
- 汉字 “中”:3字节
- 表情符号 “😀”:4字节
GBK编码
GBK是中文编码标准,使用固定2字节表示一个汉字。
UTF-16编码
UTF-16使用2或4字节表示字符:
- 基本多文种平面(BMP)字符:2字节
- 辅助平面字符:4字节(代理对)
主流数据库VARCHAR存储
MySQL
存储机制
- VARCHAR(N) 中的 N 表示字符数,不是字节数
- 存储时根据表的字符集(charset)计算实际字节占用
- 需要额外的1-2字节存储长度信息
字符集影响
- utf8mb4(推荐):
- 英文字符:1字节
- 中文字符:3字节
- 表情符号:4字节
- utf8(已弃用,实际是utf8mb3):
- 英文字符:1字节
- 中文字符:3字节
- 不支持4字节字符(如表情符号)
示例
1 | |
行大小限制
- MySQL单行最大65535字节(不包括TEXT/BLOB)
- VARCHAR实际可用空间 = 65535 - 其他字段占用 - 长度信息
PostgreSQL
存储机制
- VARCHAR(N) 中的 N 表示字符数
- 使用UTF-8编码存储
- 没有行大小限制(与MySQL不同)
示例
1 | |
SQL Server
存储机制
- VARCHAR(N) 中的 N 表示字节数(不是字符数)
- 使用单字节编码(如Latin1)
- 对于Unicode字符,需要使用 NVARCHAR(N),其中N表示字符数
示例
1 | |
DM DataBase
存储机制
- VARCHAR(N) 中的 N 取决于初始化参数
LENGTH_IN_CHAR- 默认情况 0 : 表示字节,使用utf8mb3存储,每个汉字需要3个字节存储;
- 修改后 1 : 表示字符。
- 大多数达梦数据库都是安装时保持默认情况,按照字节来存,使用达梦数据库时需要额外注意。
Oracle
存储机制
- VARCHAR2(N) 中的 N 表示字节数或字符数(取决于定义)
- 使用
BYTE或CHAR语义:VARCHAR2(1000 BYTE):1000字节VARCHAR2(1000 CHAR):1000字符
示例
1 | |
总结对比
| 数据库 | VARCHAR(N)含义 | 字符集 | 行大小限制 |
|---|---|---|---|
| MySQL | N = 字符数 | utf8mb4(3字节/汉字) | 65535字节 |
| PostgreSQL | N = 字符数 | UTF-8(3字节/汉字) | 无限制 |
| SQL Server | N = 字节数 | 单字节 | 无限制(需用NVARCHAR存Unicode) |
| Oracle | N = 字节/字符(可选) | 根据字符集 | 4000字节(VARCHAR2) |
为什么VARCHAR(1000)没法存1000个汉字?
答案取决于数据库类型:
MySQL/PostgreSQL:
- VARCHAR(1000)理论上可以存1000个字符
- 但MySQL受行大小限制(65535字节),实际可能只能存约333个汉字
- PostgreSQL没有此限制,可以存1000个汉字
SQL Server:
- VARCHAR(1000)只能存1000字节
- 使用GBK编码约500个汉字,使用UTF-8约333个汉字
- 应使用NVARCHAR(1000)存储Unicode字符
Oracle:
- VARCHAR2(1000 BYTE)只能存1000字节
- VARCHAR2(1000 CHAR)可以存1000个字符
最佳实践:
- 明确字符集和编码方式
- 了解数据库的VARCHAR定义语义(字符数 vs 字节数)
- 考虑行大小限制
- 对于多语言支持,优先使用UTF-8编码和按字符数定义
数据库字段差异
https://yicizhang00.github.io/posts/存储系统/数据库基础/数据库字段差异/