【MySQL】mysql数据类型

【MySQL】mysql数据类型

数据类型的分类

整形类型

数据类型 有符号 无符号
TINYINT(tinyint) -128 ~ 127 0 ~ 255
SMALLINT(smallint) -32768~32767 0~65535
MEDIUMINT(mediumint) -8388608~8388607 0~16777215
INT(int) -2147483648~2147483647 0~4294967295
BIGINT(bigint) -9223372036854775808~9223372036854775807 0~18446744073709551615
  • 数据库中提供了很多种整形数据类型,并且每种数据类型的都有详细的范围。在我们学习编程语言的时候,如果我们存储的数据范围超出了类型范围,可能编译器不会给我们报错,而是进行截断或者强制类型转换。但是mysql中是不会这样做的。MySQL中它强制了使用者必须按照类型的数据范围存储,否则就会warning,并且数据将无法插入数据库中。
c 复制代码
mysql> create table db1 (num tinyint);
Query OK, 0 rows affected (0.02 sec)

mysql> insert into db1 values (200);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into db1 values (-200);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
  • 如果直接使用的话默认使用的是有符号的,如果要使用无符号则需要加上unsigned。

bit 类型

基本语法:

c 复制代码
bit[(M)] : 位字段类型。M表示每个值的位数,范围从1到64。如果M被忽略,默认为1。
c 复制代码
mysql> create table db2(id int, num bit(10));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into db2 (id, num) values (1, 2);
Query OK, 1 row affected (0.01 sec)

这里bit内中默认是采用16进制存放的,再老一点的版本可能是以ASCII码值存放的
mysql> select * from db2;
+------+------------+
| id   | num        |
+------+------------+
|    1 | 0x0002     |
+------+------------+
1 row in set (0.01 sec)

bit的范围最大是64;

c 复制代码
mysql> create table db3(id int, num bit(65));
ERROR 1439 (42000): Display width out of range for column 'num' (max = 64)

浮点类型

类型名称 说明 存储需求
FLOAT 单精度浮点数 4个字节
DOUBLE 双精度浮点数 8个字节
DECIMAL(M,D),DEC 压缩的"严格"定点数 M+2个字节
  1. float类型(double是一样的道理)

语法:

c 复制代码
float[(m, d)] [unsigned] : m指定显示长度,d指定小数位数,占用空间4个字节

案例:

小数:float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入。

c 复制代码
mysql> create table db3(id int, num float(4, 2));
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> insert into db3 values (1, 99.99);
Query OK, 1 row affected (0.01 sec)

mysql> insert into db3 values (1, 45.994);
Query OK, 1 row affected (0.00 sec)

mysql> insert into db3 values (1, -99.99);
Query OK, 1 row affected (0.00 sec)

mysql> select * from db3;
+------+--------+
| id   | num    |
+------+--------+
|    1 |  99.99 |
|    1 |  45.99 |
|    1 | -99.99 |
+------+--------+
3 rows in set (0.01 sec)

如果定义的是float(4,2) unsigned 这时,因为把它指定为无符号的数,范围是 0 ~ 99.99

c 复制代码
mysql> create table db4(id int, num float(4,2) unsigned);
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> insert into db4 values (1, -10.00);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> show warnings;
+-------+------+----------------------------------------------+
| Level | Code | Message                                      |
+-------+------+----------------------------------------------+
| Error | 1264 | Out of range value for column 'num' at row 1 |
+-------+------+----------------------------------------------+
1 row in set (0.01 sec)
  1. decimal类型

语法:

c 复制代码
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数

decimal和float很像,但是有区别,float和decimal表示的精度不一样

c 复制代码
mysql> create table db6(fnum float(10, 8), dnum decimal(10, 8));
Query OK, 0 rows affected, 1 warning (0.02 sec)

虽然插入的数据是相同的
mysql> insert into db6 (fnum, dnum) values(23.12345612, 23.12345612);
Query OK, 1 row affected (0.00 sec)

但是float会丢失精度,而decimal不会
mysql> select * from db6;
+-------------+-------------+
| fnum        | dnum        |
+-------------+-------------+
| 23.12345695 | 23.12345612 |
+-------------+-------------+
1 rows in set (0.00 sec)

日期/时间类型

类型名称 日期格式 日期范围 存储需求
YEAR YYYY 1901~2155 1字节
TIME HH:MM:SS -838:59:59~838:59:59 3字节
DATE YYYY-MM-DD 1000-01-01~9999-12-3 3字节
DATETIME YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00~9999-12-31 23:59:59 8字节
TIMESTAMP YYYY-MM-DD HH:MM:SS 1970-01-01 UTC ~ 2038-01-19 03:14:07 UTC 4字节

