MySQL 中的数字类型
MySQL 中数据类型常用的就三大类:
另外还包含两个没那么常用的大类:
继续之前,先来看一些单位上的约定和概念,
存储字符串时指定的类型
展示宽度/Display Width那么什么是展示宽度。展示宽度这个参数具有迷惑性,它不像 CREATE TABLE test_zero_fill mysql> INSERT INTO test_zero_fill (with_fill, without_fill) VALUES (5, 5),(123456, 123456); 另外,如果使用了 mysql> ALTER TABLE test_zero_fill ADD signed_num INT(5) signed ZEROFILL NOT NULL after without_fill; 所以对于数据存储层面来说,展示宽度其实没什么用途。如果真的需要格式化,程序中能够请求 MySQL 的 meta 信息以获取到相应的展示宽度。 假如在 Node.js 中使用 mysqljs/mysql 作为数据库连接的模块,在执行请求时,其回调中返回的 connection.query("SELECT * from test_zero_fill", function(
fields 中包含列的 meta 信息
|
类型 | 空间 (字节) | 有符号时最小取值 | 无符号时最小取值 | 有符号时最大取值 | 无符号时最大取值 |
---|---|---|---|---|---|
TINYINT | 1 | -128 | 0 | 127 | 255 |
SMALLINT | 2 | -32768 | 0 | 32767 | 65535 |
MEDIUMINT | 3 | -8388608 | 0 | 8388607 | 16777215 |
INT | 4 | -2147483648 | 0 | 2147483647 | 4294967295 |
BIGINT | 8 | -263 | 0 | 263-1 | 264-1 |
具体到每种类型:
- TINYINT[(M)] [UNSIGNED] [ZEROFILL]:微整型,取值范围 -128 ~ 127,无符号情况下为 0 ~ 255。
- BOOL, BOOLEAN:效果等同
TINYINT(1)
,0 表示 FALSE,其他非 0 值处理成 TRUE。其中关键字TRUE
,FALSE
真实代表的是数字 1 和 0。
mysql> SELECT IF(0, 'true', 'false');
+------------------------+
| IF(0, 'true', 'false') |
+------------------------+
| false |
+------------------------+ mysql> SELECT IF(1, 'true', 'false');
+------------------------+
| IF(1, 'true', 'false') |
+------------------------+
| true |
+------------------------+ mysql> SELECT IF(2, 'true', 'false');
+------------------------+
| IF(2, 'true', 'false') |
+------------------------+
| true |
+------------------------+
mysql> SELECT IF(0 = FALSE, 'true', 'false');
+--------------------------------+
| IF(0 = FALSE, 'true', 'false') |
+--------------------------------+
| true |
+--------------------------------+ mysql> SELECT IF(1 = TRUE, 'true', 'false');
+-------------------------------+
| IF(1 = TRUE, 'true', 'false') |
+-------------------------------+
| true |
+-------------------------------+ mysql> SELECT IF(2 = TRUE, 'true', 'false');
+-------------------------------+
| IF(2 = TRUE, 'true', 'false') |
+-------------------------------+
| false |
+-------------------------------+ mysql> SELECT IF(2 = FALSE, 'true', 'false');
+--------------------------------+
| IF(2 = FALSE, 'true', 'false') |
+--------------------------------+
| false |
+--------------------------------+
- SMALLINT[(M)] [UNSIGNED] [ZEROFILL]:小整型。取值范围 -32768 ~ 32767,无符号情况下为 0 ~ 65535。
- MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]:中整型。取值范围 -8388608 ~ 8388607,无符号情况下为 0 ~ 16777215。
- INT[(M)] [UNSIGNED] [ZEROFILL]: 整型。取值范围 -2147483648 ~ 2147483647,无符号情况下为 -2147483648 ~ 2147483647。
- INTEGER[(M)] [UNSIGNED] [ZEROFILL]:同
INT
。 - BIGINT[(M)] [UNSIGNED] [ZEROFILL]:大整型。取值范围 -9223372036854775808 ~ 9223372036854775807,无符号情况下为 0 ~ 18446744073709551615。
关于大整型,关键字 SERIAL
等同于 BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
。
还记得创建表时一般需要指定一个自增的整形 ID 字段么,
CREATE TABLE table_name (id INT UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT)
SERIAL
关键字其实是 BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
的别名,所以下次创建表时可直接使用该关键字,会省事很多。
CREATE TABLE table_name (id SERIAL PRIMARY KEY)
如果你不想要 BIGINT,SERIAL DEFAULT VALUE
是 NOT NULL AUTO_INCREMENT UNIQUE
的别名,那么可以这样来简写 ID 字段:
CREATE TABLE table_name (id INT SERIAL DEFAULT VALUE PRIMARY KEY)
定点型
DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL] 定点型数字,其中 M 表示总的位数(不包含正负号及小数点),D 表示小数位数。D 为 0 则表示没有小数部分。M 最大取值 65,默认 10;D 最大支持到 30,默认 0。所有的算术运算(+
,-
,*
,/
)都基于 65 位的 DECIMAL。
DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL] 同 DECIMAL
。
定点型数字存储精确的数字,用于准确性要求高的场合,比如涉及金钱。底层实现上,MySQL 使用二进制形式存储该类型的值。
通常的用法如下:
salary DECIMAL(5,2)
上面示例中,salary 为一个 5 位精度两位小数的定点型。取值范围 -999.99 ~ 999.99。
因为 D 缺省时默认为 0,所以 DECIMAL(M)
表示 DECIMAL(M,0)
,现时,MySQL 中,M 缺省时默认为 10,所以 DECIMAL
表示 DECIMAL(10,0)
。
当实际存储的值其小数大于指定的位数时,其精度会自动转换成所存储的值的精度。
浮点型
区别于 DECIMAL,浮点型存储的数字是个近似值。内部存储时,MySQL 为单精度使用 4 字节(bytes),双精度使用 8 字节。
浮点型包含以下这些类型:
- FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]:小型的单精度浮点型。根据 IEEE 标准理论取值范围 -3.402823466E+38 ~ -1.175494351E-38, 0, 1.175494351E-38 ~ 3.402823466E+38,实际的取值范围因硬件和操作系统而异,会比理论值要小。
- M 表示总位数,D 表示小数位数。两者省略的情况下,其值为硬件允许的最大值。比如
FLOAT(7,4)
看起来会是这个样子:-999.9999
。 FLOAT[(M,D)
这种形式的类型不是标准的 SQL 类型,后续会废弃掉。
- M 表示总位数,D 表示小数位数。两者省略的情况下,其值为硬件允许的最大值。比如
- FLOAT(p) [UNSIGNED] [ZEROFILL]:是标准的 SQL 类型,p 表示精度。但 MySQL 中,根据 p 取值的不同,底层实际将其处理成别的类型。比如 0 ~ 24 时,当成 4 字节单精度 FLOAT 类型来处理,25 ~ 53 时处理成 8 字节双精度的 DOUBLE 类型。
- DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]:双精度浮点型。取值范围 -1.7976931348623157E+308 ~ -2.2250738585072014E-308, 0, 2.2250738585072014E-308 ~ 1.7976931348623157E+308。同
FLOAT(M,D)
,DOUBLE(M,D)
这种形式的双精度类型也是非标准 SQL 类型,后续会废弃。 - DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL]:DOUBLE 的别名。
所以实际使用时,为了最大限度的兼容性,直接使用 FLOAT
,DOUBLE
,PRECISION
而不要指定精度及小数。
BIT 类型
BIT[(M)] 类型用于存储单个状态值,M 表示包含几位。默认为1,最大可取 64。
该类型的值可通过 b'value'
的形式书写,其中 value 部分以二进制的形式呈现,比如 b'111' 和 b'10000000' 分别表示 7 和 128。更加详细的信息可参考 9.1.5 Bit-Value Literals。
如果赋值到该类型上的值小于 M 指定的位数,值左边会补零,比如将 b'101' 存储到类型为 BIT(6) 的列,实际会是 b'000101'。
存储的值溢出的情况
将要存储的值超出数字类型的范围时,其表现跟当前设置的 SQL 模式有关。具体来说,
- 开启 SQL 严格模式时,超出范围的值会写入失败,MySQL 会中断操作并且直接抛错。
- 非严格模式下,MySQL 会将值裁剪到合适的大小进行写入。即超出的情况下存成该类型能够接收的最大值。
考察一个通过如下语句创建的表 t1
:
CREATE TABLE t1 (i1 TINYINT, i2 TINYINT UNSIGNED);
SQL 严格模式下,尝试写入一个超出范围的值时抛错:
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)
以下是非严格模式下进行裁剪存储的情况:
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 |
+------+------+
上述表现同样会出现在涉及到对列进行转换修改的一些操作上,比如 ALTER TABLE
,LOAD DATA
,UPDATE
以及使用 INSERT
同时插入多行数据时。严格模式下会抛错失败,非严格模式下值会进行裁剪。但失败的情况不尽相同,如果是事务类型的表,会整个全失败,其他情况根据具体的值会部分成功,部分失败。
进行数字计算时如果有溢出,也会抛错,比如对于 BIGINT 其最大值为 9223372036854775807,因为 MySQL 中默认对数字类型是有符号类型,如下操作会抛错,
mysql> SELECT 9223372036854775807 + 1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1)'
对于上述情况,可显式将 被操作数进行类型转换,转成无符号的 BIGINT:
mysql> SELECT CAST(9223372036854775807 AS UNSIGNED) + 1;
+-------------------------------------------+
| CAST(9223372036854775807 AS UNSIGNED) + 1 |
+-------------------------------------------+
| 9223372036854775808 |
+-------------------------------------------+
通过带上小数后,转成 DECIMAL 也能修正上面的错误,因为 DECIMAL 比整形要大,
mysql> SELECT 9223372036854775807.0 + 1;
+---------------------------+
| 9223372036854775807.0 + 1 |
+---------------------------+
| 9223372036854775808.0 |
+---------------------------+
两数相减时,其中一个为无符号数,得出的结果默认为也为无符号。所以如果想减之后结果是负数,则会抛错。
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
:
mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| -1 |
+-------------------------+
总结
对于整型或浮点型,可指定 AUTO_INCREMTN
属性。指定该属性性,将不能接收负值。同时 CHECK
属性与该属性冲突,也不能同时使用。但对于 FLOAT 和 DOUBLE,AUTO_INCREMENT
属性的支持将逐渐废弃掉,实际使用时尽量避免。
对于需要精确数值的场合,使用 DECIMAL,比如涉及金钱的情况。
对于整形,展示宽度不是其存储的值范围,只用来格式化。
相关资源
MySQL 中的数字类型的更多相关文章
- Mysql中的一些类型
列类型--整数类型Tinyint:迷你整形 一个字节=8位 最大能表示的数值是0-255 实际区间 -128~127Smallint:小整形 两个字节 能表示0-65535Mediumint:中整型 ...
- python3中的数字类型
今天在学校机房刷python题时发现自己对python中的数字类型不理解,回寝室后百度一下. 现在做一个总结. python中的数字类型有: 整数,布尔值,复数,科学计数法,浮点数 1,整数,大小没有 ...
- 解析MySQL中存储时间日期类型的选择问题
解析MySQL中存储时间日期类型的选择问题_Mysql_脚本之家 https://www.jb51.net/article/125715.htm 一般应用中,我们用timestamp,datetime ...
- javaScript中Number数字类型方法入门
前言 Number和Math都属于JavaScript中的内置对象,Number数字类型作为基础数据类型,我们在开发过程中会经常用到,包括数字精度的格式化,还有字符串转换成数字等操作. Number数 ...
- 关于MySql中的varchar类型
今天新开始的项目在做数据库设计,发现自己对MySql的varchar类型还不熟悉,故又上网收集资料整理如下. 1.varchar类型的变化 MySQL 数据库的varchar类型在4.1以下的版本中的 ...
- mysql中的timestamp类型时间比较:unix_timestamp函数
在mysql中,某字段的类型设置为了timestamp,那么我们现在希望取出指定时间段的记录,该如何做呢? 在php中有time()和strtotime()来进行日期和时间戳的格式化,而在mysql中 ...
- MySql中的varchar类型
转载:http://www.cnblogs.com/doit8791/archive/2012/05/28/2522556.html 1.varchar类型的变化 MySQL 数据库的varchar类 ...
- MySQL 中的字符串类型
字符类型包括: CHAR VARCHAR BINARY VARBINARY BLOB TEXT ENUM SET CHAR 与 VARCHAR CHAR(m) m 取值范围 0-255.列宽固定,存储 ...
- MySql中的时间类型datetime,timestamp,date,year比较
MySQL日期类型.日期格式.存储空间.日期范围比较.日期类型 存储空间 日期格式 日期范围------------ --------- ...
随机推荐
- php json 写入 mysql 的例子
$a['aaa']='aaaa'; $a['bbb']='bbb'; $a['ccc']='ccc'; $arr['step_name']='kfkf'; $arr['process_name']=' ...
- Newtonsoft.Json反序列化(Deserialize)出错:Bad JSON escape sequence
使用Newtonsoft.Json反序列化收到的字串为JObject或其它支持的数据模型,有时错误,提示如下: Bad JSON escape sequence: \c. Path , positio ...
- ubuntu输入法
一直都是使用搜狗的,但是感觉一直都不兼容.经常输入一串文字导致输入法崩溃 比如 ‘外显’waixian就崩了. 而且会出现fcitx 100%cpu占用的情况 pkill fcitx &&am ...
- CSS的六大选择器
选择器:选择器是一种模式,用于选择需要添加样式的元素. 首先简述六大选择器 基本选择器 标签选择器 类选择器 ID选择器 高级选择器 层次选择器 结构伪类选择器 属性选择器 其中基本选择器与层次选择器 ...
- php base64上传图片
php实现base64图片上传方式 本例子中没有采用File Post上传文件方式!原理一样,为了更加的理解base64 选择将其输出在文本域中,并提交至服务器!运用到项目中建议采用提交File方式. ...
- 20172306 2018-2019-2 《Java程序设计》第五周学习总结
20172306 2018-2019-2 <Java程序设计>第五周学习总结 教材学习内容总结 查找 查找中,我们对这些算法的实现就是对某个Comparable对象的数组进行查找 泛型声明 ...
- 杨其菊201771010134《面向对象程序设计(java)》第六周学习总结
<面向对象程序设计(java)>第六周学习总结 第一部分:理论知识 1)类.超类和子类2)Object:所有类的超类 3)泛型数组列表4)对象包装器和自动打包 5)参数数量可变的方法 6) ...
- 第42章:MongoDB-集群--Sharding(分片)--单机的搭建
①配置服务器 在大型的集群中,建议配置3台配置服务器,就足够用了.启动配置服务器的方式: 1:先创建几个存放数据的文件夹,比如在前面的dbs下面创建confdb文件夹,然后在confdb下面创建con ...
- mysql数据库到底是什么?!
MySql是MySql.AB公司开发的,采用客户/服务器模型的开放源码关系型SQL数据库管理系统,它可以在多种操作系统上运行. 客户端/服务器:C/S.需要给不同系统安装不同的软件,是专用的协议,比较 ...
- 《mysql必知必会》学习_第15章_20180806_欢
第15章:联结表 P98 外键:外键为某个表的一列A,同时这一列包含另一个表的主键值B(B属于A,等于或者小于的关系) P99 select vend_name,prod_name,prod_pric ...