1,整形

对于整形类型的使用 如果设置了显示宽度,那么插入的数据宽度超过显示宽度限制,会不会截断或插入失败?例如:INT(5) 答案:不会对插入的数据有任何影响,还是按照类型的实际宽度进行保存,即 显示宽度与类型可以存储的值范围无关 。从MySQL 8.0.17开始,整数数据类型不推荐使用显示宽度属性
那么这个显示宽度的存在还有什么意义呢?
是用来配合ZEROFILL 一起使用的。 原来,在 int(M) 中,M 的值跟 int(M) 所占多少存储空间并无任何关系。 int(3)、int(4)、int(8) 在磁盘上都是占用 4 bytes 的存储空间。也就是说,int(M),必须和UNSIGNED ZEROFILL一起使用才有意义。如果整数值超过M位,就按照实际位数存储。只是无须再用字符 0 进行填充。
sql
# 创建整形数据
CREATE TABLE test1(
f1 TINYINT,
f2 SMALLINT,
f3 MEDIUMINT
f4 INT,
f5 BIGINT,
);
# 常见报错 (超出范围报错)
# Out of range value for column 'f1' at row 1
INSERT INTO test_int1(f1)
VALUES(128);
# ZEROFILL的用法
CREATE TABLE test_int2(
f1 INT,
f2 INT(5),
f3 INT(5) ZEROFILL #① 显示宽度为5。当insert的值不足5位时,使用0填充。 ②当使用ZEROFILL时,自动会添加UNSIGNED
)
在评估用哪种整数类型的时候,你需要考虑存储空间 和可靠性的平衡问题:一方 面,用占用字节数少的整数类型可以节省存储空间;另一方面,要是为了节省存储空间, 使用的整数类型取值范围太小,一旦遇到超出取值范围的情况,就可能引起 系统错误 ,影响可靠性
2,浮点类型

为什么浮点数类型的无符号数取值范围,只相当于有符号数取值范围的一半,也就是只相当于有符号数取值范围大于等于零的部分呢?
MySQL 存储浮点数的格式为: 符号(S) 、 尾数(M) 和 阶码(E) 。因此,无论有没有符号,MySQL 的浮点数都会存储表示符号的部分。因此, 所谓的无符号数取值范围,其实就是有符号数取值范围大于等于零的部分
所以我们并不用去考虑有符号和无符号类型,因为占用的空间都是一样的,符号的存储方式与证书的存储方式不太一样
MySQL允许使用 非标准语法 (其他数据库未必支持,因此如果涉及到数据迁移,则最好不要这么用): FLOAT(M,D) 或 DOUBLE(M,D) 。这里,M称为 精度 ,D称为 标度 。(M,D)中 M=整数位+小数位,D=小数位。 D<=M<=255,0<=D<=30
如果存储时,小数点部分若超出范围,就分以下情况:
(1)若四舍五入 后,整数部分没有超出范围,则只警告,但能成功操作并四舍五入删除多余的小数位后保存。例如在FLOAT(5,2)列内插入999.009,近似结果是999.01。
(2)若四舍五入 后,整数部分超出范围,则MySQL报错,并拒绝处理。如FLOAT(5,2)列内插入999.995和-999.995都会报错。
从MySQL 8.0.17 开始,FLOAT(M,D) 和**DOUBLE(M,D)**用法在官方文档中已经明确不推荐使用,将来可能被移除。另外,关于浮点型FLOAT和DOUBLE的UNSIGNED也不推荐使用了,将来也可能被移除
在编程中,如果用到浮点数,要特别注意误差问题,因为浮点数是不准确的,所以我们要避免使用"="来判断两个数是否相等,同时,在一些对精确度要求较高的项目中,千万不要使用浮点数,不然会导致结果错误,甚至是造成不可挽回的损失。那么,MySQL 有没有精准的数据类型呢?当然有,这就是定点数类型: DECIMAL
sql
CREATE TABLE test_double2(
f1 DOUBLE
);
INSERT INTO test_double2
VALUES(0.47),(0.44),(0.19);
mysql> SELECT SUM(f1)
-> FROM test_double2;
+--------------------+
| SUM(f1) |
+--------------------+
| 1.0999999999999999 |
+--------------------+
1 row in set (0.00 sec)
mysql> SELECT SUM(f1) = 1.1,1.1 = 1.1
-> FROM test_double2;
+---------------+-----------+
| SUM(f1) = 1.1 | 1.1 = 1.1 |
+---------------+-----------+
| 0 | 1 |
+---------------+-----------+
1 row in set (0.00 sec)
# 如果将上面的类型改为FLOAT类型,现实的数字是1.0999999940395355
3,定点数
使用 DECIMAL(M,D) 的方式表示高精度小数。其中,M被称为精度,D被称为标度。0<=M<=65,0<=D<=30,D<M。例如,定义DECIMAL(5,2)的类型,表示该列取值范围是-999.99~999.99。DECIMAL(M,D) 的最大取值范围与DOUBLE类型一样,但是有效的数据范围是由M和D决定的
DECIMAL 的存储空间并不是固定的,总字节数 = 整数部分存储字节 + 小数部分存储字节 + 符号位(1字节) ,在一些对精度要求不高的场景下,比起占用同样字节长度的定点数,浮点数表达的数值范围可以更大一些,DECIMAL 是十进制定点存储 ,每字节仅能表示少量十进制数字(比如 4 字节最多存 9 位十进制数);而浮点数(如 4 字节 FLOAT)是二进制浮点存储 ,DECIMAL 的十进制存储逻辑是:直接按「十进制数字位」存储(比如 0.1 存储为 "1×10⁻¹",而非二进制循环数),从根源上避免了进制转换的精度丢失。
4,位类型

