MySQL中的数据类型主要有:数字类型、日期/时间类型、字符串类型。

数字类型

下面的M在不同的数据类型后面的含义是不同的!!!在表示int(或integer)类型时表示的是显示宽度(display width),最大显示宽度是255。显示宽度和数字类型的取值范围是无关的。例如,int(11)表示的是显示宽度是11,int(10)表示的是显示宽度是10,它们都是整型,整型占用的空间是固定的4个字节
下面的方括号[]表示其中的内容可选,即定义字段的时候可以加上,也可以不加。

  • bit[( M)]
    比特类型,M表示每个数字占用的比特数,M可以从1到64,不指定时默认1。
mysql> create table t_bit(id_1 bit,id_2 bit(2),id_3 bit(3));
Query OK, 0 rows affected (0.02 sec)
#4超出了2bit表示范围,报错
mysql> insert into t_bit(id_1,id_2,id_3)values(1,4,7);
ERROR 1406 (22001): Data too long for column 'id_2' at row 1
mysql> insert into t_bit(id_1,id_2,id_3)values(1,3,7);
Query OK, 1 row affected (0.00 sec)
#8超出了3bit表示范围,报错
mysql> insert into t_bit(id_1,id_2,id_3)values(1,3,8);
ERROR 1406 (22001): Data too long for column 'id_3' at row 1

从上面的可以看到id_2是2比特空间,能表示0~3,id_3是3比特空间,能表示0~7,如果超出存储范围会报错。

  • tinyint[(M)] [unsigned] [zerofill]
    表示很小的整数,占用1个字节存储空间,有符号的取值范围是-128~127,无符号表示的范围是0~255,默认字段是有符号类型,即signedM表示的是显示宽度,不指定的时候默认为4,貌似显示宽度只有在有0填充的时候有用。
mysql> create table t_tinyint(id_1 tinyint,id_2 tinyint(2),id_3 tinyint(2) zerofill,id_4 tinyint(10));
Query OK, 0 rows affected (0.01 sec)
#查看了一下表的描述,可以发现定义字段时指定了zerofill,字段就变成了unsigned类型了。
mysql> desc t_tinyint;
+-------+------------------------------+------+-----+---------+-------+
| Field | Type                         | Null | Key | Default | Extra |
+-------+------------------------------+------+-----+---------+-------+
| id_1  | tinyint(4)                   | YES  |     | NULL    |       |
| id_2  | tinyint(2)                   | YES  |     | NULL    |       |
| id_3  | tinyint(2) unsigned zerofill | YES  |     | NULL    |       |
| id_4  | tinyint(10)                  | YES  |     | NULL    |       |
+-------+------------------------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

#因为定义id_4的时候没有指名是否有符号,默认有符号,250超出了有符号表示的上限128,所以报错了。
mysql> insert into t_tinyint(id_1,id_2,id_3,id_4)
    -> values(2,3,1,250);
ERROR 1264 (22003): Out of range value for column 'id_4' at row 1

mysql> insert into t_tinyint(id_1,id_2,id_3,id_4) values(2,3,1,127);
Query OK, 1 row affected (0.00 sec)

#查询的结果可以看到定义id_3的时候指定了填充0,而显示宽度是2,所以左边的1位被填了0,尽管定义id_4的时候指定了显示宽度是10,
mysql> select * from t_tinyint;
+------+------+------+------+
| id_1 | id_2 | id_3 | id_4 |
+------+------+------+------+
|    2 |    3 |   01 |  127 |
+------+------+------+------+
1 row in set (0.00 sec)

#把id_4字段改成显示宽度为9,zerofill
mysql> alter table t_tinyint change id_4 id_4 int(9) zerofill;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

#此时再查询表,发现id_4字段宽度被0填充到9位了。
mysql> select * from t_tinyint;
+------+------+------+-----------+
| id_1 | id_2 | id_3 | id_4      |
+------+------+------+-----------+
|    2 |    3 |   01 | 000000127 |
+------+------+------+-----------+
1 row in set (0.00 sec)

mysql> insert into t_tinyint(id_2,id_3)values(120,121);
Query OK, 1 row affected (0.00 sec)

#注意,当数字大小超出了显示宽度时会显示完整的数字,不再受显示宽度束缚,例如下面的id_2,id_3字段在定义时的显示宽度都指定为2位宽度,但是插入的数据已经有3位宽度了,显示的时候并没有受显示宽度束缚。
mysql> select * from t_tinyint;
+------+------+------+-----------+
| id_1 | id_2 | id_3 | id_4      |
+------+------+------+-----------+
|    2 |    3 |   01 | 000000127 |
| NULL |  120 |  121 |      NULL |
+------+------+------+-----------+
2 rows in set (0.00 sec)
  • bool,boolean
    这些类型是tinyint(1)的同义词。0值被认为是false,非0值被认为是true。

