问题来源
很多时候我们不确定某个字段的长度, 会使用 varchar 类型, 比如某个字段定义为 varchar(100), 那这 100 的长度能存多少个中文?
当时的想法就是: 这个 100 能存多少个中文和数据库的编码方式有关, 具体怎么个有关法还真是没有细细探究. 网上的答案千奇百怪, 很不给力, 只能自己摸索了.
首先需要明确的是: 在 utf8 编码方式下, 一个中文占 3 个字节; 而 gbk 编码下, 一个中文占 2 个字节.
这个我们可以使用 varchar 类型存储一个字段 vname, 然后分别向其中添加一个汉字和英文.
- select length(vname) from tablename;
- select char_length(vname) from tablename,
你会发现二者的关系就是上述内容.
探索过程
回到那个问题, 这 100 的长度到底能存多少个中文, 既然一个中文占 3 个字节, 是不是就只能存 100/3=33 个中文呢? 换句话说, 100 这个数字是字节数, 还是字符数? 为此我做了如下测试:
在 linux 上的 mysql 中定义了下表
- CREATE TABLE `test` (
- `v` varchar(4) default NULL,
- `c` char(4) default NULL
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
即如下图
然后
insert into test values ('围脖你好','围脖你好');
, 有 2 个 warning,select 之后才发现只存进去一个 "新" 字, 后面的全丢了. 这就说明, varchar(4)和 char(4)中的 4 是字节数, 即 100 是字节数, 只能存 33 个中文字符.(备注: 如果我们存储的字符串长度超过预定义的长度, mysql 仍然可以存储成功, 只是会提示 warning, 会将超出的部分自动截断.)
答案貌似明确了, 但紧接着问题又来了!
因为以前听说, 这个 varchar(n)和 char(n)中的 n 指的是存储的字符数, 这不和我刚才做的测试完全不符吗? 所以我又在本地 windows 下的 mysql 中做了同样的操作, 建相同的表, 插入相同的数据, 看到结果, 我傻眼了!!
insert into test values (
'围脖你好','围脖你好');, 并未 warning, 而是 query OK!select 之后发现, 这四个中文竟然都存进去了, 这也就说明我们刚才定义的那个 char(4)和 varchar(4)中的 4 是字符数, 而非字节数, 这么说来, 那 100 就是可以存 100 个中文字符了, 这不完全将刚才的那个结论颠覆了?? 可是这两个结果都是对的啊, 只是环境不同而已.
这样的话, 那我们以后定义 char 和 varchar 字段还要先判断一下该环境下这个 (n) 到底代表的啥? 是字节还是字符?
不甘心, 想搞清楚原因, 为何会出现这样的差别?
show variable like '%char%';
这下清晰了, linux 下的和 windows 下的 mysql 相关变量编码定义完美呈现
实际上,
character_set_client,character_set_connection,character_set_results
是可以改变的, 这个可以使用 set names gbk/utf8, 只是为了和客户端编码页保持一致, 不会乱码, 如果客户端编辑页设定的文档是 utf8, 那么我们自然要 set names utf8 了, gbk 同理. 这个命令只会改变显示问题, 底部的 database 的编码还是不会因为这个命令而受到影响的. 包括 server,system 也不会随之改变, 这时我们对比上下两张表, 他们的 server 和 system 以及 database 的编码发现 Linux 下的都是 Latin1, 而 windows 下的这个都是 utf8,
总结
我们知道 Latin1 都是存储字节为单位的字符比如数字, 字母, 一个 Latin 字符只占一个字节, 而 utf8 存储的种类繁多, 字符所占的字节数也就不确定了, utf8 具有统一功能, 其实网上大多是说 char(n)存的是 n 个字符, 就是因为此处的编码都是 utf8 的, utf8 屏蔽了中文和英文和数字的显示区别, 他们都是一个字符, 所以定义的时候那个 n 就代表了字符的个数, 具体占多少个字节是根据他们自身字符串的长度定的, 比如 char(100)存储 100 个中文, 那么占 300 个字节, 存 100 个字母, 就占 100 个字节.
来源: https://www.qcloud.com/developer/article/1159062