MySQL 五種整型資料型別的範圍與區別 tinyint smallint mediumint int bigint
之前在論壇上看到一個有意思的問題,如果有一個欄位的值超過bigint,會發生什麼。
然後就看到有人噴,說0.1秒插入一個值,將bigint設定為無符號,插入到極限需要多久,根本不可能遇到如何如何。
(接下來會做個測試)
好了,進入正文:
首先需要知道一個概念,如果在定義的時候,設定UNSIGNED可以將範圍擴大一倍,該值意味著此欄位無符號(即不包含負數)。
根據文件可知,資料型別有五種,分別為
TINYINT,SMALLINT,MEDIUMINT,INT(INTEGER),BIGINT。
其值的範圍,同樣查閱官方文件可知
TINYINT為 -128~127 無符號數則為127-(-128)=255(2^8-1),因為非負,所以從0開始即0~255,以此類推:
SMALLINT為 -32768~32767 無符號數則為0~65535(2^16-1)
MEDIUMINT為 -8388608~8388607 無符號數則為0~16777215(2^24-1)
INT為-2147483648~2147483647 無符號數則為0~4294967295(2^32-1)
BIGINT為-9223372036854775808~9223372036854775807 無符號數則為0~18446744073709551615(2^64-1)
當然光是INT就已經達到了20億以上的數量級,十分夠用。
下表來自MySQL 5.6官方手冊
其儲存所需容量也可以看出,由小到大分別為
TINYINT 1位元組
SMALLINT 2位元組
MEDIUMINT 3位元組
INT 4位元組
BIGINT 8位元組
當然上述資料型別及範圍好像在sql server中也是適用的,同時也包括一些程式設計語言。
回到開始的話題,如果超過BIGINT的範圍怎麼辦?
其實mysql的處理方法和超過TINYINT一樣:
此處測試均為MySQL 5.6版本(社群版),儲存引擎為預設的InnoDB。
首先插入255上限值,然後我做了如下兩個操作:
1、插入256,報錯ERROR 1264,即超過ID列的上限值。
2、插入NULL,此處應該自增,報錯ERROR 1062,即由於主鍵約束,故無法重複存在。
其報錯結果可以輕易看出,256是不能夠被插入的(廢話)
處理AUTO_INCREMENT約束時,即便遇到數值型別的上限值,仍然會嘗試插入,此時插入的值是上限值,即255。
此處可以看出此處的AUTO_INCREMENT=255,而不是256(即便255已經存在)。
注,此處(ENGINE=InnoDB後面)的AUTO_INCREMENT為MySQL認為該表的下一個自增欄位的值。
才
當然既然開始了,還是要做一下BIGINT的實驗。
同樣插入BIGINT UGSIGNED的上限值,然後繼續做如下兩個操作:
1、插入18446744073709551616,報錯ERROR 1264,即超過ID列的上限值。(與實驗1的報錯結果一致)
2、插入NULL,此處報錯與之前不同,為ERROR 1467。
ERROR 1467官方解釋為:
搜了一下google,好像還真有人在實際運用中遇到這種問題,有個小哥提出瞭如下的方法:
After some searching i found the answer and it solved my problem.
run this sql query it will fix the problem
ALTER TABLE `YOUR_TABLE` AUTO_INCREMENT = 1
我也做了如下操作,但是…… 發現並未生效。
額外兩個tips:
【1】由於TIMESTAMP用的其實是INT來儲存,故從1970年1月1日開始往後順延2147483647s,約24855天,即68年(到2038年)。
關於TIMESTAMP,官方給出的範圍是:
'1970-01-01 00:00:01.000000' UTC to '2038-01-19 03:14:07.999999' UTC.
【2】
MySQL提供了一個叫SERIAL的”型別“
實際上是unsigned NOT NULL AUTO_INCREMENT UNIQUE的別名:
關於整型資料型別寬度int(11)的解釋可參考
http://blog.itpub.net/29773961/viewspace-1804920/
作者公眾號(持續更新)
然後就看到有人噴,說0.1秒插入一個值,將bigint設定為無符號,插入到極限需要多久,根本不可能遇到如何如何。
(接下來會做個測試)
好了,進入正文:
首先需要知道一個概念,如果在定義的時候,設定UNSIGNED可以將範圍擴大一倍,該值意味著此欄位無符號(即不包含負數)。
根據文件可知,資料型別有五種,分別為
TINYINT,SMALLINT,MEDIUMINT,INT(INTEGER),BIGINT。
其值的範圍,同樣查閱官方文件可知
TINYINT為 -128~127 無符號數則為127-(-128)=255(2^8-1),因為非負,所以從0開始即0~255,以此類推:
SMALLINT為 -32768~32767 無符號數則為0~65535(2^16-1)
MEDIUMINT為 -8388608~8388607 無符號數則為0~16777215(2^24-1)
INT為-2147483648~2147483647 無符號數則為0~4294967295(2^32-1)
BIGINT為-9223372036854775808~9223372036854775807 無符號數則為0~18446744073709551615(2^64-1)
當然光是INT就已經達到了20億以上的數量級,十分夠用。
下表來自MySQL 5.6官方手冊
Type | Storage | Minimum Value | Maximum Value |
---|---|---|---|
(Bytes) | (Signed/Unsigned) | (Signed/Unsigned) | |
TINYINT | 1 | -128 | 127 |
0 | 255 | ||
SMALLINT | 2 | -32768 | 32767 |
0 | 65535 | ||
MEDIUMINT | 3 | -8388608 | 8388607 |
0 | 16777215 | ||
INT | 4 | -2147483648 | 2147483647 |
0 | 4294967295 | ||
BIGINT | 8 | -9223372036854775808 | 9223372036854775807 |
0 | 18446744073709551615 |
TINYINT 1位元組
SMALLINT 2位元組
MEDIUMINT 3位元組
INT 4位元組
BIGINT 8位元組
當然上述資料型別及範圍好像在sql server中也是適用的,同時也包括一些程式設計語言。
回到開始的話題,如果超過BIGINT的範圍怎麼辦?
其實mysql的處理方法和超過TINYINT一樣:
此處測試均為MySQL 5.6版本(社群版),儲存引擎為預設的InnoDB。
-
mysql> CREATE TABLE a (id TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT);
-
Query OK, 0 rows affected (0.25 sec)
-
-
mysql> INSERT INTO a SELECT 255;
-
Query OK, 1 row affected (0.04 sec)
-
Records: 1 Duplicates: 0 Warnings: 0
-
-
mysql> INSERT INTO a SELECT 256;
-
ERROR 1264 (22003): Out of range value for column 'id' at row 1
-
-
mysql> INSERT INTO a SELECT NULL;
-
ERROR 1062 (23000): Duplicate entry '255' for key 'PRIMARY'
-
-
mysql> SELECT * FROM a;
-
+-----+
-
| id |
-
+-----+
-
| 255 |
-
+-----+
- 1 row in set (0.00 sec)
1、插入256,報錯ERROR 1264,即超過ID列的上限值。
2、插入NULL,此處應該自增,報錯ERROR 1062,即由於主鍵約束,故無法重複存在。
其報錯結果可以輕易看出,256是不能夠被插入的(廢話)
處理AUTO_INCREMENT約束時,即便遇到數值型別的上限值,仍然會嘗試插入,此時插入的值是上限值,即255。
此處可以看出此處的AUTO_INCREMENT=255,而不是256(即便255已經存在)。
注,此處(ENGINE=InnoDB後面)的AUTO_INCREMENT為MySQL認為該表的下一個自增欄位的值。
才
-
mysql> SHOW CREATE TABLE a\G
-
*************************** 1. row ***************************
-
Table: a
-
Create Table: CREATE TABLE `a` (
-
`id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=255 DEFAULT CHARSET=latin1
- 1 row in set (0.00 sec)
當然既然開始了,還是要做一下BIGINT的實驗。
-
mysql> CREATE TABLE b (id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT);
-
Query OK, 0 rows affected (0.26 sec)
-
-
mysql> INSERT INTO b SELECT 18446744073709551615;
-
Query OK, 1 row affected (0.05 sec)
-
Records: 1 Duplicates: 0 Warnings: 0
-
-
mysql> INSERT INTO b SELECT 18446744073709551616;
-
ERROR 1264 (22003): Out of range value for column 'id' at row 1
-
-
mysql> INSERT INTO b SELECT NULL;
-
ERROR 1467 (HY000): Failed to read auto-increment value from storage engine
-
-
mysql> SHOW CREATE TABLE b\G
-
*************************** 1. row ***************************
-
Table: b
-
Create Table: CREATE TABLE `b` (
-
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1
- 1 row in set (0.00 sec)
1、插入18446744073709551616,報錯ERROR 1264,即超過ID列的上限值。(與實驗1的報錯結果一致)
2、插入NULL,此處報錯與之前不同,為ERROR 1467。
ERROR 1467官方解釋為:
Error: 1467 SQLSTATE: HY000 ()
Message: Failed to read auto-increment value from storage engine
字面意思為“從儲存引擎讀取自增欄位失敗”。搜了一下google,好像還真有人在實際運用中遇到這種問題,有個小哥提出瞭如下的方法:
After some searching i found the answer and it solved my problem.
run this sql query it will fix the problem
ALTER TABLE `YOUR_TABLE` AUTO_INCREMENT = 1
我也做了如下操作,但是…… 發現並未生效。
-
mysql> ALTER TABLE b AUTO_INCREMENT = 1;
-
Query OK, 0 rows affected (0.04 sec)
-
Records: 0 Duplicates: 0 Warnings: 0
-
-
mysql> INSERT INTO b SELECT NULL;
-
ERROR 1467 (HY000): Failed to read auto-increment value from storage engine
-
mysql> SHOW CREATE TABLE b\G
-
*************************** 1. row ***************************
-
Table: b
-
Create Table: CREATE TABLE `b` (
-
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1
- 1 row in set (0.00 sec)
額外兩個tips:
【1】由於TIMESTAMP用的其實是INT來儲存,故從1970年1月1日開始往後順延2147483647s,約24855天,即68年(到2038年)。
關於TIMESTAMP,官方給出的範圍是:
'1970-01-01 00:00:01.000000' UTC to '2038-01-19 03:14:07.999999' UTC.
【2】
MySQL提供了一個叫SERIAL的”型別“
實際上是unsigned NOT NULL AUTO_INCREMENT UNIQUE的別名:
-
mysql> CREATE TABLE test(a SERIAL);
-
Query OK, 0 rows affected (0.41 sec)
-
-
mysql> show create table test\G
-
*************************** 1. row ***************************
-
Table: test
-
Create Table: CREATE TABLE `test` (
-
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
-
UNIQUE KEY `a` (`a`)
-
) ENGINE=InnoDB DEFAULT CHARSET=latin1
- 1 row in set (0.00 sec)
-
關於整型資料型別寬度int(11)的解釋可參考
http://blog.itpub.net/29773961/viewspace-1804920/
作者公眾號(持續更新)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29773961/viewspace-1803302/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mysql中bigint、int、mediumint、smallint 和 tinyint的取值範圍MySql
- SQL SERVER數值型別int、bigint、smallint 和 tinyint範圍SQLServer型別
- mysql中tinyint、smallint、int和bigint型別的用法區別MySql型別
- mysql中int、bigint、smallint 和 tinyint的區別與長度的含義MySql
- 關於mysql中欄位定義的型別int、tinyint區別MySql型別
- 資料型別範圍資料型別
- MySQL 修改int型別為bigint SQL語句拼接MySql型別
- MySQL數字型別int與tinyint、float與decimal如何選擇MySql型別Decimal
- Golang的值型別和引用型別的範圍、儲存區域、區別Golang型別
- MySQL資料庫int型別的那些事MySql資料庫型別
- MySQL字元資料型別char與varchar的區別MySql字元資料型別
- int/double資料範圍
- mysql bigint型別和datetime型別的轉換MySql型別
- 強制型別轉換(int)、(int&)和(int*)的區別型別
- mysql int(3)與int(10)的數值範圍相同嗎?MySql
- Mysql中tinyint(1)和tinyint(4)的區別詳析WIFRMySql
- Java整型資料型別(詳解)Java資料型別
- C/C++中各種型別int、long、double、char表示範圍(最大最小值)C++型別
- int與Integer的區別
- Python基本資料型別之整型Python資料型別
- Mysql中 int(10)和int(11)的區別MySql
- mysql 中資料型別tinyint(2)括號中的數字意思MySql資料型別
- (int)a、&a、(int)&a、(int&)a的區別
- Java 支援的資料型別與 MySQL 支援的資料型別對比Java資料型別MySql
- MySQL資料庫中的timestamp型別與時區MySql資料庫型別
- Mysql兩種主要資料引擎的區別MySql
- 區別值型別資料和引用型別資料型別
- int[] 、 list<int> 、 list<int>[] 的區別
- c#System.Int32資料型別官方正寫與簡寫intC#資料型別
- SqlSugar code first 欄位為列舉型別,預設生成資料庫欄位為bigint如何設定為int型別SqlSugar型別資料庫
- Java個人學習筆記-資料型別及取值範圍Java筆記資料型別
- 判斷a是否是int型別資料型別
- Python基本資料型別之intPython資料型別
- MySQL 的資料型別MySql資料型別
- MySQL的資料型別MySql資料型別
- extern int a 和int a的區別
- Redis五種資料型別應用場景Redis資料型別
- UIModalPresentationStyle 各種型別的區別UI型別