MySQL 建表字段长度的限制

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

脑补,varchar(N),N指的是最大字符数,不是字节数。

先上测试说明:

 

在MySQL建表时,遇到一个奇怪的现象:

复制代码
root@localhost : test 10:30:54>CREATE TABLE tb_test ( -> recordid varchar(32) NOT NULL, -> areaShow varchar(10000) DEFAULT NULL, -> areaShow1 varchar(10000) DEFAULT NULL, -> areaShow2 varchar(10000) DEFAULT NULL, -> PRIMARY KEY (recordid) -> ) ENGINE=INNODB DEFAULT CHARSET=utf8; ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs 报错
root@localhost : test 10:31:01>CREATE TABLE tb_test ( -> recordid varchar(32) NOT NULL, -> areaShow varchar(30000) DEFAULT NULL, -> areaShow1 varchar(30000) DEFAULT NULL, -> areaShow2 varchar(30000) DEFAULT NULL, -> PRIMARY KEY (recordid) -> ) ENGINE=INNODB DEFAULT CHARSET=utf8; Query OK, 0 rows affected, 3 warnings (0.26 sec) 可以建立只是类型被转换了。
root@localhost : test 10:31:14>show warnings; +-------+------+----------------------------------------------------+ | Level | Code | Message | +-------+------+----------------------------------------------------+ | Note | 1246 | Converting column 'areaShow' from VARCHAR to TEXT | | Note | 1246 | Converting column 'areaShow1' from VARCHAR to TEXT | | Note | 1246 | Converting column 'areaShow2' from VARCHAR to TEXT | +-------+------+----------------------------------------------------+ 3 rows in set (0.00 sec)
复制代码

疑问:

为什么字段小(10000)的反而报错,而大(30000)的则可以建立。为什么小的不能直接转换呢?

解决:

这里多感谢orczhou的帮助,原来MySQL在建表的时候有个限制:MySQL要求一个行的定义长度不能超过65535。具体的原因可以看:

http://dev.mysql.com/doc/refman/5.1/en/silent-column-changes.html

(1)单个字段如果大于65535,则转换为TEXT 。

(2)单行最大限制为65535,这里不包括TEXT、BLOB。

按照上面总结的限制,来解释出现的现象:

第一个情况是:
单个字段长度:varchar(10000) ,字节数:10000*3(utf8)+(1 or 2) = 30000 ,小于65535,可以建立。
单行记录长度:varchar(10000)*3,字节数:30000*3(utf8)+(1 or 2) = 90000,大于65535,不能建立,所以报错:

ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs

第二个情况是:
单个字段长度:varchar(30000) ,字节数:30000*3+(1 or 2) = 90000 , 大于65535,需要转换成TEXT,才可以建立。所以报warnings。
单行记录长度:varchar(30000)*3,因为每个字段都被转换成了TEXT,而TEXT没有限制,所以可以建立表。

复制代码
root@localhost : test 10:31:14>show warnings; +-------+------+----------------------------------------------------+ | Level | Code | Message | +-------+------+----------------------------------------------------+ | Note | 1246 | Converting column 'areaShow' from VARCHAR to TEXT | | Note | 1246 | Converting column 'areaShow1' from VARCHAR to TEXT | | Note | 1246 | Converting column 'areaShow2' from VARCHAR to TEXT | +-------+------+----------------------------------------------------+
复制代码

用了这么久的MySQL,这个基本的建表限制都还不知道,惭愧啊。。

 

 

原因如下:

 

  被问到一个问题:MySQL中varchar最大长度是多少?这不是一个固定的数字。本文简要说明一下限制规则。

 

 

1、限制规则

 

字段的限制在字段定义的时候有以下规则:

 

 

 

a)                  存储限制

 

varchar 字段是将实际内容单独存储在聚簇索引之外,内容开头用1到2个字节表示实际长度(长度超过255时需要2个字节),因此最大长度不能超过65535。

 

 

 

b)                  编码长度限制

 

