【MySQL】mysql数据类型

数据类型的分类

整形类型

数据类型有符号无符号
TINYINT(tinyint)-128 ~ 1270 ~ 255
SMALLINT(smallint)-32768~327670~65535
MEDIUMINT(mediumint)-8388608~83886070~16777215
INT(int)-2147483648~21474836470~4294967295
BIGINT(bigint)-9223372036854775808~92233720368547758070~18446744073709551615
  • 数据库中提供了很多种整形数据类型,并且每种数据类型的都有详细的范围。在我们学习编程语言的时候,如果我们存储的数据范围超出了类型范围,可能编译器不会给我们报错,而是进行截断或者强制类型转换。但是mysql中是不会这样做的。MySQL中它强制了使用者必须按照类型的数据范围存储,否则就会warning,并且数据将无法插入数据库中。
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 类型

基本语法:

bit[(M)] : 位字段类型。M表示每个值的位数,范围从164。如果M被忽略,默认为1
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;

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是一样的道理)

语法:

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

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

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

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类型

语法:

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

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

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)

日期/时间类型

类型名称日期格式日期范围存储需求
YEARYYYY1901~21551字节
TIMEHH:MM:SS-838:59:59~838:59:593字节
DATEYYYY-MM-DD1000-01-01~9999-12-33字节
DATETIMEYYYY-MM-DD HH:MM:SS1000-01-01 00:00:00~9999-12-31 23:59:598字节
TIMESTAMPYYYY-MM-DD HH:MM:SS1970-01-01 UTC ~ 2038-01-19 03:14:07 UTC4字节

常用的日期有如下三个:

  • date :日期 ‘yyyy-mm-dd’ ,占用三字节
  • datetime 时间日期格式 ‘yyyy-mm-dd HH:ii:ss’ 表示范围从 1000 到 9999 ,占用八字节
  • timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用四字节
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类型

语法:

char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
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类型

语法:

varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节
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。

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的边长最大值其实是会越来也少的

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个。

示例:

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是多选一,所以也就可以对单一的条件进行查询

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;

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函数我们可以发现,这个函数可以做到查看某个字段是否在一个集合当中。

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)非常小的BLOBL+1个字节,在此L<2^8
BLOB(M)小BLOBL+2字节,在此L<2^16
MEDIUMBLOB(M)中等大小的BLOBL+3字节,在此L<2^24
LONGBLOB(M)非常大的BLOBL+4字节,在此L<2^32
  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三问走天下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值