「MySQL」- 数据类型

在 MySQL 中,支持众多的数据类型,主要分为以下几类:
1)数值类型(Numeric)
2)日期、时间类型(Date and Time)
3)字符串类型(String)
4)空间数据类型(Spatial Data Types)

本文描述数据类型时用到了以下约定:

  • M – 表示整数类型的最大显示宽度。对于浮点(floating-point)定点(fixed-point)类型,M 代表可以存储的总位数(精度(precision))。对于字符串类型,M 是最大长度。因此,M 允许的最大值取决于数据类型;
  • D – 用于浮点定点类型,代表小数点后面的数字位数(刻度(scale))。可能的最大值为 30,但不应大于 M-2;
  • fsp – 适用于 TIME,DATETIME 和 TIMESTAMP 类型,表示小数秒精度;也就是秒数后的小数点后的数字位数。fsp 值(如果给定)必须在 0 到 6 之间。值为 0 表示没有小数部分。如果省略,默认精度为 0。(与标准 SQL 默认值 6 不同,与以前的 MySQL 版本兼容);
  • 方括号([和])表示类型定义中的可选部分;

数值类型(Numeric Types)

概述

如上所述,M 表示整数类型的最大显示宽度。最大显示宽度为 255。显示宽度与类型的范围无关。对于浮点和定点类型,M 是可以存储的总数(即精读);

如果为数字列指定 ZEROFILL,MySQL 会自动将 UNSIGNED 属性添加到该列;

数值类型允许 UNSIGNED 和 SIGNED,这些数据类型是默认 SIGNED 的;

SERIAL 是 BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE 的别名。在整型列的定义中,SERIAL DEFAULT VALUE 是 NOT NULL AUTO_INCREMENT UNIQUE 的别名;

当整数类型做减法的时候,如果其中一个类型为 UNSIGNED,那么除非启用了 NO_UNSIGNED_SUBTRACTION SQL 模式,否则结果是无符号的;

整数类型

类型 别名 存储长度 有符号长度 无符号长度 描述
BIT(M)   M     一个位值类型。M 表示每个值的位数
TINYINT   1 字节 -128 ~ 127 0 ~ 255 数值范围较小时使用,,比如订单状态(状态值)、性别等
BOOL BOOLEAN 1 字节     等价与 TINYINT(1)。
SMALLINT   2 字节 -32768 ~ 32767 0 ~ 65535  
MEDIUMINT   3 字节 -8388608 ~ 8388607 0 ~ 16777215 相对较大的数据
INT INTEGER 4 字节 -2147483648 ~ 2147483647 0 ~ 4294967295 正常大小的整数值
BIGINT   8 字节 -9233372036854775808 ~ 9223372036854775807 0 ~ 18446744073709551615 极大整数值,比如身份证,或者手机号码
SERIAL          

关于 BIGINT 列应该注意的一些事情:

  • 所有算术运算使用带符号的 BIGINT 或 DOUBLE 值进行计算,因此除了位函数外,不应使用大于 9223372036854775807(63 位)的无符号大整数!如果这样做,结果中的最后一位数字可能会错误,因为将 BIGINT 值转换为 DOUBLE 时会出现舍入误差。MySQL 能处理以下几种情况中的 BIGINT:1)当使用整数在 BIGINT 列中存储大的无符号值时。。2)在 MIN(col_name)或 MAX(col_name)中,col_name 指的是 BIGINT 列。3)当使用操作符(+,-,*等等)时,其中两个操作数都是整数;
  • 通过使用字符串向 BIGINT 列中保存精确整数值。在这种情况下,MySQL 执行字符串到数字的隐式转换,不涉及中间双精度表示;
  • 当两个操作数都是整数值时,-,+和*运算符使用 BIGINT 算术。这意味着如果您乘以两个大整数(或返回整数的函数的结果),则当结果大于 9223372036854775807 时,可能会得到意想不到的结果;

