跳到主要内容 MySQL 数据类型详解 | 极客日志
SQL
MySQL 数据类型详解 MySQL 数据类型涵盖整型、浮点型、字符串、日期及枚举集合类型。整型支持有符号与无符号,tinyint 范围小。浮点型 float 存在精度损失,decimal 适合高精度场景。字符串 char 为定长,varchar 为变长,根据长度变化选择。日期类型包括 date、datetime 和 timestamp,后者自动更新。枚举和集合用于限制取值范围,查询时使用 find_in_set 处理集合类型。
晚风告白 发布于 2026/2/8 更新于 2026/4/18 2 浏览数据类型
数据类型分类
数据类型
整型可以指定是有符号的和无符号的,默认是有符号的。
无符号的后面要加上 unsigned。
tinyint 类型(整型)
INSERT INTO `value ` VALUES (-128 );
INSERT INTO `value ` VALUES (127 );
INSERT INTO `value ` VALUES (0 );
INSERT INTO `value ` VALUES (1 );
INSERT INTO `value ` VALUES (-1 );
超过 tinyint 的范围则无法插入。注意:创建表的时候要在某个库里面创建。
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 SQL 美化和格式化 在线格式化和美化您的 SQL 查询(它支持各种 SQL 方言)。 在线工具,SQL 美化和格式化在线工具,online
SQL转CSV/JSON/XML 解析 INSERT 等受限 SQL,导出为 CSV、JSON、XML、YAML、HTML 表格(见页内语法说明)。 在线工具,SQL转CSV/JSON/XML在线工具,online
CSV 工具包 CSV 与 JSON/XML/HTML/TSV/SQL 等互转,单页多 Tab。 在线工具,CSV 工具包在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
INSERT INTO `value ` VALUES (0 );
INSERT INTO `value ` VALUES (255 );
总结
MySQL 规定了数据类型不会发生截断,保证了数据的完整性和确定性,也就是在规定的范围内才可以插入数据。
数据类型本身也是一种约束。
什么是约束呢?让程序员正确地插入,约束使用者,保证插入的合法性和可预期性。
MySQL 表中建立属性列的规则:列名称 类型在后。
注意:尽量不使用 unsigned,对于 int 类型可能存放不下的数据,int unsigned 同样可能存放不下,与其如此,还不如设计时,将 int 类型提升为 bigint 类型。
bit 类型(字节)
bit[(M)] : 位字段类型。M 表示每个值的位数,范围从 1 到 64。如果 M 被忽略,默认为 1。
CREATE TABLE t3 (id INT , online BIT);
INSERT INTO t3 (id, online) VALUES (123 , 1 );
INSERT INTO t3 (id, online) VALUES (124 , 0 );
SELECT * FROM t3;
实际上查表的时候是以 ASCII 的形式存的,当前的 ASCII 是不可显示。
使用 16 进制的方式显示。
ALTER TABLE t3 MODIFY online BIT(10 );
INSERT INTO t3 (id, online) VALUES (123 , 97 );
INSERT INTO t3 (id, online) VALUES (123 , 'a' );
SELECT * FROM t3;
浮点类型
float 类型
float[(m, d)] [unsigned] : M 指定显示总长度,d 指定小数位数,占用空间 4 个字节。
案例 :小数:float(4,2) 表示的范围是 -99.99 ~ 99.99,MySQL 在保存值时会进行四舍五入。
CREATE TABLE t5 (id INT , salary FLOAT (4 ,2 ));
INSERT INTO t5 (id, salary) VALUES (123 , 99.99 );
INSERT INTO t5 (id, salary) VALUES (123 , -99.99 );
INSERT INTO t5 (id, salary) VALUES (123 , 10.0 );
INSERT INTO t5 (id, salary) VALUES (123 , 1.00 );
float 也不能超过范围。
精度比规定的精度要高,不会拦截,会进行四舍五入。
在合法的范围内才可以进行四舍五入。
CREATE TABLE t6 (id BIGINT , salary FLOAT (4 ,2 ) UNSIGNED);
INSERT INTO t5 (id, salary) VALUES (1 , 0.00 );
INSERT INTO t5 (id, salary) VALUES (1 , 99.99 );
无符号的 float 是直接把负数的部分砍掉不要,只保留正数的部分 [0, 99.99]。
默认的 float 会存在精度的损失(整数和小数部分)
ALTER TABLE t6 MODIFY salary FLOAT ;
存的是 32423423422.21,但保存的是 32423400000。
decimal 类型 decimal 类型可以解决 float 的精度损失的问题。
案例 ,float 精度会损失,decimal 会完整保留小数位数,不会损失
CREATE TABLE t6 (salary FLOAT (10 ,8 ), salary1 DECIMAL (10 ,8 ));
INSERT INTO t6 (salary, salary1) VALUES (10.23232232 , 10.23423423 );
float 表示的精度大约是 7 位。
decimal 整数最大位数 m 为 65。支持小数最大位数 d 是 30。如果 d 被省略,默认为 0。如果 m 被省略,默认是 10。
默认的精度不同的 MySQL 版本不一样,最好自己设置。
如果希望小数的精度高,推荐使用 decimal。
字符串类型
char 类型
char(L): 固定长度字符串,L 是可以存储的长度,单位为字符,最大长度值可以为 255。
CREATE TABLE t8 (id INT , name CHAR (2 ));
INSERT INTO t8 (id, name) VALUES (1 , 'a' );
INSERT INTO t8 (id, name) VALUES (1 , 'ab' );
INSERT INTO t8 (id, name) VALUES (1 , '中国' );
MySQL 的一个字符表示只要占一个位置就是一个字符,不像编译器,一个汉字占 3 或者 4 个字节。
varchar(变长字符串)
varchar(L): 可变长度字符串,L 表示字符长度,最大长度 65535 个字节,最大可以存 21845 个字符。
CREATE TABLE t9 (id INT , name VARCHAR (6 ));
INSERT INTO t9 (id, name) VALUES (1 , '中国人,加' );
varchar(6),给了你 6 个字符的空间,如果你只使用 1 个空间,那么就只给你分配一个空间,而 char 是给你分配 6 个空间的。
关于 varchar(len), len 到底是多大,这个 len 值,和表的编码密切相关:
varchar 长度可以指定为 0 到 65535 之间的值,但是有 1 - 3 个字节用于记录数据大小,所以说有效字节数是 65532。
当我们的表的编码是 utf8 时,varchar(n) 的参数 n 最大值是 65532/3=21844(因为 utf8 中,一个字符占用 3 个字节),如果编码是 gbk,varchar(n) 的参数 n 最大是 65532/2=32766(因为 gbk 中,一个字符占用 2 字节)。
CREATE TABLE tt11 (name VARCHAR (21845 )) CHARSET= utf8;
还有就是一行可能会被其他变量分去空间,比如一个字符占 3 个字节,所以说一行的最大空间是 65532 字节。
char 和 varchar 的对比
变长效率低的原因:varchar 需要维护有效字符的长度,需要额外的空间保存字符的长度。
如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5。
如果数据长度有变化,就使用变长 (varchar),比如:名字,地址,但是你要保证最长的能存的进去。
定长的磁盘空间比较浪费,但是效率高。
变长的磁盘空间比较节省,但是效率低。
定长的意义是,直接开辟好对应的空间。
变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。
日期类型
date: 日期 'yyyy-mm-dd',占用三字节(年月日)
datetime: 时间日期格式 'yyyy-mm-dd HH:ii:ss' 表示范围从 1000 到 9999,占用八字节(年月日时分秒,不会随着时间变化而变化的)
timestamp: 时间戳,从 1970 年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用四字节(年月日时分秒,会随着时间变化而变化的)
案例
CREATE TABLE IF NOT EXISTS t11 (t1 DATE , t2 DATETIME, t3 TIMESTAMP );
INSERT INTO t11 (t1, t2) VALUES ('2006-10-01' , '2006-10-01 08:00:00' );
UPDATE t11 SET t1 = '1999-01-01' ;
时间戳的应用场景,比如你发表评论的时间是自动更新的。
固定时间 datetime 的应用场景:比如你的出生年月时分秒,你公司的入职时间。
enum 和 set 类型(枚举和集合)
enum: 枚举,'单选'类型;(多选一)
enum('选项 1','选项 2','选项 3',…);
set: 集合,'多选'类型;(多选多和多选一都可以)
set('选项值 1','选项值 2','选项值 3', …);
CREATE TABLE IF NOT EXISTS votes (usename VARCHAR (30 ), gender ENUM('男' , '女' ), hobby SET ('代码' , '羽毛球' , '乒乓球' ));
DESCRIBE votes \G;
INSERT INTO votes (usename, gender) VALUES ('张三' , '男' );
INSERT INTO votes (usename, gender) VALUES ('张三' , '女' );
INSERT INTO votes (usename, gender) VALUES ('张三' , 1 );
INSERT INTO votes (usename, gender) VALUES ('张三' , 2 );
枚举的下标是从 1 开始的,1 表示男,2 表示女。
INSERT INTO votes (usename, gender, hobby) VALUES ('张三' , 1 , '代码' );
INSERT INTO votes (usename, gender, hobby) VALUES ('张三' , 1 , '羽毛球,足球,游泳' );
INSERT INTO votes VALUES ('张三' , 1 , '羽毛球,足球,游泳' );
NULL vs '' 的区别:NULL 是什么都没有,而''是有只不过是空串(前者就是你没有银行卡,后者就是你有银行卡但是里面没钱)。
多选是位图,00000 表示 0 是代码,00010 表示 2 是羽毛球,00111 表示 7 是代码,羽毛球和乒乓球,1 代表有,0 代表没有。
枚举是下标,下表从 1 开始,集合是位图,7 表示 00111,从左往右选三项运动。
enum 和 set 的查找 SELECT * FROM votes WHERE gender = '男' ;
SELECT * FROM votes WHERE gender = '1' ;
set
集合查询使用 find_in_set 函数:
FIND_IN_SET(sub, str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回 0;
str_list 用逗号分隔的字符串。
SELECT * FROM votes WHERE hobby = '羽毛球' ;
SELECT * FROM votes WHERE FIND_IN_SET('羽毛球' , hobby);
查询爱好里面有羽毛球的,只要有就行。
查询爱好里面有羽毛球的和代码的,不是只有羽毛球和代码的,可以有其他的。