BIT类型,如果没有指定(M),默认是1位,表示只能存储1位的二进制,这里(M)表示的是二进制的位数,最小值为1,最大值为64
sql
CREATE TABLE test_bit1(
f1 BIT,
f2 BIT(5),
f3 BIT(64)
);
INSERT INTO test_bit1(f1)
VALUES(1);
#Data too long for column 'f1' at row 1
INSERT INTO test_bit1(f1)
VALUES(2);
INSERT INTO test_bit1(f2)
VALUES(23);
mysql> SELECT * FROM test_bit1;
+------------+------------+------------+
| f1 | f2 | f3 |
+------------+------------+------------+
| 0x01 | NULL | NULL |
| NULL | 0x17 | NULL |
+------------+------------+------------+
2 rows in set (0.00 sec)
mysql> SELECT BIN(f2),HEX(f2)
-> FROM test_bit1;
+---------+---------+
| BIN(f2) | HEX(f2) |
+---------+---------+
| NULL | NULL |
| 10111 | 17 |
+---------+---------+
2 rows in set (0.00 sec)
# 使用b+0查询数据的时候,可以直接查询出存储的十进制数据的值
mysql> SELECT f2 + 0
-> FROM test_bit1;
+--------+
| f2 + 0 |
+--------+
| NULL |
| 23 |
+--------+
2 rows in set (0.00 sec)
5,日期与时间类型

1,YEAR
1字节存储空间
以4位字符串或数字格式表示YEAR类型,其格式为YYYY,最小值为1901,最大值为2155
以2位字符串格式表示YEAR类型,最小值为00,最大值为99。 当取值为01到69时,表示2001到2069; 当取值为70到99时,表示1970到1999; 当取值整数的0或00添加的话,那么是0000年; 当取值是日期/字符串的'0'添加的话,是2000年
2位字符串格式表示YEAR的话,这个从MySQL5.5.27开始,2位格式的YEAR已经不推荐使用
2,TIME
3字节存储空间
在MySQL中,向TIME类型的字段插入数据时,也可以使用几种不同的格式。 (1)可以使用带有冒号的 字符串,比如**' D HH:MM:SS' 、' HH:MM:SS '**、' HH:MM '、' D HH:MM '、' D HH '或' SS '格式,都能被正
确地插入TIME类型的字段中。其中D表示天,其最小值为0,最大值为34。如果使用带有D格式的字符串
插入TIME类型的字段时,D会被转化为小时 ,计算格式为D*24+HH。当使用带有冒号并且不带D的字符串
表示时间时,表示当天的时间,比如12:10表示12:10:00,而不是00:12:10。
(2)可以使用不带有冒号的 字符串或者数字,格式为' HHMMSS '或者 HHMMSS 。如果插入一个不合法的字符串或者数字,MySQL在存储数据时,会将其自动转化为00:00:00进行存储。比如1210,MySQL会将最右边的两位解析成秒,表示00:12:10,而不是12:10:00。
(3)使用 CURRENT_TIME() 或者 NOW() ,会插入当前系统的时间。
3,DATE
3字节存储空间
以 YYYY-MM-DD 格式或者 YYYYMMDD 格式表示的字符串日期,其最小取值为1000-01-01,最大取值为9999-12-03。YYYYMMDD格式会被转化为YYYY-MM-DD格式
以 YY-MM-DD 格式或者 YYMMDD 格式表示的字符串日期,此格式中,年份为两位数值或字符串满足YEAR类型的格式条件为:当年份取值为00到69时,会被转化为2000到2069;当年份取值为70到99时,会被转化为1970到1999。
使用 CURRENT_DATE() 或者 NOW() 函数,会插入当前系统的日期
4,DATETIME,TIMESTAMP
都是为可以表示为 YYYY-MM-DD HH:MM:SS ,其中YYYY表示年份,MM表示月份,DD表示日期,HH表示小时,MM表示分钟,SS表示秒。
存储数据的时候需要对当前时间所在的时区进行转换,查询数据的时候再将时间转换回当前的时
区。因此,使用TIMESTAMP存储的同一个时间值,在不同的时区查询时会显示不同的时间

6,文本字符串类型

1,CHAR,VARCHAR

1,CHAR(M) CHAR(M) 类型一般需要预先定义字符串长度。如果不指定(M),则表示长度默认是1个字符。 如果保存时,数据的实际长度比CHAR类型声明的长度小,则会在 右侧填充 空格以达到指定的长度。当MySQL检索CHAR类型的数据时,CHAR类型的字段会去除尾部的空格。 定义CHAR类型字段时,声明的字段长度即为CHAR类型字段所占的存储空间的字节数。
2,VARCHAR(M) VARCHAR(M) 定义时, 必须指定 长度M,否则报错。 MySQL4.0版本以下,varchar(20):指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节) ;MySQL5.0版本以上,varchar(20):指的是20字符。 检索VARCHAR类型的字段数据时,会保留数据尾部的空格。VARCHAR类型的字段所占用的存储空间为字符串实际长度加1个字节。

情况1:存储很短的信息。比如门牌号码101,201......这样很短的信息应该用char,因为varchar还要占个byte用于存储信息长度,本来打算节约存储的,结果得不偿失
情况3:十分频繁改变的column。因为varchar每次存储都要有额外的计算,得到长度等工作,如果一个非常频繁改变的,那就要有很多的精力用于计算,而这些对于char来说是不需要的
2,枚举ENUM和集合SET
1,ENUM

2,SET


