数据类型官方文档: https://dev.mysql.com/doc/refman/5.6/en/data-types.html 。
基本特性
各种类型的存储大小、最大最小取值范围如下:
类型 | 存储大小(字节) | 有符号类型最小值 | 有符号类型最大值 | 无符号类型最小值 | 无符号类型最大值 |
---|---|---|---|---|---|
TINYINT |
1 | -128 |
127 |
0 |
255 |
SMALLINT |
2 | -32768 |
32767 |
0 |
65535 |
MEDIUMINT |
3 | -8388608 |
8388607 |
0 |
16777215 |
INT 、INTEGER |
4 | -2147483648 |
2147483647 |
0 |
4294967295 |
BIGINT |
8 | -263 |
2^63-1 |
0 |
2^64-1 |
int(m) 代表显示长度
为m。例如 int(1) 代表显示长度为1,但若值的长度大于1,例如为99,也会显示为 99 。
这个显示长度
, 是客户端的行为。因为是显示长度,所以不影响数值的大小。
默认值
create table test_table (
num int
) engine = InnoDB character set = utf8mb4;
查询创建语句:
mysq> show create table test_table;
+------------+-----------------------------------------+
| Table | Create Table |
+------------+-----------------------------------------+
| test_table | CREATE TABLE `test_table` ( |
| | `num` int(11) DEFAULT NULL |
| | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+------------+-----------------------------------------+
可以看到默认值是 null。
看下效果:
insert into test_table values();
insert into test_table(num) values(default);
mysql> select * from test_table;
+--------+
| num |
+--------+
| <null> |
| <null> |
+--------+
若指定列为 not null 呢?
mysql> create table test_table (num int not null) engine = InnoDB character set = utf8mb4;
mysql> show create table test_table
+------------+-----------------------------------------+
| Table | Create Table |
+------------+-----------------------------------------+
| test_table | CREATE TABLE `test_table` ( |
| | `num` int(11) NOT NULL |
| | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+------------+-----------------------------------------+
mysql> insert into test_table values();
mysql> insert into test_table(num) values(default);
mysql> select * from test_table;
+-----+
| num |
+-----+
| 0 |
| 0 |
+-----+
可以看到,用0做默认值。
默认的显示长度
create table test_table (
num int
) engine = InnoDB character set = utf8mb4;
mysq> show create table test_table;
+------------+-----------------------------------------+
| Table | Create Table |
+------------+-----------------------------------------+
| test_table | CREATE TABLE `test_table` ( |
| | `num` int(11) DEFAULT NULL |
| | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+------------+-----------------------------------------+
有符号int的默认显示长度是11,-2147483648
的长度是11,所以显示长度把负号也算上了。
如果是无符号的int呢?
create table test_table (
num int unsigned
) engine = InnoDB character set = utf8mb4;
mysql> show create table test_table;
+------------+-----------------------------------------+
| Table | Create Table |
+------------+-----------------------------------------+
| test_table | CREATE TABLE `test_table` ( |
| | `num` int(10) unsigned DEFAULT NULL |
| | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+------------+-----------------------------------------+
无符号int的默认显示长度是10,因为最小值是0,最大值4294967295
的长度是 10。
显示长度与zerofill
这个显示长度
, 是存在MySQL服务器中,当有查询操作时,会把这个属性返回给进行查询的客户端,客户端据此进行展示。有些客户端会忽略该属性。很多情况下是看不出有什么效果的,加上zerofill
后,一些客户端中会看到效果。zerofill
用来修饰数字类型(int、float等),作用是显示时若长度不够,则在前面补0。它有一个副作用,会将列类型变成 unsigned 。所以要慎用!
另外,https://dev.mysql.com/doc/refman/5.6/en/numeric-type-attributes.html 给出了显示长度和zerofill 另外两个特点:
- The ZEROFILL attribute is ignored when a column is involved in expressions or UNION queries. 含义:在表达式或者 UNION 查询时,zerofill 不会生效。
- If you store values larger than the display width in an integer column that has the ZEROFILL attribute, you may experience problems when MySQL generates temporary tables for some complicated joins. In these cases, MySQL assumes that the data values fit within the column display width. 含义:如果存储的数字大于显示长度,当因为复杂的join查询导致临时表产生,可能会出现不符合预期的结果。-》这又是一个副作用。
我们忽略zerofill 的副作用,通过示例看下效果:
创建表:
create table test_table (
num1 int(4) zerofill,
num2 int(10) zerofill
) engine = InnoDB character set = utf8mb4;
查看创建语句,会发现num1和num2变成无符号类型了。
mysql> show create table test_table;
+------------+-------------------------------------------------+
| Table | Create Table |
+------------+-------------------------------------------------+
| test_table | CREATE TABLE `test_table` ( |
| | `num1` int(4) unsigned zerofill DEFAULT NULL, |
| | `num2` int(10) unsigned zerofill DEFAULT NULL |
| | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+------------+-------------------------------------------------+
插入数据:
insert into test_table(num1, num2) values(1, 2);
insert into test_table(num1, num2) values(12345, 2);
用 MySQL 自带的命令行客户端 mysql 查询数据:
mysql> select * from test_table;
+-------+------------+
| num1 | num2 |
+-------+------------+
| 0001 | 0000000002 |
| 12345 | 0000000002 |
+-------+------------+
可以看到,长度不够的数字前面补了0。
用第三方命令行客户端 mycli 查询数据,效果不同:
mysqlt> select * from test_table;
+-------+------+
| num1 | num2 |
+-------+------+
| 1 | 2 |
| 12345 | 2 |
+-------+------+
这证明了显示长度和zerofill,不同客户端的处理方式不同。
更好的显示长度实现
首先:不要在创建表时指定显示长度,也不要使用 zerofill 关键词。为什么,因为有副作用。
那么有什么其他的方案可以达到相同的显示效果呢?
**方案1:**交给业务方。比如我们Java编写了一个web版的数据库管理系统,展示成什么样子,完全可在 Java 从数据库中取出数据后,Java 处理一下,再传给前端。例如 Java 将 1 转换成字符串 00001返回给前端。或者让前端代码将1转换成00001。
**方案2:**查询语句中用 LPAD 和 CAST 函数。
create table test_table (
num int unsigned
) engine = InnoDB character set = utf8mb4;
insert into test_table(num) values(2);
mysql> select LPAD(CAST(num AS char(10)), 10, '0') as num from test_table
+------------+
| num |
+------------+
| 0000000002 |
+------------+