UNSIGNED

  UNSIGNED属性就是将数字类型无符号化,与C、C++这些程序语言中的unsigned含义相同。例如,INT的类型范围是-2 147 483 648 ~ 2 147 483 647, INT UNSIGNED的范围类型就是0 ~ 4 294 967 295。

  看起来这是一个不错的属性选项,特别是对于主键是自增长的类型,因为一般来说,用户都希望主键是非负数。然而在实际使用中,UNSIGNED可能会带来一些负面的影响,示例如下:

  mysql> CREATE TABLE t ( a INT UNSIGNED, b INT 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)这一行数据,目前看来都没有问题,接着运行如下语句:

  SELECT a - b FROM t

  这时结果会是什么呢?会是-1吗?答案是不确定的,可以是-1,也可以是一个很大的正值,还可能会报错。在Mac操作系统中,MySQL数据库提示如下错误:

  mysql> SELECT a-b FROM t;

  ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`test`.`t`.`a` - `test`.`t`.`b`)'

  这个错误乍看起来非常奇怪,提示BIGINT UNSIGNED超出了范围,但是我们采用的类型都是INT UNSIGNED啊!而在另一台Linux操作系统中,运行的结果却是:

  mysql> SELECT a -b FROM t\G;

  *************************** 1. row ***************************

  a - b: 4294967295

  1 row in set (0.00 sec)

  在发生上述这个问题的时候,有开发人员跑来和笔者说,他发现了一个MySQL的Bug,MySQL怎么会这么“傻”呢?在听完他的叙述之后,我写了如下的代码并告诉他,这不是MySQL的Bug,C语言同样也会这么“傻”。

  #include

  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: -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程序做一些修改:

  #include

  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: -1,ffffffff

  a - b: 4294967295,ffffffff

  可以看到结果都是0xFFFFFFFF,只是0xFFFFFFFF可以代表两种值:对于无符号的整型值,其是整型数的最大值,即4 294 967 295;对于有符号的整型数来说,第一位代表符号位,如果是1,表示是负数,这时应该是取反加1得到负数值,即-1。

  这个问题的核心是,在MySQL数据库中,对于UNSIGNED数的操作,其返回值都是UNSIGNED的。而正负数这个问题在《MySQL技术内幕:InnoDB存储引擎》中有更深入的分析,有兴趣的可以进一步研究。

  那么,怎么获得-1这个值呢?这并不是一件难事,只要对SQL_MODE这个参数进行设置即可,例如:

  mysql>SET sql_mode='NO_UNSIGNED_SUBTRACTION';

  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理解以及特殊情况的更多相关文章

  1. MYSQL学习笔记三:日期和时间函数

    MYSQL学习笔记三:日期和时间函数 1. 获取当前日期的函数和获取当前时间的函数 /*获取当前日期的函数和获取当前时间的函数.将日期以'YYYY-MM-DD'或者'YYYYMMDD'格式返回 */ ...

  2. MySql学习笔记三

    MySql学习笔记三 4.DML(数据操作语言) 插入:insert 修改:update 删除:delete 4.1.插入语句 语法: insert into 表名 (列名1,列名2,...) val ...

  3. mysql基本数据类型(mysql学习笔记三)

    Mysql数据类型 小数: 浮点:小数位可以变化 Float单精度默认精度6位左右 Double 双精度默认精度16位左右 支持,控制数值范围 Type(M,D) M表示所有数值位数(不包括小数点和符 ...

  4. MySQL学习笔记(三)—索引

    一.概述 1.基本概念       在大型数据库中,一张表中要容纳几万.几十万,甚至几百万的的数据,而当这些表与其他表连接后,所得到的新的数据数目更是要大大超出原来的表.当用户检索这么大量的数据时,经 ...

  5. mysql学习笔记三 —— 数据恢复与备份

    要点: 1.存储引擎2.导入导出3.备份与恢复 查看当前数据库中的所有表use db1:show tables: 1.存储引擎 不同的发动机(引擎)适用的汽车类型不一样. 存储和处理的不同方式.不同的 ...

  6. MySQL学习笔记三:库和表的管理

    1.MySQL数据库服务配置好后,系统会有4个默认的数据库. information_schema:虚拟对象,其对象都保存在内存中 performance_schema:服务器性能指标库 mysql: ...

  7. MySQL学习笔记(三):常用函数

    一:字符串函数 需要注意的几个细节: 1.cancat中有一个字符串为null,则结果为null. 2.left(str,x) 和 right(str,x)中x为null,则不返回任何字符串,不是nu ...

  8. Java多线程高并发学习笔记(三)——深入理解线程池

    线程池最核心的一个类:ThreadPoolExecutor. 看一下该类的构造器: public ThreadPoolExecutor(int paramInt1, int paramInt2, lo ...

  9. mysql学习笔记(三)

    -- 主键冲突(duplicate key) ,'xujian','anhui'); ,'xiewei','anhui'); ,'luyang','anhui');-- 主键冲突了 -- 可以选择性的 ...

  10. ROS学习笔记三(理解ROS节点)

    要求已经在Linux系统中安装一个学习用的ros软件包例子: sudo apt-get install ros-indigo-ros-tutorials ROS图形概念概述 nodes:节点,一个节点 ...

随机推荐

  1. codeforces div2_604 E. Beautiful Mirrors(期望+费马小定理)

    题目链接:https://codeforces.com/contest/1265/problem/E 题意:有n面镜子,你现从第一面镜子开始询问,每次问镜子"今天我是否美丽",每天 ...

  2. dp--C - Mysterious Present

    C - Mysterious Present Peter decided to wish happy birthday to his friend from Australia and send hi ...

  3. unity命令行参数

    Typically, Unity will be launched by double-clicking its icon from the desktop but it is also possib ...

  4. JVM的前世今生

    前世 jvm的数据区 分别是方法区(Method Area),Java栈(Java stack),本地方法栈(Native Method Stack),堆(Heap),程序计数器(Program Co ...

  5. jenkins集成robot

    一.jenkins集成robot的非gui的运行命令 pybot     配置文件   用例地址 或者robot  配置文件   用例地址 二.展示robot 运行结果图表 1.在系统配置中增加Rob ...

  6. Uncaught TypeError: Cannot read property 'addEventListener' of null

    <script type="text/javascript"> var body1=document.getElementById('#body') </scri ...

  7. 每天进步一点点------直接数字频率合成DDS

     

  8. Linux gd库安装步骤说明

    gd 库是 PHP 处理图形的扩展库,它提供了一系列用来处理图片的 API(应用程序编程接口),使用 gd 库可以处理图片或者生成图片.在网站上,gd 库通常用来生成缩略图,或者对图片加水印,或者生成 ...

  9. 使用spring中遇到"java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor"问题

    项目中缺少aopalliance的jar包,下载一个相应的jar加入项目中就可以解决问题. 下载链接:http://www.java2s.com/Code/Jar/a/Downloadaopallia ...

  10. JQuery/JS插件 jsTree加载树,预先加载,初始化时加载前三级节点,当展开第三级节点时 就加载该节点下的所有子节点

    jsTree加载树, 初始化时 加载前三级节点, 当展开第三级节点时 就加载该节点下的所有子节点 html: <!DOCTYPE html> <html> <head&g ...