关于 BOOLEAN 中应该注意的一些问题:

  • 在 IF()中,0 被视为 FALSE,非 0 被视为 TRUE;
  • TRUE 和 FALSE 仅仅是 1 和 0 的别名,因此其他的数值(比如:2,3,4,5 等等)即不为 1,也不为 0;

浮点数类型

FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
字节:4 字节
有符号范围:(-3.402823466 E+38 ~ -1.175494351 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)

单精度浮点数值,精确到大约 7 位小数位。用于存储小数。有符号和无符号的取值范围是基于 IEEE 标准的理论限制,实际的取值与硬件和操作系统有关系。M 是数字的总数,D 是小数点后面的位数。如果省略 M 和 D,则将值存储到硬件允许的限制;

如果指定 UNSIGNED,则不允许负值;

使用 FLOAT 可能发生一些意想不到的问题,因为 MySQL 中的所有计算都以双精度完成。详细内容可以查看Section B.5.4.7, “Solving Problems with No Matching Rows”

FLOAT(p) [UNSIGNED] [ZEROFILL]
浮点数;
p 表示精度位,但 MySQL 仅使用此值来确定是否对结果数据类型使用 FLOAT 或 DOUBLE:

  • 如果 p 从 0 到 24,数据类型变为 FLOAT,不带 M 或 D 值;
  • 如果 p 从 25 到 53,数据类型变为 DOUBLE,没有 M 或 D 值;

结果列的范围与本节描述的单精度 FLOAT 或双精度 DOUBLE 数据类型相同;

DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
字节:8 字节
有符号范围:(1.797693134862315 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)
双精度浮点数值。用于存储更大的小数,表示的范围更大。有符号和无符号的取值范围是基于 IEEE 标准的理论限制,实际的取值与硬件和操作系统有关系。M 是数字的总数,D 是小数点后面的位数。如果省略 M 和 D,则将值存储到硬件允许的限制;

M 是数字的总数(精度),D 是小数点后面的位数(刻度)。如果省略 M 和 D,则将值存储到硬件允许的限制。双精度浮点数精确到 15 位小数位;

DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL]
REAL[(M,D)] [UNSIGNED] [ZEROFILL]
这些类型是 DOUBLE 的同义词。例外:如果 SQL 模式中 REAL_AS_FLOAT 被启用,REAL 是 FLOAT 而不是 DOUBLE 的同义词;

定点类型

DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
一个包装的“精确”的定点数。M 是数字的总数(精度),D 是小数点后的数字(刻度)。小数点和符号(用于负数)不在 M 中计数。如果 D 为 0,则值不具有小数点或小数部分。DECIMAL 的最大位数(M)为 65.支持的小数(D)的最大数量为 30.如果省略 D,默认值为 0.如果省略 M,默认值为 10;

如果指定 UNSIGNED,则不允许负值;

使用 DECIMAL 列的所有基本计算(+,-,*,/)的精度为 65 位数;

DEC[(M[,D])] [UNSIGNED] [ZEROFILL]
NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL]
FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]
与 DECIMAL 是同义的。FIXED 用于与其他数据库兼容;

日期、时间类型(Date and Time)

对空间数据的扩展(Extensions for Spatial Data)

JSON 数据类型(The JSON Data Type)

从 MySQL 5.7.8 开始,表的列也支持 JSON 数据类型;

JSON 类型的列不能被索引。可以通过从 JSON 列中提取的标量值,生成新列,在新列上创建索引来处理此限制

数据类型选择上的建议

更小的数据类型

简单的数据类型

减少 NULL 的使用

参考文献

MySQL 5.7 Reference Manual / Data Types:https://dev.mysql.com/doc/refman/5.7/en/data-types.html
https://dev.mysql.com/doc/refman/5.7/en/spatial-extensions.html
https://dev.mysql.com/doc/refman/5.7/en/json.html