跳至主要內容

数值类型

AkashiNeko原创MySQL数据类型

整数类型

MySQL提供了5种整数类型,它们分别占用1~8字节。同编程语言类似,它们也有无符号类型,需要用 UNSIGNED 关键字修饰。

类型字节范围(有符号)范围(无符号)
TINYINT11[27,271][-2^{7}, 2^{7}-1][0,281][0, 2^{8}-1]
SMALLINT22[215,2151][-2^{15}, 2^{15}-1][0,2161][0, 2^{16}-1]
MEDIUMINT33[223,2231][-2^{23}, 2^{23}-1][0,2241][0, 2^{24}-1]
INT44[231,2311][-2^{31}, 2^{31}-1][0,2321][0, 2^{32}-1]
BIGINT88[263,2631][-2^{63}, 2^{63}-1][0,2641][0, 2^{64}-1]

TINYINT 类似于编程语言的 char,占一个字节,表示范围为 127-127128128SMALLINT 占两个字节,类似于 shortINT 和普通的 int 相同,都是四个字节;BIGINT 类似于 long long,是一个八字节的长整数类型。

范围限制

MySQL 在数据类型上有严格的范围限制,不同于编程语言的截断操作,MySQL 不允许超过范围的数据插入到表中。

ZEROFILL

MySQL 在设置列为整数类型时,类型之后可以加上 (n),比如 INT(10)

值得注意的是,加上 () 之后,并不会对这些类型的底层存储有任何影响,比如 INTINT(1)INT(10) 类型,它们在底层仍是四字节的空间,表示的范围也相同。它只会影响某些客户端的显示效果,比如下面例子。

CREATE TABLE num (
    n int,
    n10 int(10) ZEROFILL
);
INSERT INTO num VALUES (123,123);


 


设置 ZEROFILL 后的显示效果。

SELECT * FROM num;
+------+------------+
| n    | n10        |
+------+------------+
|  123 | 0000000123 |
+------+------------+

布尔类型

MySQL 没有提供专门的布尔类型,但是可以使用 TINYINT(1) 当作布尔类型。MySQL 专门提供了关键字 BOOLBOOLEAN 作为 TINYINT(1) 的别名。

CREATE TABLE bool_test ( val bool );
DESC bool_test;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| val   | tinyint(1) | YES  |     | NULL    |       |
+-------+------------+------+-----+---------+-------+

可以发现,BOOL 类型的本质其实是 TINYINT(1)

浮点数类型

与编程语言相同,MySQL 提供了四字节的单精度浮点数类型 FLOAT 和八字节的双精度浮点数类型 DOUBLE。与C/C++的 floatdouble 一样,遵循IEEE 754open in new window标准。

类型字节范围
FLOAT4477 位十进制有效数字
DOUBLE881515 位十进制有效数字

在使用 FLOATDOUBLE 类型时,除了直接使用类型名外,还可以指定存储的位数。

FLOAT(m,n) 类型用于指定浮点数最多可存储的位数和小数位。其中 m 为最多可存储的数字位数,n 为最多可存储的小数部分位数。

比如类型 FLOAT(5,3),它表示最多存储 55 个数位(十进制),其中小数部分最多为 33 位,所以整数部分最多为 53=25-3=2 位。即可存储的小数范围为 00 ~ 99.99999.999,精度最小为 0.0010.001

CREATE TABLE num ( val float(5,3) );
INSERT INTO num VALUES (12.345);
INSERT INTO num VALUES (0.001);
INSERT INTO num VALUES (99.999);
INSERT INTO num VALUES (100.000);
-- ERROR 1264 (22003): Out of range value for column 'val' at row 1
INSERT INTO num VALUES (12.3456789);




 
 

SELECT * FROM num;
+--------+
| val    |
+--------+
| 12.345 |
|  0.001 |
| 99.999 |
| 12.346 |
+--------+

如果输入了更高精度的小数,MySQL 会自动对数据进行四舍五入。比如上面的 12.3456789 被储存为 12.346

定点数类型

同编程语言一样,FLOATDOUBLE 也是将小数位转为二进制存储,所以对于高精度的小数,也会发生精度丢失的问题。

为了解决浮点数精度丢失的问题,MySQL 提供了更精确的定点数类型 DECIMAL,我们可以进行如下对比。

CREATE TABLE float_and_decimal (
    float_val float(10,8),
    decimal_val decimal(10,8)
);
INSERT INTO float_and_decimal VALUES (10.23456789,10.23456789);
SELECT * FROM float_and_decimal;




 

+-------------+-------------+
| float_val   | decimal_val |
+-------------+-------------+
| 10.23456764 | 10.23456789 |
+-------------+-------------+

可以看到,对于高精度的小数,FLOAT 在存储时发生了精度丢失,而 DECIMAL 没有问题。

FLOAT 类型不同,DECIMAL 类型使用一种固定的精度存储和表示小数值,这意味着它不会发生舍入误差。它以字符串形式存储小数值,并且每个数字都以固定的精度进行存储,而不依赖于二进制表示。

由于 DECIMAL 存储和表示的精度是固定的,它适合于需要精确计算和存储货币金额、精确度要求高的金融数据或进行精确计算的应用程序。然而 DECIMAL 类型也有一些缺点:

DECIMAL的缺点

  • 存储占用更大:由于每个数字都以字符串形式,并且具有固定的精度,因此它在存储空间上比较消耗资源。与 FLOATDOUBLE 类型相比,它需要更多的存储空间来表示相同的值。

  • 计算效率更低:由于 DECIMAL 类型的计算是基于字符串的,而不是二进制,因此在进行算术运算时,它的计算效率可能会降低。对于大规模的计算或复杂的查询,使用 DECIMAL 类型可能会导致性能下降。