本文主要介绍MYSQL数据类型的使用以及常见的应用场景。
类型 | 所占字节 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
tinyint | 1 Bytes | (-128,127) | (0,255) | 一般用于枚举数据;也可表示Boolean用1表示true,0表示false |
smallint | 2 Bytes | (-215,215 -1) | (0,216-1) | 可用于较小范围的数据统计(数值万级),比如统计工厂的固定资产库存数量 |
mediumint | 3 Bytes | (-223,223 -1) | (0,224-1) | 可用于较大范围的数据统计(数值百万级),比如车站日客流量 |
int | 4 Bytes | (-231,231-1) | (0,232-1) | 大整数值(十亿级),比如商品编号 |
bigint | 8 Bytes | (-263,263-1) | (0,264-1) | 极大整数值,比如流水号,大型门户网站流量统计等 |
在mysql 中存在四个常量分别是true TRUE false FALSE其值分别是1 1 0 0
所以为了方便我们再插入布尔类型数据的时候可以直接使用上面四个常量,或者使用0和1来表示真假
mysql> SELECT true,false,TRUE,FALSE;
+------+-------+------+-------+
| true | false | TRUE | FALSE |
+------+-------+------+-------+
| 1 | 0 | 1 | 0 |
+------+-------+------+-------+
1 row in set (0.00 sec)
# 带符号
create table demo(num1 int, num2 tinyint);
# 不带符号的设置如下
create table demo(num1 int unsigned, num2 tinyint unsigned);
int(1)与int(11)在mysql8.0.17以前,主要区别是显示宽度,所占字节任是4个字节
mysql> create table numDemo
-> (
-> id int(1) unsigned not null,
-> num int(11) not null,
-> primary key (id)
-> )comment 'numDemo';
Query OK, 0 rows affected, 2 warnings (0.05 sec)
mysql> insert into numDemo(id, num)VALUES (111, true);
Query OK, 1 row affected (0.01 sec)
mysql> select * from numDemo;
+-----+-----+
| id | num |
+-----+-----+
| 111 | 1 |
+-----+-----+
1 row in set (0.00 sec)
可以看出mysql8.0.17后int(1)与int(11)已经无任何区别了
官网解释
MySQL Server 8.0.17 deprecated the display width for the TINYINT, SMALLINT, MEDIUMINT, INT, and BIGINT data types when the ZEROFILL modifier is not used, and MySQL Server 8.0.19 has removed the display width for those data types from results of SHOW CREATE TABLE, SHOW CREATE FUNCTION, and queries on INFORMATION_SCHEMA.COLUMNS, INFORMATION_SCHEMA.ROUTINES, and INFORMATION_SCHEMA.PARAMETERS (except for the display width for signed TINYINT(1)). This patch adjusts Connector/J to those recent changes of MySQL Server and, as a result, DatabaseMetaData, ParameterMetaData, and ResultSetMetaData now report identical results for all the above-mentioned integer types and also for the FLOAT and DOUBLE data types. (Bug #30477722)
从8.0.17版本开始,TINYINT, SMALLINT, MEDIUMINT, INT, and BIGINT类型的显示宽度将失效。
当使用ZEROFILL时,会自动添加UNSIGNED
类型 | 所占字节 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
float[(M,D)] [unsigned] | 4 Bytes | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度,浮点数值(m总个数,d小数位数)float的精度(尾数)为6~7位有效数字 |
double[(M,D)] [unsigned] | 8 Bytes | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 单精度,浮点数值(m总个数,d小数位数)double的精度(尾数)为15~16位有效数字 |
类型 | 所占字节 | 范围 | 用途 |
---|---|---|---|
decimal[(m,d)] [unsigned] | m+2 Bytes | 依赖于M和D的值 | 小数值,如金钱,财务相关的数据 |
BIT类型中存储的是二进制值,类似010110。
类型 | 所占字节 | 范围 | 用途 |
---|---|---|---|
bit(M) | M位 | 1<=M<=64 | 类似redis的bitmap,常用于统计签到次数、登录次数等 |
BIT类型,如果没有指定(M),默认是1位。这个1位,表示只能存1位的二进制值。这里(M)是表示二进制的位数,位数最小值为1,最大值为64。
mysql> CREATE TABLE bit1_demo(f1 BIT,f2 BIT(7));
Query OK, 0 rows affected (0.05 sec)
mysql> insert into bit1_demo(f1)value(B'1');
Query OK, 1 row affected (0.01 sec)
mysql> insert into bit1_demo(f1)value(B'11');
ERROR 1406 (22001): Data too long for column 'f1' at row 1 #报错
mysql> insert into bit1_demo(f1)value(2);
ERROR 1406 (22001): Data too long for column 'f1' at row 1 #报错
mysql> insert into bit1_demo(f2)value(B'11');
Query OK, 1 row affected (0.01 sec)
mysql> select * from bit1_demo;
+------------+------------+
| f1 | f2 |
+------------+------------+
| 0x01 | NULL |
| NULL | 0x03 |
+------------+------------+
2 rows in set (0.00 sec)
mysql> select bin(f1),bin(f2) from bit1_demo; #二进制表示
+---------+---------+
| bin(f1) | bin(f2) |
+---------+---------+
| 1 | NULL |
| NULL | 11 |
+---------+---------+
2 rows in set (0.00 sec)
mysql> select hex(f1),hex(f2) from bit1_demo;#十六进制表示
+---------+---------+
| hex(f1) | hex(f2) |
+---------+---------+
| 1 | NULL |
| NULL | 3 |
+---------+---------+
2 rows in set (0.00 sec)
mysql> select f1+0,f2+0 from bit1_demo;#十进制表示
+------+------+
| f1+0 | f2+0 |
+------+------+
| 1 | NULL |
| NULL | 3 |
+------+------+
2 rows in set (0.00 sec)
mysql> select lpad(bin(f2),7,'0') from bit1_demo;#填充0
+---------------------+
| lpad(bin(f2),7,'0') |
+---------------------+
| NULL |
| 0000011 |
+---------------------+
2 rows in set (0.00 sec)
类型 | 所占字节 | 范围 | 格式 | 用途 |
---|---|---|---|---|
date | 3 Bytes | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
time | 3 Bytes | ‘-838:59:59’/‘838:59:59’ | HH:MM:SS | 时间值或持续时间 |
year | 1 Bytes | 1901/2155 | YYYY | 年份值 |
datetime | 8 Bytes | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
timestamp | 4 Bytes | 1970-01-01 00:00:00/2038 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
DATETIME 类型在所有的日期时间类型中占用的存储空间最大,总共需要 8 个字节的存储空间。在格式上为DATE 类型和 TIME 类型的组合,可以表示为 YYYY-MM-DD HH:MM:SS ,其中 YYYY 表示年份, MM 表示月份,DD 表示日期, HH 表示小时, MM 表示分钟, SS 表示秒。
使用函数**CURRENT_TIMESTAMP(), NOW()**可以向datetime类型字段插入系统当前日期和时间。
mysql> CREATE TABLE datetime1_demo (
dt1 DATETIME,
dt2 DATETIME DEFAULT CURRENT_TIMESTAMP, #创建时设置当前时间
dt3 DATETIME ON UPDATE CURRENT_TIMESTAMP #更新时设置当前时间
);
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO datetime1_demo(dt1) values('2022-06-06 19:36:00'),
('20220606193600'),(20220606193600),(CURRENT_TIMESTAMP()), (NOW());
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from datetime1_demo;
+---------------------+---------------------+------+
| dt1 | dt2 | dt3 |
+---------------------+---------------------+------+
| 2022-06-06 19:36:00 | 2022-06-06 20:14:50 | NULL |
| 2022-06-06 19:36:00 | 2022-06-06 20:14:50 | NULL |
| 2022-06-06 19:36:00 | 2022-06-06 20:14:50 | NULL |
| 2022-06-06 20:14:50 | 2022-06-06 20:14:50 | NULL |
| 2022-06-06 20:14:50 | 2022-06-06 20:14:50 | NULL |
+---------------------+---------------------+------+
5 rows in set (0.00 sec)
mysql> update datetime1_demo set dt1=now();
Query OK, 5 rows affected (0.01 sec)
Rows matched: 5 Changed: 5 Warnings: 0
mysql> select * from datetime1_demo;
+---------------------+---------------------+---------------------+
| dt1 | dt2 | dt3 |
+---------------------+---------------------+---------------------+
| 2022-06-06 20:16:18 | 2022-06-06 20:14:50 | 2022-06-06 20:16:18 |
| 2022-06-06 20:16:18 | 2022-06-06 20:14:50 | 2022-06-06 20:16:18 |
| 2022-06-06 20:16:18 | 2022-06-06 20:14:50 | 2022-06-06 20:16:18 |
| 2022-06-06 20:16:18 | 2022-06-06 20:14:50 | 2022-06-06 20:16:18 |
| 2022-06-06 20:16:18 | 2022-06-06 20:14:50 | 2022-06-06 20:16:18 |
+---------------------+---------------------+---------------------+
5 rows in set (0.00 sec)
不考虑存储空间优化的情况下,DATETIME是最优的时间存储类型
考虑存储空间的情况下,TIMESTAMP是最优的时间存储类型
注意 TIMESTAMP 会先将用户输入转换成UTC时间进行存储,查询时也会将时间转换成当前UTC时间,所以当数据库服务器的时区跟查询客户端时区不一致时,会出现查询不到的情况。比如查询客户端与数据库服务器都在中国,北京是东八区 时间是UTC+8小时,那么存储时会先-8小时,查询时+8。
类型 | 范围 | 所占字节 | 用途 |
---|---|---|---|
char(M) | 0<=M<=255 | M个字节 | 定长字符串 |
varchar(M) | 0<=M<=65535 | M+1个字节 | 变长字符串 |
tinytext | 0<=L<=255 | L+2个字节 | 短文本字符串 |
text | 0<=L<=65535 | L+2个字节 | 长文本数据 |
mediumtext | 0<=L<=16 777 215 | L+3个字节 | 中等长度文本数据 |
longtext | 0<=L<=4 294 967 295 | L+4个字节 | 极大文本数据 |
注意:
由于其最长的限制是字节数,因此存储中文和英文的实际字符个数是不同的;
总结:
由于实际存储的长度不确定,MySQL 不允许 TEXT 类型的字段做主键。遇到这种情况,你只能采用 CHAR(M),或者 VARCHAR(M)。
TEXT文本类型,可以存比较大的文本段,搜索速度稍慢,因此如果不是特别大的内容,建议使用CHAR, VARCHAR来代替。还有TEXT类型不用加默认值,加了也没用。而且text和blob类型的数据删除后容易导致 “空洞”,使得文件碎片比较多,所以频繁使用的表不建议包含TEXT类型字段,建议单独分出去,单独用 一个表。
ENUM类型也叫作枚举类型,ENUM类型的取值范围需要在定义字段时进行指定。设置字段值时,ENUM 类型只允许从成员中选取单个值,不能一次选取多个值。 其所需要的存储空间由定义ENUM类型时指定的成员个数决定。
类型 | 所占字节 | 范围 | 用途 |
---|---|---|---|
ENUM | 1或2个字节 | 1<=L<=65535 | 枚举(一次选取单个值) |
优点
mysql> create table enum_demo(season ENUM('春','夏','秋','冬'));
Query OK, 0 rows affected (0.05 sec)
mysql> desc enum_demo;
+--------+-------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------------------+------+-----+---------+-------+
| season | enum('春','夏','秋','冬') | YES | | NULL | |
+--------+-------------------------------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> insert into enum_demo values('ss');#插入枚举值不存在数据会报错
ERROR 1265 (01000): Data truncated for column 'season' at row 1
mysql> insert into enum_demo values('春');
Query OK, 1 row affected (0.01 sec)
mysql> ALTER TABLE enum_demo MODIFY COLUMN season ENUM('春','夏','秋','冬','unknow'); #新增枚举值
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc enum_demo;
+--------+----------------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------------------------------------+------+-----+---------+-------+
| season | enum('春','夏','秋','冬','unknow') | YES | | NULL | |
+--------+----------------------------------------+------+-----+---------+-------+
1 row in set (0.01 sec)
成员范围个数(范围) | 所占字节 |
---|---|
1<=L<=8 | 1个字节 |
9<=L<=16 | 2个字节 |
17<=L<=24 | 3个字节 |
25<=L<=32 | 4个字节 |
33<=L<=64 | 8个字节 |
mysql> CREATE TABLE set_demo(st1 SET('A','B','C'));
Query OK, 0 rows affected (0.05 sec)
mysql> insert into set_demo(st1)values('A'),('A,B');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into set_demo(st1)values('A,B,C,A');#MySQL会自动删除重复的成员
Query OK, 1 row affected (0.00 sec)
mysql> insert into set_demo(st1)values('A,B,C,D');#插入SET成员中不存在的值时,MySQL会抛出错误
ERROR 1265 (01000): Data truncated for column 'st1' at row 1
mysql> select * from set_demo;
+-------+
| st1 |
+-------+
| A |
| A,B |
| A,B,C |
+-------+
3 rows in set (0.00 sec)
MySQL中的二进制字符串类型主要存储一些二进制数据,比如可以存储图片、音频和视频等二进制数据。
二进制字符串类型 | 特点 | 范围 | 占用空间 |
---|---|---|---|
BINARY(M) | 固定长度 | M(0<= M<= 255) | M个字节 |
VARBINARY(M) | 可变长度 | M(0<= M<= 65535) | M+1个字节 |
二进制字符串类型 | 值的长度 | 长度范围 | 占用空间 |
---|---|---|---|
TINYBLOB | L | 0<= M<= 255 | L+1个字节 |
BLOB | L | 0<= M<= 65535(相当于64KB) | L+2个字节 |
MEDIUMBLOB | L | 0<=L<=16777215(相当于16MB) | L+3个字节 |
longblob | L | 0<=L<=4294967295(相当于4GB) | L+4个字节 |
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式 。简洁和清晰的层次结构使得 JSON成为理想的数据交换语言。它易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在网络或者程序之间轻松地传递这个字符串,并在需要的时候将它还原为各编程语言所支持的数据格式。
mysql> CREATE TABLE json_demo(content JSON);
Query OK, 0 rows affected (0.05 sec)
mysql> insert into json_demo(content)values('{"name":"baidu","host":"www.baidu.com"}'),
('{"name":"alibaba","host":"www.alibaba.com"}');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from json_demo;
+------------------------------------------------+
| content |
+------------------------------------------------+
| {"host": "www.baidu.com", "name": "baidu"} |
| {"host": "www.alibaba.com", "name": "alibaba"} |
+------------------------------------------------+
2 rows in set (0.00 sec)
mysql> select JSON_EXTRACT(content,'$.name')as name,JSON_EXTRACT(content,'$.host')as host from json_demo;
+-----------+-------------------+
| name | host |
+-----------+-------------------+
| "baidu" | "www.baidu.com" |
| "alibaba" | "www.alibaba.com" |
+-----------+-------------------+
2 rows in set (0.00 sec)