mysql数据类型使用及应用场景

本文主要介绍MYSQL数据类型的使用以及常见的应用场景。

一、数值类型

1. 整数类型

类型 所占字节 范围(有符号) 范围(无符号) 用途
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)

注意

  1. 带符号与不带符号区别(unsigned)
# 带符号
create  table  demo(num1  int, num2  tinyint);

# 不带符号的设置如下
create  table  demo(num1  int  unsigned, num2  tinyint  unsigned);

  1. int(1)与int(11)区别

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类型的显示宽度将失效。

  1. ZEROFILL
    0填充,(如果某列是ZEROFILL,那么MySQL会自动为当前列添加UNSIGNED属性),如果指 定了ZEROFILL只是表示不够M位时,用0在左边填充,如果超过M位,只要不超过数据存储范围即可。

当使用ZEROFILL时,会自动添加UNSIGNED

2. 浮点类型

类型 所占字节 范围(有符号) 范围(无符号) 用途
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位有效数字

精度说明

  • MYSQL允许使用的非标准语法(其他数据库未必支持,所以如果涉及到数据迁移最好不要使用), 其中M称为精度,D称为标度。(M,D)中M=整数位+小数位,D=小数位。D<=M<=255,0<=D<=30。
    例1:float(5, 2)一个列可以显示为-999.99 - 999.99 如果超出这个范围会报错。
    例2:float(1, 1)一个列可以显示为-0.9 - 0.9 如果超出这个范围会报错。
    例3:float 精度(尾数)为6~7位有效数字,插入11111111.11,实际显示11111100
  • 如果存储时整数部分超过了范围,MYSQL就会报错,不允许存这样的值。
  • 如果存储时小数部分超过了范围,就分以下情况
    1. 若四舍五入后,整数部分没有超过范围,能成功操作并四舍五入删除多余的小数位后保存。例如float(5, 2)内插入999.009,结果为999.01。
    2. 若四舍五入后,整数部分超过范围,则MYSQL报错,并拒绝处理。例如float(5, 2)内插入999.995或-999.995都会报错。
  • 从8.0.17版本开始float[(M,D)和double[(M,D)]的用法在官网已经明确不推荐使用,将来可能会被移除。

3. 定点数类型

类型 所占字节 范围 用途
decimal[(m,d)] [unsigned] m+2 Bytes 依赖于M和D的值 小数值,如金钱,财务相关的数据

精度说明

  • 使用 DECIMAL(M,D) 的方式表示高精度小数。其中,M被称为精度,D被称为标度。0<=M<=65, 0<=D<=30,D < M
  • DECIMAL(M,D)的最大取值范围与DOUBLE类型一样,但是有效的数据范围是由M和D决定的。 DECIMAL 的存储空间并不是固定的,由精度值M决定,总共占用的存储空间为M+2个字节(我理解按字符串存储,那么一个数字就是一个字节总共有M个数字就是M个字符,然后小数点算一个字符,考虑有无符号留一个字符所以是M+2)。
  • 相比于float,double类型,decimal类型属于精确类型,不会丢失精度,所以只要涉及到金钱,财务相关的数据,对应的类型一定要选择decimal。
  • 当DECIMAL类型不指定精度和标度时,其默认为DECIMAL(10,0)。当数据的精度超出了定点数类型的 精度范围时,则MySQL同样会进行四舍五入处理。

4. 位类型

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

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)

TIMESTAMP和DATETIME的异同

  • 从存储时间范围看 DATETIME > TIMESTAMP
  • 从使用方便上看 带有自动更新 DATETIME , TIMESTAMP
  • 从时间精度看 DATETIME > TIMESTAMP
  • 从存储空间上看,同一精度下DATETIME > TIMESTAMP
  • 从查询速度上看,底层都是整型存储,所以 DATETIME = TIMESTAMP

不考虑存储空间优化的情况下,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个字节 极大文本数据

特点

CHAR类型

  • CHAR(M) 类型一般需要预先定义字符串长度。如果不指定(M),则表示长度默认是1个字符。
  • 如果保存时,数据的实际长度比CHAR类型声明的长度小,则会在右侧填充空格以达到指定的长度。当MySQL检索CHAR类型的数据时,CHAR类型的字段会去除尾部的空格。
  • 定义CHAR类型字段时,声明的字段长度即为CHAR类型字段所占的存储空间的字节数。

