MySQL数据类型:UNSIGNED注意事项(转)
原文地址:https://www.cnblogs.com/blankqdb/archive/2012/11/03/blank_qdb.html
1. UNSIGNED
UNSIGNED属性就是将数字类型无符号化,与C、C++这些程序语言中的unsigned含义相同。例如,INT的类型范围是-2 147 483 648 ~ 2 147 483 647, INT UNSIGNED的范围类型就是0 ~ 4 294 967 295。
在MYSQL中整型范围:
类型 大小 范围(有符号) 范围(无符号) 用途
TINYINT 1 字节 (-128,127) (0,255) 小整数值
SMALLINT 2 字节 (-32 768,32 767) (0,65 535) 大整数值
MEDIUMINT 3 字节 (-8 388 608,8 388 607) (0,16 777 215) 大整数值
INT或INTEGER 4 字节 (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值
源文档 <http://www.cnblogs.com/bukudekong/archive/2011/06/27/2091590.html>
看起来这是一个不错的属性选项,特别是对于主键是自增长的类型,因为一般来说,用户都希望主键是非负数。然而在实际使用中,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操作系统中(windows中也会),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类型。
以上文字摘自<http://tech.it168.com/a2012/0808/1382/000001382732.shtml>
本人遇到的类似问题:(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注意事项(转)的更多相关文章
- Database基础(一):构建MySQL服务器、 数据库基本管理 、MySQL 数据类型、表结构的调整
一.构建MySQL服务器 目标: 本案例要求熟悉MySQL官方安装包的使用,快速构建一台数据库服务器: 安装MySQL-server.MySQl-client软件包 修改数据库用户root的密码 确认 ...
- mysql 数据类型
1.整型 MySQL数据类型 含义(有符号) tinyint(m) 1个字节 范围(-128~127) smallint(m) 2个字节 范围(-32768~32767) mediumint(m) ...
- MySQL 数据类型 详解
MySQL 数据类型 详解 MySQL 的数值数据类型可以大致划分为两个类别,一个是整数,另一个是浮点数或小数.许多不同的子类型对这些类别中的每一个都是可用的,每个子类型支持不同大小的数据,并且 My ...
- MySQL数据类型 int(M) 表示什么意思?详解mysql int类型的长度值问题
MySQL 数据类型中的 integer types 有点奇怪.你可能会见到诸如:int(3).int(4).int(8) 之类的 int 数据类型.刚接触 MySQL 的时候,我还以为 int(3) ...
- MySQL数据类型——数值类型
1.1.1 整型 整型 占用字节 范围 范围 tinyint 1 -27~27-1 -128~127 smallint 2 -215~215-1 -32768~32767 mediumint 3 -2 ...
- 【转】MySQL数据类型和常用字段属性总结
来源:http://www.jb51.net/article/55853.htm 这里先总结数据类型.MySQL中的数据类型大的方面来分,可以分为:日期和时间.数值,以及字符串.下面就分开来进行总结. ...
- Oracle、SQL Server、MySQL数据类型对比
1,标准SQL数据类型 BINARY 每个字符占一个字节 任何类型的数据都可存储在这种类型的字段中.不需数据转换(例如,转换到文本数据).数据输入二进制字段的方式决定了它的输出方式. BIT 1 个字 ...
- MySQL数据类型和常用字段属性总结
前言 好比C++中,定义int类型需要多少字节,定义double类型需要多少字节一样,MySQL对表每个列中的数据也会实行严格控制,这是数据驱动应用程序成功的关键.MySQL提供了一组可以赋给表中各个 ...
- MySql数据类型详解
可配合http://www.cnblogs.com/langtianya/archive/2013/03/10/2952442.html学习 MySql数据类型 1.整型(xxxint) MySQ ...
- MySQL数据类型总结
MySQL中的数据类型大的方面来分,可以分为:日期和时间.数值,以及字符串.下面就分开来进行总结. 日期和时间数据类型 MySQL数据类型 含义 date 3字节,日期,格式:2014-09-18 t ...
随机推荐
- 关于TCP/IP
一.网络模型 计算机网络的两种模型:OSI 模型和 TCP/IP 模型 由于 OSI 模型过于复杂难以实现,导致 TCP/IP 模型更早地应用在现实中,这也使得 TCP/IP 模型成为标准 在 OSI ...
- poj1502 MPI Maelstrom(单源最短路)
题意:表面乍一看output是输出最小值,但仔细研究可以发现,这个最小值是从点1到所有点所花时间的最小值,其实是访问这些节点中的最大值,因为只有访问了最长时间的那个点才算访问了所有点.所以求最短路之后 ...
- nginx 负载均衡,如何判断某台服务器宕机?
答:使用参数:proxy_connect_timeout: 这个参数是连接的超时时间.设置成1,表示是1秒后超时会连接到另外一台服务器. 配置在 server 部分里.
- OSX Homebrew 安装 Spring Boot CLI
OSX Homebrew 安装 Spring Boot CLI 如果您使用的是Mac并使用Homebrew,则可以使用以下命令安装Spring Boot CLI: $ brew tap pivotal ...
- MySQL中的内连接、左连接、右连接、全连接、交叉连接
创建两个表(a_table.b_table),两个表的关联字段分别为:a_table.a_id和b_table.b_id CREATE TABLE a_table ( a_id int NOT NUL ...
- javascript:location=location;">刷新</a>
<a href="javascript:location=location;">刷新</a>
- Codeforces Round #558 (Div. 2)-Cat Party (Hard Edition)-(前缀和 + 模拟)
http://codeforces.com/problemset/problem/1163/B2 题意:有n天,每天有一个颜色,截取前x天,随便抽掉一天,使剩下的各个颜色出现的次数相等. 解题,也可以 ...
- apollo报:系统出错,请重试或联系系统负责人
说明:基于 docker 搭建的 apollo,创建项目后一直报系统出错,请重试或联系系统负责人错误. 项目人员列表一直空白: 经排查是数据库配置参数不匹配,由于自己的虚拟机 ip 为 192.168 ...
- 18-Flutter移动电商实战-首页_火爆专区商品接口制作
1.获取接口的方法 在service/service_method.dart里制作方法.我们先不接收参数,先把接口调通. Future getHomePageBeloConten() async{ ...
- UFUN函数 UF_ASSEM UF_PART函数(UF_ASSEM_ask_work_part,UF_PART_ask_part_name)
UF_initialize(); tag_t work_part_tag=NULL_TAG; ]=""; //获取当前工作部件的tag work_part_tag=UF_ASSEM ...