数值类型
整数类型
MySQL提供了5种整数类型,它们分别占用1~8字节。同编程语言类似,它们也有无符号类型,需要用 UNSIGNED
关键字修饰。
类型 | 字节 | 范围(有符号) | 范围(无符号) |
---|---|---|---|
TINYINT | |||
SMALLINT | |||
MEDIUMINT | |||
INT | |||
BIGINT |
TINYINT
类似于编程语言的 char
,占一个字节,表示范围为 到 ;SMALLINT
占两个字节,类似于 short
,INT
和普通的 int
相同,都是四个字节;BIGINT
类似于 long long
,是一个八字节的长整数类型。
范围限制
MySQL
在数据类型上有严格的范围限制,不同于编程语言的截断操作,MySQL
不允许超过范围的数据插入到表中。
ZEROFILL
MySQL
在设置列为整数类型时,类型之后可以加上 (n)
,比如 INT(10)
。
值得注意的是,加上 ()
之后,并不会对这些类型的底层存储有任何影响,比如 INT
、INT(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
专门提供了关键字 BOOL
和 BOOLEAN
作为 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++的 float
和 double
一样,遵循IEEE 754标准。
类型 | 字节 | 范围 |
---|---|---|
FLOAT | 位十进制有效数字 | |
DOUBLE | 位十进制有效数字 |
在使用 FLOAT
或 DOUBLE
类型时,除了直接使用类型名外,还可以指定存储的位数。
FLOAT(m,n)
类型用于指定浮点数最多可存储的位数和小数位。其中 m
为最多可存储的数字位数,n
为最多可存储的小数部分位数。
比如类型 FLOAT(5,3)
,它表示最多存储 个数位(十进制),其中小数部分最多为 位,所以整数部分最多为 位。即可存储的小数范围为 ~ ,精度最小为 。
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
。
定点数类型
同编程语言一样,FLOAT
和 DOUBLE
也是将小数位转为二进制存储,所以对于高精度的小数,也会发生精度丢失的问题。
为了解决浮点数精度丢失的问题,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的缺点
存储占用更大:由于每个数字都以字符串形式,并且具有固定的精度,因此它在存储空间上比较消耗资源。与
FLOAT
或DOUBLE
类型相比,它需要更多的存储空间来表示相同的值。计算效率更低:由于
DECIMAL
类型的计算是基于字符串的,而不是二进制,因此在进行算术运算时,它的计算效率可能会降低。对于大规模的计算或复杂的查询,使用DECIMAL
类型可能会导致性能下降。