MySQL資料型別 UNSIGNED注意事項

2021-07-25 13:52:19 字數 4388 閱讀 4014

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) 大整數值

源文件 <>

看起來這是乙個不錯的屬性選項,特別是對於主鍵是自增長的型別,因為一般來說,使用者都希望主鍵是非負數。然而在實際使用中,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。

#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]的結果)

a                                       b

array (  [1] => 1351843032  [2] => 1351756658  )

-2567

array ( [1] => 1351843032  [2] => 1351845599  )

array ([1] => 1351843032  [2] => 1351756658 )

array (  [1] => 1351843032  [2] => 1351756658  )

-105849

array (  [1] => 1351650809  [2] => 1351756658 )

array (  [1] => 1351843032 [2] => 1351756658  )

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資料型別用法 mysql資料型別和用法

歡迎進入linux社群論壇,與200萬技術人員互動交流 進入 mysql支援多種列型別 數值型別 日期 時間型別和字串 字元 型別。本章首先對這些列型別進行了概述,然後更加詳細地描述了各種列的型別,以及列型別儲存需求的總結。概述很簡單。關於具體列型別 歡迎進入linux社群論壇,與200萬技術人員互...

mysql 資料型別 真假 MySQL 資料型別

mysql基礎 資料型別 整型型別 根據所儲存的整數數值取值範圍不同,可分為以下五類 1 tinyint佔1個位元組 2 smallint佔2個位元組 3 mediumint 佔3個位元組 4 int佔4個位元組 5 bigint佔8個位元組 根據每種型別所佔的位元組數可確定其無符號整數和有符號整數...

mysql 郵箱 資料型別 mysql 資料型別

1 整型mysql資料型別含義 有符號 tinyint m 1個位元組 範圍 128 127 smallint m 2個位元組 範圍 32768 32767 mediumint m 3個位元組 範圍 8388608 8388607 int m 4個位元組 範圍 2147483648 21474836...