MySQL 学习笔记

MySQL是一个开源的关系型数据库,非常流行。

如无特殊说明,本专题文章的 SQL 均在 5.6 版本中验证。

👉文章列表
MySQL 学习笔记 ⏬ 创建和删除数据库 切换和查看数据库 创建和删除表 在表中增加、删除、修改列 添加和删除索引 增删查改 创建和删除主键 大小写和反引号 字符串类型值的大小写 SQL注释 CHAR类型 VARCHAR类型 整型数字 时间戳 不要使用utf8 唯一索引与NULL 唯一索引的单列长度限制 NULL的判等 DDL、DML、DCL的含义 查看表的状态 show table status InnoDB存储引擎的限制 if和case的使用 自定义函数 InnoDB 索引 事务 事务隔离级别的概念、查看和修改 读已提交(read committed)隔离级别下的锁 可重复读(repeatable read)隔离级别下的锁 修改自增主键id的类型 使用 load data 快速导入数据 使用 select into outfile 导出数据

MySQL: 整型数字


数据类型官方文档: 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
INTINTEGER 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 另外两个特点: 1. The ZEROFILL attribute is ignored when a column is involved in expressions or UNION queries. 含义:在表达式或者 UNION 查询时,zerofill 不会生效。 2. 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 |
+------------+

( 本文完 )

文章目录