首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySQL 数值类型溢出处理

MySQL 数值类型溢出处理

作者头像
Java_老男孩
发布于 2019-12-02 08:43:06
发布于 2019-12-02 08:43:06
2.4K00
代码可运行
举报
运行总次数:0
代码可运行

来,考考大家一个问题,在 MySQL 中当某一列设置为 int(0) 时会发生什么 ?

为了演示这个问题,我们先要创建一个表

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 DROP TABLE IF EXISTS `na`;
CREATE TABLE `na` (
  n1 INT(0)  NOT NULL DEFAULT '0',
  n2 INT(11) NOT NULL DEFAULT '0'
);

然后我们使用下面的语句往 na 表中插入一些数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> INSERT INTO `na` VALUES(520,520),(5201314,5201314);
Query OK, 2 rows affected (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 0

最后我们读取出来看看

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> SELECT * FROM na;
+---------+---------+
| n1      | n2      |
+---------+---------+
|     520 |     520 |
| 5201314 | 5201314 |
+---------+---------+
2 rows in set (0.00 sec)

对的,好像什么都不会发生,没什么问题才是对的,我就怕有什么问题…哈哈

我们这一章节来讲讲整型溢出问题。

MySQL 数值类型溢出处理

当 MySQL 在某个数值列上存储超出列数据类型允许范围的值时,结果取决于当时生效的 SQL 模式

  • 如果启用了严格的 SQL 模式,则 MySQL 会根据 SQL 标准拒绝带有错误的超出范围的值,并且插入失败
  • 如果没有启用任何限制模式,那么 MySQL 会将值裁剪到列数据类型范围的上下限值并存储
    1. 当超出范围的值分配给整数列时,MySQL 会存储表示列数据类型范围的相应端点的值
    2. 当为浮点或定点列分配的值超出指定(或默认)精度和比例所隐含的范围时,MySQL 会存储表示该范围的相应端点的值

这个,应该很好理解吧?

我们举一个例子,假设 t1 表的结构如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 CREATE TABLE t1 (
    i1 TINYINT,
    i2 TINYINT UNSIGNED
);

如果启用了严格的 SQL 模式,超出范围会发生一个错误

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> SET sql_mode = 'TRADITIONAL';  -- 首先设置严格模式
mysql> INSERT INTO t1 (i1, i2) VALUES(256, 256);
ERROR 1264 (22003): Out of range value for column 'i1' at row 1
mysql> SELECT * FROM t1;
Empty set (0.00 sec)

当严格模式被禁用,值可以插入,但会被裁剪,并且引发一个警告

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> SET sql_mode = '';  -- 禁用所有模式
mysql> INSERT INTO t1 (i1, i2) VALUES(256, 256);
mysql> SHOW WARNINGS;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1264 | Out of range value for column 'i1' at row 1 |
| Warning | 1264 | Out of range value for column 'i2' at row 1 |
+---------+------+---------------------------------------------+
mysql> SELECT * FROM t1;
+------+------+
| i1   | i2   |
+------+------+
|  127 |  255 |
+------+------+

如果未启用严格 SQL 模式,对于 ALTER TABLELOAD DATA INFILEUPDATE 和多行 INSERT等语句会由于裁剪而发生的列分配转换并且引发一个警告。

而如果启用了严格模式,这些语句会直接失败,并且未插入或更改部分或全部值,具体取决于表是否为事务表和其他因素。

数值表达式求值过程中的溢出会导致错误,例如,因为最大的有符号 BIGINT 值是 9223372036854775807,因此以下表达式会产生错误

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> SELECT 9223372036854775807 + 1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1)'

为了在这种情况下使操作成功,需要将值转换为 unsigned

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> SELECT CAST(9223372036854775807 AS UNSIGNED) + 1;
+-------------------------------------------+
| CAST(9223372036854775807 AS UNSIGNED) + 1 |
+-------------------------------------------+
|                       9223372036854775808 |
+-------------------------------------------+

从另一方面说,是否发生溢出取决于操作数的范围,因此处理前一个表达式的另一种方法是使用精确值算术,因为 DECIMAL 值的范围大于整数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> SELECT 9223372036854775807.0 + 1;
+---------------------------+
| 9223372036854775807.0 + 1 |
+---------------------------+
|     9223372036854775808.0 |
+---------------------------+

整数数值之间的减去,如果其中一个类型为 UNSIGNED ,默认情况下会生成无符号结果。如果为负,则会引发错误

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT CAST(0 AS UNSIGNED) - 1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'

这种情况下,如果启用了 NO_UNSIGNED_SUBTRACTION SQL 模式,则结果为负

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
|                      -1 |
+-------------------------+

如果此类操作的结果用于更新 UNSIGNED 整数列,则结果将裁剪为列类型的最大值,如果启用了 NO_UNSIGNED_SUBTRACTION 则裁剪为 0。但如果启用了严格的 SQL 模式,则会发生错误并且列保持不变。

后记

