关于char/varchar(n)中n的探究:字符数or字节数
【问题来源】将设计的数据库表展示的时候,yu哥问我,你的那个top_info字段定义的类型是varchar(100),为什么是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)到底代表的啥?是字节还是字符?
不甘心,想搞清楚原因,为何会出现这样的差别?于是yu哥给我说了这样一个命令
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个字节。
但是这好像并不能说明这n代表的是字符而不是字节!
什么情况下它代表字节,什么情况下代表字符?这和我们刚才列出的那些变量的编码有什么关系?。。。。。。继续探索中,求指点!
注:部分描述可能存在问题,望提出宝贵的意见和指导。
附:char与varchar的部分总结比较(与此文无关)

关于char/varchar(n)中n的探究:字符数or字节数的更多相关文章
- Java中的字节流,字符流,字节缓冲区,字符缓冲区复制文件
一:创建方式 1.建立输入(读)对象,并绑定数据源 2.建立输出(写)对象,并绑定目的地 3.将读到的内容遍历出来,然后在通过字符或者字节写入 4.资源访问过后关闭,先创建的后关闭,后创建的先关闭 ...
- 用PHP,怎么获取PHP.ini中的文件上传最大的字节数。也就是默认的2M
PHP中用ini_get函数来获取服务器允许的文件上传最大字节数,如:
- ORACLE中一个字符占多少字节?
问题描述 或许你会说一个中文字符占2个字节,这是一定的?如何计算一个字符串的字节数? 解决方案 在oracle中一个字符特别是中文占几个字节是不同的. 比如我创立一个表create table tes ...
- Java中字符编码和字符串所占字节数 .
首 先,java中的一个char是2个字节.java采用unicode,2个字节来表示一个字符,这点与C语言中不同,C语言中采用ASCII,在大多数 系统中,一个char通常占1个字节,但是在0~12 ...
- Python中的字符串与字符编码
本节内容: 前言 相关概念 Python中的默认编码 Python2与Python3中对字符串的支持 字符编码转换 一.前言 Python中的字符编码是个老生常谈的话题,同行们都写过很多这方面的文章. ...
- 【转】Python中的字符串与字符编码
[转]Python中的字符串与字符编码 本节内容: 前言 相关概念 Python中的默认编码 Python2与Python3中对字符串的支持 字符编码转换 一.前言 Python中的字符编码是个老生常 ...
- 数据库中char, varchar, nvarchar的差异
char char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符. nvarc ...
- MySQL中varchar与char的区别以及varchar(50)中的50代表的涵义
varchar与char的区别: 1).varchar与char的区别char是一种固定长度的类型,varchar则是一种可变长度的类型 尽可能的使用 varchar 代替 char ,因为首先变长 ...
- mysql中char,varchar,text
1.char char最大长度是255字符,注意是字符数和字符集没关系. 1)可以有默认值, 2)尾部有空格会被截断 3)不管汉字.英文,还是其他编码,都可以存255字符 2.varchar 1)va ...
随机推荐
- 畅通工程再续--hdu1875
畅通工程再续 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- 新浪研发中心: Berkeley DB 使用经验总结
http://blog.sina.com.cn/s/blog_502c8cc40100yqkj.html NoSQL是现在互联网Web2.0时代备受关注的技术之一,被用来存储大量的非关系型的数据.Be ...
- Android中图片的目录
图片放在hdpi及在mdpi中的效果是不一样的 http://blog.csdn.net/loongggdroid/article/details/9469935
- document.body.scrollTop vs document.documentElement.scrollTop && document.body.scrollHeight vs document.documentElement.scrollHeight
FireFox下 document.body.scrollHeight || document.documentElement.scrollHeight;//等价 document.body.scro ...
- PowerShell3.0中,所有的命令
Get-Command * >> cmd.txt CommandType Name ModuleName ----------- ---- ---------- Alias % -> ...
- Eclipse标准版安装J2EE
虽然有Eclipse IDE for Java EE Developers,已经包含了j2ee的插件,但有时我们需要在标准版上安装插件来达到开发j2ee的功能. 安装 Java EE 插件: * 依 ...
- Dynamics CRM 2013 初体验(2):UI
Dynamics CRM 2013 系统的UI与2011相比改动是巨大的:传统的导航栏被去掉了,取代它的是win8风格的小磁铁:Ribbon风格的工具栏也被去掉啦,它的风格将回滚至4.0时代:新系统添 ...
- 【LeetCode练习题】Valid Palindrome
Valid Palindrome Given a string, determine if it is a palindrome, considering only alphanumeric char ...
- OpensStack instance debug
错误: 创建实例 "RuiyTest23" 失败: 请稍后再试 [错误: Virtual Interface creation failed].
- pyqt listwidget下面创建多张图片
def Photosvisi(self): i=0 self.lists.setIconSize(QtCore.QSize(70,70))#设置显示图片大小 self.lists.setResizeM ...