常用的日期有如下三个:

  • date :日期 'yyyy-mm-dd' ,占用三字节
  • datetime 时间日期格式 'yyyy-mm-dd HH:ii:ss' 表示范围从 1000 到 9999 ,占用八字节
  • timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用四字节
c 复制代码
mysql> create table d10(t1 date, t2 datetime, t3 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.03 sec)

mysql> insert into d10 (t1, t2) values ('2024-8-10', '2024-8-10 8:8:8');
Query OK, 1 row affected (0.00 sec)

mysql> select * from d10;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 2024-08-10 | 2024-08-10 08:08:08 | 2024-08-10 17:41:50 |
+------------+---------------------+---------------------+
1 row in set (0.00 sec)

mysql> update d10 set t2='2024-8-10 8:8:9';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from d10;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 2024-08-10 | 2024-08-10 08:08:09 | 2024-08-10 17:42:24 |
+------------+---------------------+---------------------+
1 row in set (0.00 sec)

字符串类型

类型名称 说明 存储需求
CHAR(M) 固定长度非二进制字符串 M字节,1<=M<=255
VARCHAR(M) 变长非二进制字符串 L+1字节,在此L<=M和1<=M<=65535个字节
TINYTEXT 非常小的非二进制字符串 L+1字节,在此L<2^8
TEXT 小的非二进制字符串 L+2字节,在此L<2^16
MEDIUMTEXT 中等大小的非二进制字符串 L+3字节,在此L<2^32
LONGTEXT 大的非二进制字符串 L+4字节,在此L<2^24
ENUM 枚举类型,只能有一个枚举字符串值 1或2个字节,取决于枚举值数目(最大值65535)
SET 一个设置,字符串对象可以有0个或多个SET成员 1,2,3,4或8个字节,取决于集合成员的数量(最多64个成员)
  1. char类型

语法:

c 复制代码
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
c 复制代码
mysql> create table db7(id int, str char(2));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into db7 values(1, 'a');
Query OK, 1 row affected (0.01 sec)

mysql> insert into db7 values(1, 'ab');
Query OK, 1 row affected (0.01 sec)

mysql> insert into db7 values(1, '中国');
Query OK, 1 row affected (0.00 sec)

mysql> insert into db7 values(1, '中国人');
ERROR 1406 (22001): Data too long for column 'str' at row 1
mysql> select * from db7;
+------+--------+
| id   | str    |
+------+--------+
|    1 | a      |
|    1 | ab     |
|    1 | 中国   |
+------+--------+
3 rows in set (0.00 sec)

说明:

char(2) 表示可以存放两个字符,可以是字母或汉字,但是不能超过2个, 最多只能是255

  1. varchar类型

语法:

c 复制代码
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节
c 复制代码
mysql> create table db8 (id int ,name varchar(6)); --表示这里可以存放6个字符
mysql> insert into db8 values(100, 'hello'); 
mysql> insert into db8 values(100, '我爱你,中国');
mysql> select * from db8;
+------+--------------------+
| id   | name               |
+------+--------------------+
|  100 | hello              |
|  100 | 我爱你,中国         |
+------+--------------------+ 

这里会发现提示varchar最大的16383,不是说了是65535字节吗,这里16383表示的是字符,16383 * 4 == 65532,而varchar之所以是变长字符,是因为varchar有1 - 3 个字节用于记录数据大小,所以说有效字节数是65532。

c 复制代码
mysql> alter table db8 modify name varchar(65535);
ERROR 1074 (42000): Column length too big for column 'name' (max = 16383); use BLOB or TEXT instead

在最新的MySQL中当如果我们的表的编码是utf8时,varchar(n)的参数n最大值是65532/4=16383[因为utf中,一个字符占

用4个字节],如果编码是gbk,varchar(n)的参数n最大是65532/2=32766(因为gbk中,一个字符占用2字节)。

这里我们同时也会发现,varchar的长度其实还跟行字段有关,也就说如果行字段更多其实varchar的边长最大值其实是会越来也少的

c 复制代码
mysql> alter table db8 modify str varchar(16383);
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> alter table db8 modify str varchar(16382);
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> alter table db8 modify str varchar(16381);
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> alter table db8 modify str varchar(16380);
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> alter table db8 modify str varchar(16379);
mysql> desc db8;
+-------+----------------+------+-----+---------+-------+
| Field | Type           | Null | Key | Default | Extra |
+-------+----------------+------+-----+---------+-------+
| id    | int            | YES  |     | NULL    |       |
| name  | char(3)        | YES  |     | NULL    |       |
| str   | varchar(16379) | YES  |     | NULL    |       |
+-------+----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)


