最近自己的程序在調用mysql的存儲過程傳參給smallint類型變量的時候,總是出現out of range value的錯誤,剛開始用C數值轉換方式的二進制位轉換思路來思考時,總是覺得沒什么問題,因為我的數確實在16位二進制數下能保存,但是后來才發現,原來mysql並不是按照這種二進制轉換的方式。
先附上mysql各個整數類型的取值范圍:
bigint
從 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型數據(所有數字)。存儲大小為 8 個字節。
P.S. bigint已經有長度了,在mysql建表中的length,只是用於顯示的位數
int
從 -2^31 (-2,147,483,648) 到 2^31 – 1 (2,147,483,647) 的整型數據(所有數字)。存儲大小為 4 個字節。int 的 SQL-92 同義字為 integer。
smallint
從 -2^15 (-32,768) 到 2^15 – 1 (32,767) 的整型數據。存儲大小為 2 個字節。
tinyint
從 0 到 255 的整型數據。存儲大小為 1 字節。
因為所要調用的存儲過程主要是為了實現insert操作,而和這個存儲過程中smallint類型的變量對應的表中欄位是一個無符號smallint,由於mysql存儲過程是沒有無符號這種類型,所以只好在存儲過程接受時用smallint接收,當時猜想mysql可能和C語言中一樣應該會自動對有符號數進行無符號數轉換。
可是並不是這樣,當我傳入參數64000(在無符號bigint內不在有符號bigint內),mysql會提示錯誤out of range value,意思是超出了取值范圍。在不斷的測試之后,我發現mysql並不會像常用的編程語言的機制那樣,會自動將有符號數轉換為無符號數,當判斷你不在有符號數(此處是-32768-32767)或者無符號數(0-65535)之間時,它就認定你是一個非法數,超出了范圍,然后會提示錯誤;當你用無符號數時,你傳入的若是一個負數,則認定你傳入的數也是一個非法數(親測是這樣),然后也會提示該錯誤。
解決方法:
由於存儲過程沒有無符號類型,所以在接受傳入的值的時候,我們可以使用大范圍的數進行接收,比如這里我將smallint類型改為了int,就能正常運行了。
個人理解:
我個人覺得,mysql里面在數值方面並沒有特別注意類型這個概念,而只是關心的是范圍,我們設定了類型,其實就是設定了范圍,當我們傳入一個數字,如果在這個范圍內,我們就認定是這個類型的。當然這是我個人的看法,只是為了方便理解。如果有什么問題的話,希望大家多提建議。