mysql学习笔记(三):unsigned理解以及特殊情况
UNSIGNED
UNSIGNED属性就是将数字类型无符号化,与C、C++这些程序语言中的unsigned含义相同。例如,INT的类型范围是-2 147 483 648 ~ 2 147 483 647, INT UNSIGNED的范围类型就是0 ~ 4 294 967 295。
看起来这是一个不错的属性选项,特别是对于主键是自增长的类型,因为一般来说,用户都希望主键是非负数。然而在实际使用中,UNSIGNED可能会带来一些负面的影响,示例如下:
ENGINE=INNODB;
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO t SELECT 1,2;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM t\G;
*************************** 1. row ***************************
a: 1
b: 2
1 row in set (0.00 sec)
我们创建了一个表t,存储引擎为InnoDB。表t上有两个UNSIGNED的INT类型。输入(1,2)这一行数据,目前看来都没有问题,接着运行如下语句:
这时结果会是什么呢?会是-1吗?答案是不确定的,可以是-1,也可以是一个很大的正值,还可能会报错。在Mac操作系统中,MySQL数据库提示如下错误:
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`test`.`t`.`a` - `test`.`t`.`b`)'
这个错误乍看起来非常奇怪,提示BIGINT UNSIGNED超出了范围,但是我们采用的类型都是INT UNSIGNED啊!而在另一台Linux操作系统中,运行的结果却是:
*************************** 1. row ***************************
a - b: 4294967295
1 row in set (0.00 sec)
在发生上述这个问题的时候,有开发人员跑来和笔者说,他发现了一个MySQL的Bug,MySQL怎么会这么“傻”呢?在听完他的叙述之后,我写了如下的代码并告诉他,这不是MySQL的Bug,C语言同样也会这么“傻”。
int main(){
unsigned int a;
unsigned int b;
a = 1;
b = 2;
printf(a - b: %d\n,a-b);
printf(a - b: %u\n,a-b);
return 1;
}
上述代码的运行结果是:
a - b: 4294967295
可以看到,在C语言中a-b也可以返回一个非常巨大的整型数,这个值是INT UNSIGNED的最大值。难道C语言也发生了Bug?这怎么可能呢?
在实际的使用过程中,MySQL给开发人员的印象就是存在很多Bug,只要结果出乎预料或者有开发人员不能理解的情况发生时,他们往往把这归咎于MySQL的 Bug。和其他数据库一样,MySQL的确存在一些Bug,其实并不是MySQL数据库的Bug比较多,去看一下Oracle RAC的Bug,那可能就更多了,它可是Oracle的一款旗舰产品。因此,不能简单地认为这个问题是MySQL的Bug。
对于上述这个问题,正如上述所分析的,如果理解整型数在数据库中的表示方法,那么这些就非常好理解了,这也是为什么之前强调需要看一些计算机组成原理方面相关书籍的原因。将上面的C程序做一些修改:
int main(){
unsigned int a;
unsigned int b;
a = 1;
b = 2;
printf(a - b: %d,%x\n,a-b,a-b);
printf(a - b: %u,%x\n,a-b,a-b);
return 1;
}
这次不仅打印出a-b的结果,也打印出a-b的十六进制结果,运行程序后的结果如下所示:
a - b: 4294967295,ffffffff
可以看到结果都是0xFFFFFFFF,只是0xFFFFFFFF可以代表两种值:对于无符号的整型值,其是整型数的最大值,即4 294 967 295;对于有符号的整型数来说,第一位代表符号位,如果是1,表示是负数,这时应该是取反加1得到负数值,即-1。
这个问题的核心是,在MySQL数据库中,对于UNSIGNED数的操作,其返回值都是UNSIGNED的。而正负数这个问题在《MySQL技术内幕:InnoDB存储引擎》中有更深入的分析,有兴趣的可以进一步研究。
那么,怎么获得-1这个值呢?这并不是一件难事,只要对SQL_MODE这个参数进行设置即可,例如:
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT a-b FROM t\G;
*************************** 1. row ***************************
a-b: -1
1 row in set (0.00 sec)
后面会对SQL_MODE进一步讨论,这里不进行深入的讨论。笔者个人的看法是尽量不要使用UNSIGNED,因为可能会带来一些意想不到的效果。另外,对于INT类型可能存放不了的数据,INT UNSIGNED同样可能存放不了,与其如此,还不如在数据库设计阶段将INT类型提升为BIGINT类型
本人遇到的类似问题:(linux上)
当(a-b)在where子句后时也会出现相同的情况
以下是php使用Mysql查询的结果(每组的第一行是第二行[1]-[2]的结果)
86374
a b
Array ( [1] => 1351843032 [2] => 1351756658 )
-2567
Array ( [1] => 1351843032 [2] => 1351845599 )
86374
Array ([1] => 1351843032 [2] => 1351756658 )
86374
Array ( [1] => 1351843032 [2] => 1351756658 )
-105849
Array ( [1] => 1351650809 [2] => 1351756658 )
86374
Array ( [1] => 1351843032 [2] => 1351756658 )
86374
Array ( [1] => 1351843032 [2] => 1351756658 )
下面在mysql语句中查询select * from table where (a-b)>86374;
结果(按正常思路来讲,结果应该为空,但在Linux是却现出以下结果 ):
Array ( [1] => 1351843032 [2] => 1351845599 )
Array ( [1] => 1351650809 [2] => 1351756658 )
而这个结果恰是[1]-[2]为负数的那两行。
结论:如果使用unsigne并且在where子句后出现两列相减值小于0((a-b)<0),在查询时,linux上的Mysql会将负数转换成unsigned后再进行查询( (-2576+4294967295+1)>86374, (-105849+4294967295+1)>86374 )。
mysql学习笔记(三):unsigned理解以及特殊情况的更多相关文章
- MYSQL学习笔记三:日期和时间函数
MYSQL学习笔记三:日期和时间函数 1. 获取当前日期的函数和获取当前时间的函数 /*获取当前日期的函数和获取当前时间的函数.将日期以'YYYY-MM-DD'或者'YYYYMMDD'格式返回 */ ...
- MySql学习笔记三
MySql学习笔记三 4.DML(数据操作语言) 插入:insert 修改:update 删除:delete 4.1.插入语句 语法: insert into 表名 (列名1,列名2,...) val ...
- mysql基本数据类型(mysql学习笔记三)
Mysql数据类型 小数: 浮点:小数位可以变化 Float单精度默认精度6位左右 Double 双精度默认精度16位左右 支持,控制数值范围 Type(M,D) M表示所有数值位数(不包括小数点和符 ...
- MySQL学习笔记(三)—索引
一.概述 1.基本概念 在大型数据库中,一张表中要容纳几万.几十万,甚至几百万的的数据,而当这些表与其他表连接后,所得到的新的数据数目更是要大大超出原来的表.当用户检索这么大量的数据时,经 ...
- mysql学习笔记三 —— 数据恢复与备份
要点: 1.存储引擎2.导入导出3.备份与恢复 查看当前数据库中的所有表use db1:show tables: 1.存储引擎 不同的发动机(引擎)适用的汽车类型不一样. 存储和处理的不同方式.不同的 ...
- MySQL学习笔记三:库和表的管理
1.MySQL数据库服务配置好后,系统会有4个默认的数据库. information_schema:虚拟对象,其对象都保存在内存中 performance_schema:服务器性能指标库 mysql: ...
- MySQL学习笔记(三):常用函数
一:字符串函数 需要注意的几个细节: 1.cancat中有一个字符串为null,则结果为null. 2.left(str,x) 和 right(str,x)中x为null,则不返回任何字符串,不是nu ...
- Java多线程高并发学习笔记(三)——深入理解线程池
线程池最核心的一个类:ThreadPoolExecutor. 看一下该类的构造器: public ThreadPoolExecutor(int paramInt1, int paramInt2, lo ...
- mysql学习笔记(三)
-- 主键冲突(duplicate key) ,'xujian','anhui'); ,'xiewei','anhui'); ,'luyang','anhui');-- 主键冲突了 -- 可以选择性的 ...
- ROS学习笔记三(理解ROS节点)
要求已经在Linux系统中安装一个学习用的ros软件包例子: sudo apt-get install ros-indigo-ros-tutorials ROS图形概念概述 nodes:节点,一个节点 ...
随机推荐
- mysql查询速度慢的分析和解决
一.定位执行慢的sql,如2秒内没执行完的抽取出来 show engines;查看慢查询时间show variables like 'slow%';查看设置多久是慢查询show variables l ...
- mysql数据库函数之left()、right()、substring()、substring_index()
在实际的项目开发中有时会有对数据库某字段截取部分的需求,这种场景有时直接通过数据库操作来实现比通过代码实现要更方便快捷些,mysql有很多字符串函数可以用来处理这些需求,如Mysql字符串截取总结:l ...
- C++-POJ1018-Communication System
贪心算法:先排序,再枚举最小带宽(B),每次更新当前最小花费(P)和以及答案(ans) #include <cstdio> #include <algorithm> using ...
- 命令行(一):Git
1,使用gitbash进行操作 2,初始化一个Git仓库,使用git init命令. 3,添加文件到Git仓库,分两步:使用命令git add <filename>可反复多次使用,添加多个 ...
- 【visio】数据流图
率属于 软件和数据库 又名 Gane-Sarson图,数据流图示描述系统数据流程关系的工具,它可以综合的反映出数据在系统中的来源.流动.处理和存储情况,可以将数据流形象具体的表现出来. 在大型项目中, ...
- Spring-Aop编程(三)-AspectJ
AspectJ 1. 介绍 AspectJ是一个基于Java语言的AOP框架,Spring2.0以后新增了对AspectJ切点表达式支持,@AspectJ 是AspectJ1.5新增功能,通过JDK5 ...
- VIM - ex 命令行的窗口切换
1. 概述 操作 vim 同时编辑多个文件 约定 ctrl 使用按键 ctrl + w 时, 写作 ^W 思路 我记得这个由两个机制 ex 命令与缓冲区 分屏 2. 场景 文件 file1 file2 ...
- CSS学习(4)常见样式声明
1.文本 color 文字颜色 预设值:定义好的单词,如red blue 光学的三原色(红,绿,蓝),如 rgb(32,45,255) HEX十六进制,如#008CFF(#112233可以简写为#12 ...
- KFC 小猪短租
# 分析肯德基门店信息 import requests,json post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op= ...
- GITlab安装、使用及新项目推送到gitlab
==================================================================================================== ...