mysql> alter table db9 modify str varchar(16383);
Query OK, 0 rows affected (0.05 sec)
mysql> desc db9;
+-------+----------------+------+-----+---------+-------+
| Field | Type           | Null | Key | Default | Extra |
+-------+----------------+------+-----+---------+-------+
| str   | varchar(16383) | YES  |     | NULL    |       |
+-------+----------------+------+-----+---------+-------+
1 row in set (0.00 sec)
  1. char与varchar的比较
  • 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
  • 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
  • 定长的磁盘空间比较浪费,但是效率高。
  • 变长的磁盘空间比较节省,但是效率低。
  • 定长的意义是,直接开辟好对应的空间
  • 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。
  1. enum和set

语法:

  • enum:枚举,"单选"类型;

    enum('选项1','选项2','选项3',...);

    该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;而且出于效率考虑,这些值实际存储的是"数字",因为这些选项的每个选项值依次对应如下数字:1,2,3,...最多65535个;当我们添加枚举值时,也可以添加对应的数字编号。

  • set:集合,"多选"类型;

    set('选项值1','选项值2','选项值3', ...)

    该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值;而且出于效率考虑,这些值实际存储的是"数字",而这个数字是使用位图的方式进行存储的,因为这些选项的每个选项值依次对应如下数字:1,2,4,8,16,32,... 最多64个。

示例:

c 复制代码
mysql> create table db11(
    -> name varchar(20),
    -> gender enum('男','女'),
    -> hobby set('代码','篮球','乒乓球','足球','羽毛球')
    -> );
    
mysql> desc db11;
+--------+---------------------------------------------------------+------+-----+---------+-------+
| Field  | Type                                                    | Null | Key | Default | Extra |
+--------+---------------------------------------------------------+------+-----+---------+-------+
| name   | varchar(20)                                             | YES  |     | NULL    |       |
| gender | enum('男','女')                                         | YES  |     | NULL    |       |
| hobby  | set('代码','篮球','乒乓球','足球','羽毛球')             | YES  |     | NULL    |       |
+--------+---------------------------------------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

enum示例:
mysql> insert into db11 (name, gender) values ('张三','男');
Query OK, 1 row affected (0.01 sec)

mysql> insert into db11 (name, gender) values ('李四',2); // 可以使用下标插入
Query OK, 1 row affected (0.01 sec)

mysql> insert into db11 (name, gender) values ('赵六','不确定'); // 只能插入enum中有的
ERROR 1265 (01000): Data truncated for column 'gender' at row 1
mysql> select * from db11;
+--------+--------+-------+
| name   | gender | hobby |
+--------+--------+-------+
| 张三   | 男     | NULL  |
| 李四   | 女     | NULL  |
+--------+--------+-------+
2 rows in set (0.00 sec)


set示例:
mysql> insert into db11 (name, hobby) values ('孙悟空','代码');
Query OK, 1 row affected (0.01 sec)

mysql> insert into db11 (name, hobby) values ('八戒','乒乓球,.羽毛球')
Query OK, 1 row affected (0.00 sec)

mysql> insert into db11 (name, hobby) values ('玄奘',1); // 这里有五个爱好分别对应着五个bit为00000,00001就是代表代码
Query OK, 1 row affected (0.01 sec)

mysql> insert into db11 (name, hobby) values ('玄奘',2); // 00010 就是代表篮球
Query OK, 1 row affected (0.01 sec)

mysql> insert into db11 (name, hobby) values ('玄奘',31); // 11111 就是代表全部都有
Query OK, 1 row affected (0.01 sec)

mysql> select * from db11;
+-----------+--------+------------------------------------------+
| name      | gender | hobby                                    |
+-----------+--------+------------------------------------------+
| 张三      | 男     | NULL                                      |
| 李四      | 女     | NULL                                      |
| 孙悟空    | NULL   | 代码                                      |
| 八戒      | NULL   | 乒乓球,羽毛球                              |
| 玄奘      | NULL   | 代码                                      |
| 玄奘      | NULL   | 篮球                                      |
| 玄奘      | NULL   | 代码,篮球,乒乓球,足球,羽毛球                 |
+-----------+--------+------------------------------------------+
7 rows in set (0.00 sec)

所以总结就是,enum和set都是可以做到选择所提供的选项的,但是对于enum来讲的,enum只能选择所以提供的选项之一,可以使用文本插入,也可以使用下标插入,但是在使用文本插入的时候必须和选项一摸一样。而set的话它可以做到选择多个选项,但是要注意的是,如果使用数字添加的话,set是使用位图的形式存储的。

  1. enum和set类型查找

