持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
前言
上篇我们学习了MySQL中的数据类型中的整数。有兴趣的小伙伴可以阅读(# MySQL学习-数据类型-整数)。
下面学习MySQL中的数据类型中的浮点数,定点数类型与位类型。
浮点数类型
类型介绍
浮点数可以处理小数,可以把整数看成小数的一个特例。因此,浮点数的使用场景,比整数大。MySQL支持的浮点数类型,分别是FLOAT、DOUBLE、REAL。
- FLOAT:表示单精度浮点数。占用字节数少,取值范围小。
- DOUBLE:表示双精度浮点数。占用字节数多,取值范围大。
| 类型 | 有符号数取值范围 | 无符号数取值范围 | 占用字节数 |
|---|---|---|---|
| FLOAT | (-3.402823466E+38, -1.175494351E-38), 0, (1.175494351E-38, 3.402823466E+38) | 0, (1.175494351E-38, 3.402823466E+38) | 4 |
| DOUBLE | (-1.7976931348623157E+308, -2.2250738585072014E-308), 0, (2.2250738585072014E-308, 1.7976931348623157E+308) | 0, (2.2250738585072014E-308, 1.7976931348623157E+308) | 8 |
- REAL默认就是DOUBLE。如果把SQL模式设定为启用“REAL_AS_FLOAT”,则MySQL就认为REAL是FLOAT。如果要启用“REAL_AS_FLOAT”,可以通过以下SQL语句实现:
SET sql_mode = "REAL_AS_FLOAT";
精度误差说明
浮点数类型有个缺陷,不精准。下面设计一个表,有f1这个字段,插入值分别为0.47,0.44,0.19,运行SUM函数,我们期待的运行结果是:0.47+0.44+0.19 = 1.1。但是实际运行结果是1.0999999999999999。虽然误差很小,但确实存在误差。为什么会存在误差?问题出在MySQL对浮点类型数据的存储方式上。
MySQL用4个字节存储FLOAT类型数据,用8个字节存储DOUBLE类型数据。无论哪个,都是采用二进制的方式来进行存储的。比如9.625,用二进制,就是1001.101,或者是1.001101*2^3。如果尾数不是0或者5(比如9.264),就无法用一个二进制来精确表达。进而,就只好在取值允许的范围内进行四舍五入。
在实际开发中,如果使用浮点数,需要特别注意误差问题。因为浮点数是不准确的,所以我们要避免使用"="来判断两个数是否相等。同时,在一些对精确度要求较高的项目中,千万不要使用浮点数,不然会导致结果错误,甚至造成不可挽回的损失。那么,MySQL有没有精准的数据类型呢?是有的,就是定点数类型:DECIMAL。
定点数类型
类型介绍
- MySQL中的定点数类型只有DECIMAL一种类型。
| 数据类型 | 字节数 | 含义 |
|---|---|---|
| DECIMAL(M,D),DEC,NUMERIC | M+2字节 | 有效范围由M和D决定 |
使用DECIMAL(M,D)的方式表示高精度小数。其中,M被称为精度,D被称为标度。
- DECIMAL(M,D)的最大取值范围与DOUBLE类型一样,但是有效的数据范围是由M和D决定的。DECIMAL的存储空间并不是固定的,由精度值M决定,总共占用的存储空间为M+2个字节。也就是说,在一些对精度要求不高的场景下,比起占用同样字节长度的定点数,浮点数表达的数值范围可以更大一些。
- 定点数在MySQL内部是以字符串的形式进行存储的,这就决定了它一定是精准的。
- 当DECIMAL类型不知道精度和标度时,默认为DECIMAL(10,0)。当数据的精度超出了定点数类型的精度范围时,则MySQL同样会进行四舍五入处理。
位类型
类型介绍
BIT类型中存储的二进制值,类似010110。
| 二进制字符串类型 | 长度 | 长度范围 | 占用空间 |
|---|---|---|---|
| BIT(M) | M | 1<=M<=64 | 约为(M + 7)/8个字节 |
BIT类型,如果没有指定M,默认1位。表示只能存1位的二进制值。这里的M表示二进制的位数,位数最小值为1,最大值为64。插入数据时,需要注意确保插入的数据在BIT类型支持的范围内。
使用SELECT查询位字段时,可以用BIN或HEX函数进行读取。或者使用b+0查询,可以直接查询出存储的十进制数据的值。
今天先学习到这里,明天继续。