如下内容可以看到0是false,非0的都是true:

mysql> select if(0,'true','false');
+----------------------+
| if(0,'true','false') |
+----------------------+
| false                |
+----------------------+
1 row in set (0.00 sec)

mysql> select if(1,'true','false');
+----------------------+
| if(1,'true','false') |
+----------------------+
| true                 |
+----------------------+
1 row in set (0.00 sec)

mysql> select if(2,'true','false');
+----------------------+
| if(2,'true','false') |
+----------------------+
| true                 |
+----------------------+
1 row in set (0.00 sec)

然而,反过来就不一样了。true仅表示1,false仅表示0

mysql> select if(0=false,'true','false');
+----------------------------+
| if(0=false,'true','false') |
+----------------------------+
| true                       |
+----------------------------+
1 row in set (0.01 sec)

mysql> select if(1=true,'true','false');
+---------------------------+
| if(1=true,'true','false') |
+---------------------------+
| true                      |
+---------------------------+
1 row in set (0.01 sec)

mysql> select if(2=true,'true','false');
+---------------------------+
| if(2=true,'true','false') |
+---------------------------+
| false                     |
+---------------------------+
1 row in set (0.00 sec)

让我们来看如下内容:

mysql> create table t_bool(b1 bool,b2 boolean);
Query OK, 0 rows affected (0.02 sec)
#可以看到定义字段的时候bool,boolean都是tinyint(1)的别名。
mysql> desc t_bool;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| b1    | tinyint(1) | YES  |     | NULL    |       |
| b2    | tinyint(1) | YES  |     | NULL    |       |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

#既然是tinyint(1)就可以插入-128~127范围内的整数
mysql> insert into t_bool values(0,1);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_bool;
+------+------+
| b1   | b2   |
+------+------+
|    0 |    1 |
+------+------+
1 row in set (0.00 sec)

mysql> insert into t_bool values(1,2);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_bool;
+------+------+
| b1   | b2   |
+------+------+
|    0 |    1 |
|    1 |    2 |
+------+------+
2 rows in set (0.00 sec)

#插入的时候true被转为数字1,false被转为数字0。
mysql> insert into t_bool values(true,false);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_bool;
+------+------+
| b1   | b2   |
+------+------+
|    0 |    1 |
|    1 |    2 |
|    1 |    0 |
+------+------+
3 rows in set (0.00 sec)

mysql> insert into t_bool values(-1,120);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_bool;
+------+------+
| b1   | b2   |
+------+------+
|    0 |    1 |
|    1 |    2 |
|    1 |    0 |
|   -1 |  120 |
+------+------+
4 rows in set (0.00 sec)
  • smallint[(M)] [unsigned] [zerofill]
    M含义和tinyint一样,都是表示显示宽度,不同的是smallint存储的时候占用2个字节,有符号表示范围为-32768~32767,无符号表示范围为0~65535。
  • mediumint[(M)] [unsigned] [zerofill]
    M含义和tinyint一样,都是表示显示宽度,不同的是mediumint存储的时候占用3个字节,有符号表示范围为-8388608~8388607,无符号表示范围为0~16777215。
  • int[(M)] [unsigned] [zerofill]
    M含义和tinyint一样,都是表示显示宽度,不同的是int存储的时候占用4个字节,有符号表示范围为-2147483648~2147483647,无符号表示范围为0~4294967295。
  • integer[(M)] [unsigned] [zerofill]
    是int的别名,含义一样。
  • bigint[(M)] [unsigned] [zerofill]
    很大的整数,有符号范围为 -9223372036854775808~9223372036854775807。无符号范围为0~18446744073709551615。
    serial是bigint unsigned not null auto_increment unique的别名:
mysql> create table t_serial(id serial);
Query OK, 0 rows affected (0.01 sec)

mysql> desc t_serial;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
+-------+---------------------+------+-----+---------+----------------+
1 row in set (0.00 sec)
  • decimal[(M[,D])] [unsigned] [zerofill]
    压缩的严格定点数。M表示总共的位数,也就是精度,D是小数点后的位数,也叫做标度。对于负数中的负号-不算在M内。如果D为0,则没有小数部分。decimal最大的位数(M)为65,如果省略M的值,则默认为10;最大的D是30,如果省略D的值,则默认为0。decimal类型占用的空间是M+2个字节。在MySQL中,定点数以字符串的形式存储,在对精度要求比较高的时候(比如金融相关的)推荐使用decimal。
