UNSIGNED 無符號化

2022-07-22 12:21:14 字數 2732 閱讀 6845

在介紹資料型別前,先來介紹兩個屬性:unsigned和zerofill,是否使用這兩個屬性對選擇資料型別有著莫大的關係。

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()

上述**的執行結果是:

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()

這次不僅列印出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型別。

文字符號化 Fslex

文字符號化 fslex 文字符號化 tokenizing,有時也叫詞法分析,lexical analysis 或 lexing 其基本意思是把文字分成可管理的塊 lump 或符號 token 要用到工具fslex.exe,它本身就是建立詞法分析器 有時也叫掃瞄器,scanner 進行文字符號化的程式...

iOS 崩潰符號化

1.符號表是什麼?dsym檔案其實是乙個目錄,在子目錄中包含了乙個16進製制的儲存函式位址對映資訊的中轉檔案,所有debug的symbols都在這個檔案中 包括檔名 函式名 行號等 所以也稱之為除錯符號資訊檔案。注意 來檢查 那如何知道crash檔案的uuid呢?可以用 grep 那麼,問題就來了!...

C MapwinGIS符號化配置

背景 基於c 進行mapwingis開發,現在需要對管點管線資料進行符號化。之前通過工程檔案來載入資料和符號化,現在資料單獨載入 sqlserver 符號化也要單獨載入 符號配置檔案 基於style配置檔案對資料進行符號化。管線通過defaultdrawingoptions對其進行符號化。管點基於附...