完整的数据类型介绍请参考我翻译的官方文档:第11章 数据类型。
1. 数值型类型
这里只做简要说明,详细内容请参考:11.1 数值数据类型 。
1.1. 整数类型
类型 | 声明格式 | 存储字节 | 默认显示宽度 | 描述 | 取值范围(有符号) | 取值范围(无符号) |
---|---|---|---|---|---|---|
tinyint | TINYINT[(M)] [UNSIGNED] [ZEROFILL] | 1 | tinyint(4) | 很小的整数 | -128 ~ 127 | 0 ~ 255 |
smallint | SMALLINT[(M)] [UNSIGNED] [ZEROFILL] | 2 | smallint(6) | 小的整数 | -32 768 ~ 32 767 | 0 ~ 65 535 |
mediumint | MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] | 3 | mediumint(9) | 中等大小的整数 | -8 388 608 ~ 8 388 607 | 0 ~ 16 777 215 |
int;integer | INT[(M)] [UNSIGNED] [ZEROFILL] | 4 | int(11) | 普通大小的整数 | -2 147 483 648 ~ 2 147 483 647 | 0 ~ 4 294 967 295 |
bigint | BIGINT[(M)] [UNSIGNED] [ZEROFILL] | 8 | bigint(20) | 大整数 | -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807 | 0 ~ 18 446 744 073 709 551 615 |
对于整数类型,M
表示最大显示宽度。最大显示宽度为255
。显示宽度与一个数据类型可以存储的值范围无关。如果定义列类型的时候没有指定显示宽度,则系统会为每一种类型指定默认的宽度值(见上表默认显示宽度)。
从 MySQL 8.0.17 开始,对于数值型类型,ZEROFILL
属性已被弃用,对于整数类型,显示宽度
属性也已被弃用。
可以在这些整数类型前面加上UNSIGNED
关键字,指定该列数据 >=0。同时改变该列所存储数据的范围(有符号变为无符号了)。
如果您为数值列指定了ZEROFILL
属性,MySQL 会自动添加UNSIGNED
属性。
TINYINT(1)
的同义词为BOOL
、BOOLEAN
,零值0
被认为是FALSE
。非零值1
被认为是TRUE
,值TRUE
和FALSE
分别只是1
和0
的别名。
SERIAL
是BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
的一个别名。
有符号的情况下,可以使用Java
中取值范围相同的整型(包装类型)进行数据接收,tinyint
对应Byte
,smallint
对应Short
,mediumint
没有取值范围刚好相同的,直接用Integer
接收,int
对应Integer
,bigint
对应Long
。
1.2. 定点类型
当需要保持精确的精度时使用这种类型,例如货币数据。MySQL 以二进制格式存储DECIMAL
值。
类型 | 声明格式 | 描述 | 默认值 |
---|---|---|---|
decimal; dec; numeric; fixed; | DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL] | 一个紧凑的“精确”定点数字 | decimal(10,0) |
M
为总位数(精度),D
为小数点后的位数(刻度)。小数点和-
号(对于负数)不算在M
中。如果D
为0
,则数值没有小数点和小数部分。
DECIMAL
的最大位数(M
)是65
。支持的小数(D
)的最大数目是30
。
如果省略M
,则默认值为10
。如果省略D
,则默认值为0
。DECIMAL(M)
的语法等价于DECIMAL(M,0)
。
如果您为数值列指定了ZEROFILL
属性,MySQL 会自动添加UNSIGNED
属性。
如果指定了UNSIGNED
,则禁止使用负值。从 MySQL 8.0.17 开始,DECIMAL
类型(以及任何同义词),弃用了UNSIGNED
属性;对于数值型类型,ZEROFILL
属性已被弃用。
1.3. 浮点类型
类型 | 声明格式 | 存储字节 | 描述 | 取值范围 |
---|---|---|---|---|
float | FLOAT[(M,D)] [UNSIGNED] [ZEROFILL] | 4 | 单精度浮点数值 | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 E+38) |
double; double precision; real | DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL] | 8 | 双精度浮点数值 | (-1.797 693 134 862 315 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) |
float(p ) | FLOAT(p ) [UNSIGNED] [ZEROFILL] | 精度p 为0 到24 会产生一个4 字节的单精度FLOAT 列。25 到53 的精度会产生一个8 字节的双精度DOUBLE 列 | 浮点数 | 参考上面的范围 |
M
是总位数,D
是小数点后的位数。如果省略M
和D
,值将存储在硬件允许的范围内,单精度浮点数精确到小数点后7
位左右,双精度浮点数精确到小数点后大约15
位。如果数字位数超过了该列所定义的精度或者有效位数,该数据将被四舍五入。
从 MySQL 8.0.17 开始,非标准的FLOAT(M,D)
和DOUBLE(M,D)
语法已经被弃用。对于浮点类型的列,UNSIGNED
属性已被弃用。FLOAT
和DOUBLE
列不支持AUTO_INCREMENT
。
如果指定了UNSIGNED
,则禁止使用负值。不过和整数类型的区别是并没有改变该列所存储数据的范围。
对于FLOAT
,标准 SQL 允许在关键字FLOAT
后面的圆括号中指定位的精度(但是不是位数的取值范围);也就是上表的FLOAT(p)
。
应该使用没有指定精度和刻度的FLOAT
或DOUBLE
。
如果启用了REAL_AS_FLOAT
SQL模式,REAL
就是FLOAT
的同义词,而不是DOUBLE的同义词。
可以使用Java
中取值范围相同的浮点型(包装类型)进行数据接收,float
对应Float
,double
对应Double
。
一个定义为
float(4,2)
的列将会存储四位有效数字,其中两位在小数点左边,两位在小数点右边。如果向该列中添加数据 27.44 和 8.19 是允许的,但是添加 17.8675 将会被四舍五入为 17.87, 添加 178.375 则会报错。
一个定义为float(3,1)
类型的列,向该列中添加数据 9.96 会被四舍五入为 10.0。
2. 时间型类型
这里只做简要说明,详细内容请参考:11.2 日期和时间数据类型 。
2.1. 时间格式
类型 | 描述 | 默认格式 | 取值范围 | 零值 |
---|---|---|---|---|
date | 日期 | 'YYYY-MM-DD' | '1000-01-01' ~ '9999-12-31' | '0000-00-00' |
time[(fsp)] | 一段时间 | 'hh:mm:ss[.fraction]' | '-838:59:59.000000' ~ '838:59:59.000000' | '00:00:00' |
datetime[(fsp)] | 日期和时间的组合 | 'YYYY-MM-DD hh:mm:ss[.fraction]' | '1000-01-01 00:00:00.000000' ~ '9999-12-31 23:59:59.999999' | '0000-00-00 00:00:00' |
timestamp[(fsp)] | 时间戳 | 'YYYY-MM-DD hh:mm:ss[.fraction]' | UTC'1970-01-01 00:00:00.000000' ~ UTC'2038-01-19 03:14:07.999999' | '0000-00-00 00:00:00' |
year | 年份值 | 'YYYY' | 1901 ~ 2155 | 0000 |
fsp
适用于TIME
、DATETIME
和TIMESTAMP
类型,表示以秒为单位的精度;即小数秒的小数点后的位数。如果给定fsp
值,必须在0
到6
的范围内。值为0
表示没有小数部分。如果省略,默认精度为0
。
当你指定一个 MySQL 不能表示的无效值时,“零”值可能会被使用。
在 MySQL 8.0.19 中,带有显式显示宽度的 YEAR(4) 数据类型已被弃用;并且不支持旧版本 MySQL 中允许的两位数的 YEAR(2) 数据类型。
2.2. 当前时间
可以利用内建函数直接获取系统时钟并返回当前的日期或时间字符串:
#获取当前日期时间
mysql> SELECT CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(), NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, LOCALTIMESTAMP();
+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
| CURRENT_TIMESTAMP | CURRENT_TIMESTAMP() | NOW() | LOCALTIME | LOCALTIME() | LOCALTIMESTAMP | LOCALTIMESTAMP() |
+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
| 2021-02-03 13:03:54 | 2021-02-03 13:03:54 | 2021-02-03 13:03:54 | 2021-02-03 13:03:54 | 2021-02-03 13:03:54 | 2021-02-03 13:03:54 | 2021-02-03 13:03:54 |
+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
1 row in set
#获取当前日期
mysql> SELECT CURDATE(), CURRENT_DATE(), CURRENT_DATE;
+------------+----------------+--------------+
| CURDATE() | CURRENT_DATE() | CURRENT_DATE |
+------------+----------------+--------------+
| 2021-01-28 | 2021-01-28 | 2021-01-28 |
+------------+----------------+--------------+
1 row in set
# 获取当前时间
mysql> SELECT CURTIME(), CURRENT_TIME(), CURRENT_TIME;
+-----------+----------------+--------------+
| CURTIME() | CURRENT_TIME() | CURRENT_TIME |
+-----------+----------------+--------------+
| 11:27:18 | 11:27:18 | 11:27:18 |
+-----------+----------------+--------------+
1 row in set
3. 字符型类型
这里只做简要说明,详细内容请参考:11.3 字符串数据类型 及其相关文章。
3.1. 字符类型
字符型数据可以使用定长或可变长字符串来实现。固定长度的字符串使用空格向右填充,以保证占用同样的字节数。变长字符串不需要向右填充,字节数可变。
类型 | 默认字符个数 | 最大字节数 | 描述 |
---|---|---|---|
char | char(1) | 255 | 定长字符串 |
varchar | 不指定会报错 | 65 535 | 可变长字符串 |
char(n) 和 varchar(n) 括号中 n 代表可存储的字符的个数,并不代表字节个数,如果需要存储最大长度不超过 20 个字符的字符串,可以这样定义:
char(20)
varchar(20)
建表的时候如果不指定CHAR
字段的字符个数,数据库会默认设置为CHAR(1)
,但是不指定VARCHAR
字段的字符个数的话会直接报错。报错提示如下:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
MySQL 6.0
版本以后的默认行为是严格 SQL 模式,所以如果向varchar(20)
类型的列里存储的长度超过20个字符的字符串,会抛出异常,不会存储成功。提示错误如下:
1406 - Data too long for column 'name' at row 1
早先的数据库版本中默认的是ANSI
模式,该模式下如果出现上述情况,会截断字符串并发出一个警告。会将已截断的字符串(前20个字符)存储成功。
如果希望数据库采用ANSI
方式,可以按照以下方式进行修改:
#查看数据库的当前模式,当前我的为STRICT模式
SELECT @@session.sql_mode;
#设置模式为ANSI
SET sql_mode='ansi';
现在可以测试一下存入超过限定长度的字符串,会发现存储成功了,但是存储的是被截断后的字符串,并且生成了一个警告信息。
#查看生成的警告信息
SHOW WARNINGS;
比如使用 varchar(20) 的字符列如果存汉字的话,使用 utf8 字符集,该字符集三个字节表示一个汉字字符,也就是说该字段最多能存 20 个汉字,最多会占用 60 个字节。
在所有主流数据库中,char 和 varchar 的使用方式都是类似的,注意,Oracle 数据库对 varchar 的使用是个特例,使用 varchar2 类型表示可变长字符串。
3.2. 文本类型
如果需要存储的数据超过 64KB(varchar 列所能允许的最大值),就需要使用文本类型。下面是 MySQL 的文本类型。
类型 | 最大字节数 | 描述 |
---|---|---|
tinytext | 255 | 短文本数据 |
text | 65 535 | 长文本数据 |
mediumtext | 16 777 215 | 中等长度文本数据 |
longtext | 4 294 967 295 | 极大文本数据 |
注意事项:
- 保存到文本列中的数据超出了该类型最大长度,数据会被截断。
- 向文本列保存数据的时候,不会消除数据的尾部空格。
- 当使用文本列排序或分组的时候,只会使用前 1024 个字节,当然在需要时可以放宽该限制。
- MySQL 中 varchar 最大为 65535 字节,所以不需要使用 thinytext 和 text 类型了。
- SQLServer 只提供 text 类型,DB2 和 Oracle 的文本类型为 clob。
- Oracle 中 char 列最大 2000 字节,varchar2 列最大 4000 字节,SQLServer 中 char 和 varchar 都能最大容纳 8000 字节。