#可以看出decimal的最大精度超过65就报错了
mysql> create table t_decimal(d1 decimal(65,30),d2 decimal,d3 decimal(70));
ERROR 1426 (42000): Too-big precision 70 specified for 'd3'. Maximum is 65.
mysql> create table t_decimal(d1 decimal(65,30),d2 decimal,d3 decimal(10));
Query OK, 0 rows affected (0.02 sec)

mysql> desc t_decimal;
+-------+----------------+------+-----+---------+-------+
| Field | Type           | Null | Key | Default | Extra |
+-------+----------------+------+-----+---------+-------+
| d1    | decimal(65,30) | YES  |     | NULL    |       |
| d2    | decimal(10,0)  | YES  |     | NULL    |       |
| d3    | decimal(10,0)  | YES  |     | NULL    |       |
+-------+----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> alter table t_decimal change d3 d3 decimal(5,2);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc t_decimal;
+-------+----------------+------+-----+---------+-------+
| Field | Type           | Null | Key | Default | Extra |
+-------+----------------+------+-----+---------+-------+
| d1    | decimal(65,30) | YES  |     | NULL    |       |
| d2    | decimal(10,0)  | YES  |     | NULL    |       |
| d3    | decimal(5,2)   | YES  |     | NULL    |       |
+-------+----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

#d3的位数超出了5位,报错了
mysql> insert into t_decimal(d1,d2,d3)values(222222222222222.44444444,3432.34,2223.45);
ERROR 1264 (22003): Out of range value for column 'd3' at row 1
mysql> mysql> insert into t_decimal(d1,d2,d3)values(222222222222222.44444444,3432.34,233.45);
Query OK, 1 row affected, 1 warning (0.01 sec)

#可以看到d1的小数部分精度不足的被0填充
mysql> select * from t_decimal;
+------------------------------------------------+------+--------+
| d1                                             | d2   | d3     |
+------------------------------------------------+------+--------+
| 222222222222222.444444440000000000000000000000 | 3432 | 223.45 |
+------------------------------------------------+------+--------+
1 row in set (0.00 sec)

mysql> insert into t_decimal(d1,d2,d3)values(222222222222222.44444444,3432.34,23.454);
Query OK, 1 row affected, 2 warnings (0.01 sec)

#上面插入的d3值的小数部分被截掉了,因为d3定义的时候小数部分是2位
mysql> select * from t_decimal;
+------------------------------------------------+------+--------+
| d1                                             | d2   | d3     |
+------------------------------------------------+------+--------+
| 222222222222222.444444440000000000000000000000 | 3432 | 223.45 |
| 222222222222222.444444440000000000000000000000 | 3432 |  23.45 |
+------------------------------------------------+------+--------+
2 rows in set (0.00 sec)
  • dec [(M[,D])] [unsigned] [zerofill], numeric[(M[,D])] [unsigned] [zerofill], fixed[(M[,D])] [usigned] [zerofill]
    上面这几种都是decimal的同义词,其中fixed(有定点的意思)和其他数据库系统的命名兼容。
  • float [(M,D)] [unsigned] [zerofill]
    小一点的(单精度)浮点数,占用4个字节。可以取值的范围是-3.402823466E+38~-1.175494351E-38, 0, 和1.175494351E-38~3.402823466E+38,如果定义unsigned,就不能取负值。这是基于IEEE标准的理论上的限制,真实的范围会小一些,并且取决与硬件和操作系统。
    M是总共的位数,D是小数点后的位数。如果MD被省略了,将按照硬件允许的范围存储。单精度浮点数可以精确到大约7位小数。
    使用float可能会有意想不到的问题,因为MySQL中所有的计算都是基于双精度的。
  • double [(M,D)] [unsigned] [zerofill]
    正常大小的(双精度)浮点数。可以取值的范围是-1.7976931348623157E+308~-2.2250738585072014E-308, 0, 和2.2250738585072014E-308~1.7976931348623157E+308,如果定义unsigned,就不能取负值。同样是理论值,真实范围会小一些,并且取决于硬件和操作系统。
    MD的含义同float,双精度浮点数可以精确到大约15位小数。

参考网址:https://dev.mysql.com/doc/refman/8.0/en/numeric-type-overview.html