字符类型若为gbk,每个字符最多占2个字节,最大长度不能超过32766;

 

字符类型若为utf8,每个字符最多占3个字节,最大长度不能超过21845。

 

若定义的时候超过上述限制,则varchar字段会被强行转为text类型,并产生warning。

 

 

 

c)                   行长度限制

 

导致实际应用中varchar长度限制的是一个行定义的长度。 MySQL要求一个行的定义长度不能超过65535。若定义的表长度超过这个值,则提示

 

ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs。

 

 

 

2、计算例子

 

举两个例说明一下实际长度的计算。

 

 

 

a)                  若一个表只有一个varchar类型,如定义为

 

create table t4(c varchar(N)) charset=gbk;

 

则此处N的最大值为(65535-1-2)/2= 32766。

 

减1的原因是实际行存储从第二个字节开始’;

 

减2的原因是varchar头部的2个字节表示长度;

 

除2的原因是字符编码是gbk。

 

 

 

b)                  若一个表定义为

 

create table t4(c int, c2 char(30), c3 varchar(N)) charset=utf8;

 

则此处N的最大值为 (65535-1-2-4-30*3)/3=21812

 

减1和减2与上例相同;

 

减4的原因是int类型的c占4个字节;

 

减30*3的原因是char(30)占用90个字节,编码是utf8。

 

 

 

       如果被varchar超过上述的b规则,被强转成text类型,则每个字段占用定义长度为11字节,当然这已经不是“varchar”了。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6月前
|
Oracle 关系型数据库 MySQL
实时计算 Flink版操作报错合集之用CTAS从mysql同步数据到hologres,改了字段长度,报错提示需要全部重新同步如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
156 8
|
6月前
|
关系型数据库 MySQL
mysql及sqlserver修改字段名和字段长度
mysql及sqlserver修改字段名和字段长度
89 0
|
SQL 关系型数据库 MySQL
MYSQL中LIMIT语句(限制语句)
记录下MYSQL中LIMIT语句的基本使用
188 0
MYSQL中LIMIT语句(限制语句)
|
关系型数据库 MySQL 索引
mysql更新varchar类型字段长度报错:ERROR 1074 (42000): Column length too big for column ‘value‘ (max = 21845);
mysql更新varchar类型字段长度报错:ERROR 1074 (42000): Column length too big for column ‘value‘ (max = 21845);
|
关系型数据库 MySQL
MySQL练习4——查询结果限制返回行数
MySQL练习4——查询结果限制返回行数!
|
存储 关系型数据库 MySQL
MySQL启用GTID的限制
开启 GTID 之后,会由部分的限制,内容如下: 更新非事务引擎表GTID 同步复制是基于事务的,所以 MyISAM 存储引擎不支持,这可能导致多个 GTID 分配给同一个事务。 使用GTID时,使用非事务性存储引擎(如MyISAM)对表的更新不能在与使用事务性存储引擎(如InnoDB)的表的更新相同的语句或事务中进行。
2975 0
|
大数据 关系型数据库 MySQL
MYSQL中group_concat有长度限制!默认1024(转载)
在mysql中,有个函数叫“group_concat”,平常使用可能发现不了问题,在处理大数据的时候,会发现内容被截取了,其实MYSQL内部对这个是有设置的,默认不设置的长度是1024,如果我们需要更大,就需要手工去修改配置文件。
4765 0
|
存储 SQL 缓存
InnoDB(1)变长字段长度列表--mysql从入门到精通(六)
InnoDB(1)变长字段长度列表--mysql从入门到精通(六)
|
SQL 关系型数据库 MySQL
Mysql常用sql语句(6)- limit 限制查询结果的条数
Mysql常用sql语句(6)- limit 限制查询结果的条数
1471 0
Mysql常用sql语句(6)- limit 限制查询结果的条数
|
存储 关系型数据库 MySQL
MySQL原理 - InnoDB表的限制
MySQL原理 - InnoDB表的限制
下一篇
无影云桌面