对于enum来讲的话,因为enum是多选一,所以也就可以对单一的条件进行查询

c 复制代码
mysql> select * from db11 where gender='男';
+--------+--------+-------+
| name   | gender | hobby |
+--------+--------+-------+
| 张三   | 男     | NULL  |
+--------+--------+-------+
1 row in set (0.00 sec)

mysql> select * from db11 where gender=2;
+--------+--------+-------+
| name   | gender | hobby |
+--------+--------+-------+
| 李四   | 女     | NULL  |
+--------+--------+-------+
1 row in set (0.00 sec)

但是对于set来讲的话,set是可以存放多条记录的,所以这里需要引入一个函数find_in_set;

c 复制代码
mysql> select find_in_set('a','a,c,d');
+--------------------------+
| find_in_set('a','a,c,d') |
+--------------------------+
|                        1 |
+--------------------------+
1 row in set (0.00 sec)

mysql> select find_in_set('b','a,c,d');
+--------------------------+
| find_in_set('b','a,c,d') |
+--------------------------+
|                        0 |
+--------------------------+
1 row in set (0.00 sec)

mysql> select find_in_set('d','a,c,d');
+--------------------------+
| find_in_set('d','a,c,d') |
+--------------------------+
|                        3 |
+--------------------------+
1 row in set (0.00 sec)

从find_in_set函数我们可以发现,这个函数可以做到查看某个字段是否在一个集合当中。

c 复制代码
mysql> select * from db11 where find_in_set('代码',hobby);
+-----------+--------+------------------------------------------+
| name      | gender | hobby                                    |
+-----------+--------+------------------------------------------+
| 孙悟空    | NULL   | 代码                                     |
| 玄奘      | NULL   | 代码                                     |
| 玄奘      | NULL   | 代码,篮球,乒乓球,足球,羽毛球             |
+-----------+--------+------------------------------------------+
3 rows in set (0.00 sec)

mysql> select * from db11 where find_in_set('代码',hobby) and find_in_set('篮球',hobby);
+--------+--------+------------------------------------------+
| name   | gender | hobby                                    |
+--------+--------+------------------------------------------+
| 玄奘   | NULL   | 代码,篮球,乒乓球,足球,羽毛球             |
+--------+--------+------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from db11 where find_in_set('代码',hobby) or find_in_set('篮球',hobby);
+-----------+--------+------------------------------------------+
| name      | gender | hobby                                    |
+-----------+--------+------------------------------------------+
| 孙悟空    | NULL   | 代码                                     |
| 玄奘      | NULL   | 代码                                     |
| 玄奘      | NULL   | 篮球                                     |
| 玄奘      | NULL   | 代码,篮球,乒乓球,足球,羽毛球             |
+-----------+--------+------------------------------------------+
4 rows in set (0.00 sec)

二进制类型

类型名称 说明 存储需求
BIT(M) 位字段类型 大约(M+7)/8个字节
BINARY(M) 固定长度二进制字符串 M个字节
VARBINARY(M) 可变长度二进制字符串 M+1个字节
TINYBLOB(M) 非常小的BLOB L+1个字节,在此L<2^8
BLOB(M) 小BLOB L+2字节,在此L<2^16
MEDIUMBLOB(M) 中等大小的BLOB L+3字节,在此L<2^24
LONGBLOB(M) 非常大的BLOB L+4字节,在此L<2^32
相关推荐
希忘auto22 分钟前
详解MySQL安装
java·mysql
运维佬29 分钟前
在 MySQL 8.0 中,SSL 解密失败,在使用 SSL 加密连接时出现了问题
mysql·adb·ssl
Leo.yuan34 分钟前
数据量大Excel卡顿严重?选对报表工具提高10倍效率
数据库·数据分析·数据可视化·powerbi
Runing_WoNiu43 分钟前
MySQL与Oracle对比及区别
数据库·mysql·oracle
天道有情战天下1 小时前
mysql锁机制详解
数据库·mysql
看山还是山,看水还是。1 小时前
Redis 配置
运维·数据库·redis·安全·缓存·测试覆盖率
谷新龙0011 小时前
Redis运行时的10大重要指标
数据库·redis·缓存
CodingBrother1 小时前
MySQL 中单列索引与联合索引分析
数据库·mysql
精进攻城狮@1 小时前
Redis缓存雪崩、缓存击穿、缓存穿透
数据库·redis·缓存
小酋仍在学习1 小时前
光驱验证 MD5 校验和
数据库·postgresql