一切都是套路,套路….基本都和 SQL 模式有关…

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL 数值类型溢出处理
来,考考大家一个问题,在 MySQL 中当某一列设置为 int(0) 时会发生什么 ?
Java_老男孩
2019/09/10
1.9K0
Mysql运行模式及1690错误处理
经过查询,发现这个错误的原因是两个时间字段进行减法运算时,如果有一个时间为0000-00-00时造成的,根本原因是因为这样减法的结果会超过Mysql数值字段的范围,从而触发1690报错。
大江小浪
2018/07/24
1.2K0
MySQL文档阅读(一)-数字类型
MySQL支持很多系列的SQL数据类型:数字类型(numeric types)、日期和时间类型(date and time types)、字符串类型(字符和字节)、特殊类型和JSON数据类型。
阿杜
2018/08/06
1.5K0
MySQL文档阅读(一)-数字类型
​MySQL引发的监控问题
今天在线上发现一个问题,挺有意思的,这里简单记录下。 问题的背景是查看一个Grafana监控的时候,发现监控没有数据了:
AsiaYe
2021/07/14
1K0
​MySQL引发的监控问题
MySQL SQL模式特点汇总
MySQL服务器可以在不同的SQL模式下运行,并且可以针对不同的客户端以不同的方式应用这些模式,具体取决于sql_mode系统变量的值。DBA可以设置全局SQL模式以匹配站点服务器操作要求,并且每个应用程序可以将其会话SQL模式设置为其自己的要求。
CrazyCodes
2018/09/18
1.1K0
理解 MySQL 中的数字类型
存储字符串时指定的类型 VARCHAR(50) 中可接收一个数字作为长度,其实除了字符串类型,数字类型也是可指定该参数的,比如 INT(10),BIGINT(20)。假设后续讨论中这个参数使用字母 M 来表示,即上面提到的。该参数被用在不同类型上时,其表示的意思不一样。
星哥玩云
2022/08/18
2.3K0
HFCTF2022_babysql题目复现
虎符的一道纯SQL注入题,原来准备自己再做一遍的,结果今天题目环境给关了,都怪周一课太多了 自己太懒。
pankas
2022/08/10
4960
HFCTF2022_babysql题目复现
【数据库】MySql的sql_mode模式说明
mysql5.7+的版本中,sql_mode为严格模式。比如必须给字段默认值,更新数据的长度必须符合限制等。
参谋带个长
2023/04/28
2K0
【MySql】MySql的数据类型
对于数据类型分类,这里简单分为数值类型(如BIT,BOOL,INT),文本、二进制类型(如CHAR,VARCHAR),时间日期(DATE),String类型(如ENUM类型),这里简单了解一下即可
平凡的人1
2023/10/15
9000
【MySql】MySql的数据类型
mysql数据类型tinyint_公司的类型及区别是什么
MySQL支持多种数据类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。其中, 整数类型包括:tinyint、smallint、mediumint、int和bigint。
全栈程序员站长
2022/11/08
1.3K0
mysql数据类型tinyint_公司的类型及区别是什么
MySQL的sql_mode详解:从优雅草分发平台故障谈数据库模式配置-优雅草卓伊凡
近日,优雅草分发平台(youyacaocn)在运行过程中遭遇了一次数据库访问故障。在排查过程中,技术人员发现问题的根源在于MySQL的sql_mode设置过于严格,导致部分SQL语句执行失败。通过将sql_mode调整为宽松模式(NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION)并重启MySQL服务,问题得以解决。
卓伊凡
2025/05/12
2490
又谈mysql,面试官问表结构设计要注意啥?
排序规则(Collation)是比较和排序字符串的一种规则,每个字符集都会有默认的排序规则,可以使用命令 SHOW CHARSET 来查看:
微客鸟窝
2021/10/20
8140
MySQL案例:sql_mode详解
相信看过上一篇文章《MySQL案例:一个数据丢失惨》的童鞋,都应该意识到,sql_mode是一个非常关键的配置,接下来就带来该配置项的详细解析。
brightdeng@DBA
2020/12/12
2K0
MySQL案例:sql_mode详解
Mysql系列 - 第2天:详解mysql数据类型(重点)
上面表格中有符号和无符号写反了,[]包含的内容是可选的,默认是无符号类型的,无符号的需要在类型后面跟上unsigned
路人甲Java
2019/09/16
1.1K0
Mysql系列 - 第2天:详解mysql数据类型(重点)
MySQL系列之SQL_MODE学习笔记
SQL_MODE:MySQL特有的一个属性,用途很广,可以通过设置属性来实现某些功能支持
SmileNicky
2022/05/07
8030
MySQL系列之SQL_MODE学习笔记
MySQL数据库数据类型
在MySQL数据库中,MySQL数据类型分有四大类:数值类型、文本/二进制类型、时间日期和String类型。以下是这四大类的具体类型:
二肥是只大懒蓝猫
2023/10/13
5630
MySQL数据库数据类型
MySQL数据类型
总结: 如果插入的数据超过MySQL数据类型的范围,那么MySQL就不让你插入,直接拦截,不让做对应的操作。这点和C/C++一样,但是编译器不会报错,语言上给你发生截断,编译器内部可能会隐式转换。 如果已经有数据被成功插入到MySQL中,那么插入的时候一定是合法的。 因此,MySQL中,一般而言,数据类型本身也是一种约束。这种约束倒逼程序员,让程序员尽可能正确插入,如果不正确插入,MySQL也能保证插入的数据合法性。这样就能保证数据库中的数据是可预期完整的。
南桥
2024/07/26
3480
MySQL数据类型
MySQL sql_mode的坑及严格模式详解
mysql可以为不同的客户端设置不同的sql_mode,并且每个应用能够设置他自己的会话级别的sql_mode。sql_mode会影响sql语法以及mysql显示数据的正确性。
Petrochor
2022/06/07
3.1K0
MySQL之表的数据类型
一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考: http://www.runoob.com/mysql/mysql-data-types.html http://dev.mysql.com/doc/refman/5.7/en/data-type-overview.html mysql常用数据类型概览 #1. 数字: 整型:tinyinit int bigint 小数: float :在位数比较短的
人生不如戏
2018/04/10
5.8K0
MySQL之表的数据类型
MySQL或者MariaDB里面sql_mode的设置详解
地址:http://dev.mysql.com/doc/refman/5.6/en/sql-mode.html
保持热爱奔赴山海
2019/09/18
2.7K0
相关推荐
MySQL 数值类型溢出处理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验