背景:在大佬强烈要求下,整理了一下商品总表goods
,发现有个简介description
的字段使用text类型,大佬强烈要求想改成varchar类型,但由于历史原因,有些类型的商品简介这个字段存的是后台的富文本编辑框内容,查了一下最大长度,有6万多一点(字符数/字数,不是字节数)。
后来网上查了一下,varchar类型可以存储的字节和TEXT都是65535个字节。
问题:是不是就是说只要设置varchar(65535)就相当于设置了text类型呢?
答案:??
接下来就自己测试了一番。
测试版本:5.6
首先,我创建了一个表,==编码为UTF8==。新增text字段,往字段内填充内容,中英文乱七八糟的,结果发现,text确实可以最大字节数为65535(将使用PHP的函数strlen()计算得到长度为65535的数据填充进去刚刚好)。
然后,删除text字段,新增varchar字段,发现根本不能设置长度为65535,==最大只能设置为21844,即可以存储包括中英文符号等在内的所有字符数量之和为21844==(将使用PHP的函数mb_strlen()计算得到长度为21844的数据填充进去刚刚好)。
原因:因为UTF8编码按每个字符最多要占用三个字节数计算,65535/3=21845,又因为varchar本身要占用一个字节(这里我不确定utf8编码是否要占用三个字节,还是占用了一个字节剩下两个字节凑不够一个字符),所以少了一个字符数量。
其实,所谓的varchar类型可以存储65535个字节,是对于MySQL表的行大小的限制为65535个字节。==即每张表所有字段长度加起来的总字节数不能大于65535个字节。==
现在,我再去新增一个字段,int类型,发现创建失败!!
提示如下错误:
原因:int类型要占用表的一个字符数,但是varchar字段已经使用了MySQL行最大限制上限,所以导致新增字段失败。
接着,我随意新增字段,并有意减少varchar字段长度,做最大上限测试。
得出以下结论:
==根据创建表的编码类型,不同的类型需要占用的字符数不同==,UTF8编码下:
- tinyint类型占本身一个字符。
- int类型占本身一个字符+1(存储length长度)。
- char类型占length长度
- varchar类型占本身一个字符+length长度
- text类型占本身四个字符
最后回顾一下问题:
是不是就是说只要设置varchar(65535)就相当于设置了text类型呢?
答案:错误的!!
varchar类型存储长度与表的编码有关系。
当我尝试新建一个表,编码为单字节字符集latin1类型,最终可以设置的最大长度如下(也达不到65535):
所以,得出结论:当下我这个goods
表中的description
字段无法修改类型为varchar。
原因:①utf8编码下,长度不够;②这个字段长度设置过大,会导致容易达到表的行最大限制长度,这个问题会导致新增字段都新增不了!!!