数据库字段差异

为什么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
2
3
4
5
6
7
-- 创建表,使用utf8mb4字符集
CREATE TABLE test (
name VARCHAR(1000) CHARACTER SET utf8mb4
);

-- 可以存储约333个汉字(1000字符 ÷ 3字节/字符 ≈ 333)
-- 但实际还要考虑行大小限制(65535字节)

行大小限制

  • MySQL单行最大65535字节(不包括TEXT/BLOB)
  • VARCHAR实际可用空间 = 65535 - 其他字段占用 - 长度信息

PostgreSQL

存储机制

  • VARCHAR(N) 中的 N 表示字符数
  • 使用UTF-8编码存储
  • 没有行大小限制(与MySQL不同)

示例

1
2
3
4
5
6
-- 可以存储1000个字符,无论是什么字符
CREATE TABLE test (
name VARCHAR(1000)
);

-- 可以存储1000个汉字(每个汉字3字节,共3000字节)

SQL Server

存储机制

  • VARCHAR(N) 中的 N 表示字节数(不是字符数)
  • 使用单字节编码(如Latin1)
  • 对于Unicode字符,需要使用 NVARCHAR(N),其中N表示字符数

示例

1
2
3
4
5
6
7
8
9
10
-- VARCHAR(1000) 只能存储1000字节
-- 如果使用GBK编码,可以存储约500个汉字
CREATE TABLE test (
name VARCHAR(1000) -- 1000字节
);

-- NVARCHAR(1000) 可以存储1000个字符(Unicode)
CREATE TABLE test2 (
name NVARCHAR(1000) -- 1000个字符,每个字符2字节(UTF-16)
);

DM DataBase

存储机制

  • VARCHAR(N) 中的 N 取决于初始化参数 LENGTH_IN_CHAR
    • 默认情况 0 : 表示字节,使用utf8mb3存储,每个汉字需要3个字节存储;
    • 修改后 1 : 表示字符。
  • 大多数达梦数据库都是安装时保持默认情况,按照字节来存,使用达梦数据库时需要额外注意。

Oracle

存储机制

  • VARCHAR2(N) 中的 N 表示字节数字符数(取决于定义)
  • 使用 BYTECHAR 语义:
    • VARCHAR2(1000 BYTE):1000字节
    • VARCHAR2(1000 CHAR):1000字符

示例

1
2
3
4
5
6
7
8
9
-- 按字节定义
CREATE TABLE test1 (
name VARCHAR2(1000 BYTE) -- 1000字节
);

-- 按字符定义(推荐)
CREATE TABLE test2 (
name VARCHAR2(1000 CHAR) -- 1000个字符
);

总结对比

数据库 VARCHAR(N)含义 字符集 行大小限制
MySQL N = 字符数 utf8mb4(3字节/汉字) 65535字节
PostgreSQL N = 字符数 UTF-8(3字节/汉字) 无限制
SQL Server N = 字节数 单字节 无限制(需用NVARCHAR存Unicode)
Oracle N = 字节/字符(可选) 根据字符集 4000字节(VARCHAR2)

为什么VARCHAR(1000)没法存1000个汉字?

答案取决于数据库类型

  1. MySQL/PostgreSQL

    • VARCHAR(1000)理论上可以存1000个字符
    • 但MySQL受行大小限制(65535字节),实际可能只能存约333个汉字
    • PostgreSQL没有此限制,可以存1000个汉字
  2. SQL Server

    • VARCHAR(1000)只能存1000字节
    • 使用GBK编码约500个汉字,使用UTF-8约333个汉字
    • 应使用NVARCHAR(1000)存储Unicode字符
  3. Oracle

    • VARCHAR2(1000 BYTE)只能存1000字节
    • VARCHAR2(1000 CHAR)可以存1000个字符

最佳实践

  • 明确字符集和编码方式
  • 了解数据库的VARCHAR定义语义(字符数 vs 字节数)
  • 考虑行大小限制
  • 对于多语言支持,优先使用UTF-8编码和按字符数定义

数据库字段差异
https://yicizhang00.github.io/posts/存储系统/数据库基础/数据库字段差异/
作者
Yici Zhang
发布于
2025年8月12日
许可协议