VARCHAR类型

  • VARCHAR(M) 定义时, 必须指定长度M,否则报错。
  • MySQL4.0版本以下,varchar(20):指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字 节) ;MySQL5.0版本以上,varchar(20):指的是20字符。
  • 检索VARCHAR类型的字段数据时,会保留数据尾部的空格。VARCHAR类型的字段所占用的存储空间为字符串实际长度加1个字节。

注意:

由于其最长的限制是字节数,因此存储中文和英文的实际字符个数是不同的;

  • 英文:一个字符占一个字节;
  • 中文(gbk编码):一个字符占2个字节;
  • 中文(utf8编码):一个字符占3个字节;

哪些情况使用 CHAR 或 VARCHAR 更好

  1. 存储很短的信息。比如门牌号码101,201……这样很短的信息应该用char,因为varchar还要占个 byte用于存储信息长度,本来打算节约存储的,结果得不偿失。
  2. 固定长度的。比如使用uuid作为主键,那么使用char更合适。
  3. 字段长度在一定范围内不确定的用varchar,比如名字在2-10个字之间那么用varchar更好,因为char会浪费更多的存储空间。

总结:

  • 满足条件能用char的用char,因为varchar每次存储都要有额外的计算,得到长度等工作,而这些对于char来说是不需要的 会更好地提高性能。

TEXT类型

由于实际存储的长度不确定,MySQL 不允许 TEXT 类型的字段做主键。遇到这种情况,你只能采用 CHAR(M),或者 VARCHAR(M)。

TEXT文本类型,可以存比较大的文本段,搜索速度稍慢,因此如果不是特别大的内容,建议使用CHAR, VARCHAR来代替。还有TEXT类型不用加默认值,加了也没用。而且text和blob类型的数据删除后容易导致 “空洞”,使得文件碎片比较多,所以频繁使用的表不建议包含TEXT类型字段,建议单独分出去,单独用 一个表。

四、ENUM类型

ENUM类型也叫作枚举类型,ENUM类型的取值范围需要在定义字段时进行指定。设置字段值时,ENUM 类型只允许从成员中选取单个值,不能一次选取多个值。 其所需要的存储空间由定义ENUM类型时指定的成员个数决定。

类型 所占字节 范围 用途
ENUM 1或2个字节 1<=L<=65535 枚举(一次选取单个值)
  • 当ENUM类型包含1~255个成员时,需要1个字节的存储空间;
  • 当ENUM类型包含256~65535个成员时,需要2个字节的存储空间。
  • ENUM类型的成员个数的上限为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)

五、SET类型

  • SET表示一个字符对象,可以包含0个或多个成员,但成员个数的上限为64,设置字段值时,可以取取值范围内的0个或多个值。
  • SET类型在存储数据时成员个数越多,其占用的存储空间越大。注意:SET类型在选取成员时,可以一次选择多个成员,这一点与ENUM类型不同。
成员范围个数(范围) 所占字节
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中的二进制字符串类型主要存储一些二进制数据,比如可以存储图片、音频和视频等二进制数据。

1.BINARY与VARBINARY类型

  • BINARY和VARBINARY类似于CHAR和VARCHAR,只是它们存储的是二进制字符串。
  • BINARY (M)为固定长度的二进制字符串,M表示最多能存储的字节数,取值范围是0~255个字符。如果未指定(M),表示只能存储1个字节 。例如BINARY (8),表示最多能存储8个字节,如果字段值不足(M)个字 节,将在右边填充’\0’以补齐指定长度。
  • VARBINARY (M)为可变长度的二进制字符串,M表示最多能存储的字节数,总字节数不能超过行的字节长度限制65535,另外还要考虑额外字节开销,VARBINARY类型的数据除了存储数据本身外,还需要1或2个 字节来存储数据的字节数。VARBINARY类型必须指定(M) ,否则报错。
二进制字符串类型 特点 范围 占用空间
BINARY(M) 固定长度 M(0<= M<= 255) M个字节
VARBINARY(M) 可变长度 M(0<= M<= 65535) M+1个字节

2.BLOB类型

  • BLOB是一个二进制大对象 ,可以容纳可变数量的数据。
  • MySQL中的BLOB类型包括TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB 4种类型,它们可容纳值的最大长度不同。可以存储一个二进制的大对象,比如图片 、 音频和视频 等。
  • 需要注意的是,在实际工作中,往往不会在MySQL数据库中使用BLOB类型存储大对象数据,通常会将图片、音频和视频文件存储到服务器的磁盘上 ,并将图片、音频和视频的访问路径存储到MySQL中。
二进制字符串类型 值的长度 长度范围 占用空间
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类型

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)

你可能感兴趣的:(MySQL,mysql,数据库,database)