今天在做db2測試的時候發現乙個問題:
select 1/3 from sysibm.sysdummy1;
結果得到: 0!!!!鬱悶,怎麼會這樣。
後來仔細查了一下db2的資料,發現db2的算術運算是遵循一下規則:
argument1 argument2 result
decimal(a,b) decimal(c,d) decimal(p,s)
p=max( max(b,d) + max(a-b,c-d)
s=max(b,d)
但除法的小數字計算遵循下面規則: 31-p+s-s'(其中p為被除數的精度,s為被除數的小數字,s'為除數的小數字)
舉例來講:
1/3 由於,由於兩者資料型別皆為int,所以結果也為int 即結果為0
1.0/3,由於1.0為小數,按照小數除法的規則,
describe select 1.0 from sysibm.sysdummy1; (2,1)
describe select 3 from sysibm.sysdummy1; (4,0)
31-2+1-0=31-1=3031-2+1=30,故此保留30位小數。
select 1.0/3 from sysibm.sysdummy1;
結果為:--- 0.333333333333333333333333333333
1/3.0,由於1為int,3.0為小數
describe select 1 from sysibm.sysdummy1; (4)---4個位元組,共佔10位,其中符號位一位,共11位
describe select 3.0 from sysibm.sysdummy1; (2,1)
31-11+0-1=31-12=19,故此保留19位小數。
select 1/3.0 from sysibm.sysdummy1;
結果為:---0.3333333333333333333
另外,如果你的db2沒有設定過的話,執行一下語句可能會出錯:
select dec(1,31,0)/dec(1,31,5) from sysibm.sysdummy1;
報錯說除法運算無效。其實原因就是小數字的問題,按照31-p+s-s'的演算法,31-31+0-5=-5,也即小數字數為-5,小數字又怎麼能是負值呢?所以就報錯了。
此時需要設定乙個引數:min_dec_div_3. 執行以下語句即可
db2 update db cfg for db_name using min_dec_div_3 yes
即將min_dec_div_3的值設定為yes,意思是小數字數取3和按照31-p+s-s' 計算出的小數字兩者的較大值。即是說最小也有3位小數,這樣自然就不會再報錯了。
需要注意的是,雖然可以使用db2 update db cfg 命令來設定min_dec_div_3這個引數,但是實際上這個引數在db cfg 中是不可見的。
也就是說不要指望使用db2 get db cfg for db_name 可以找到它,這是乙個隱藏的引數(搞不懂db2是什麼用意。。。。。。)。
從db2v7版本以上又引入了乙個db2_min_dec_div_6這麼乙個引數,可以將小數字至少儲存6位,如果min_dec_div_3和db2_min_dec_div_6同時為yes,則db2_min_dec_div_6覆蓋min_dec_div_3。
db2_min_dec_div_6這個引數可以使用db2set 來設定:語句為
db2set db2_min_dec_div_6=yes 可以使用db2set -all 來檢視
設完需要重啟db2。
(ps:我使用的是db2 v9.5,伺服器為aix,在我自己的平台上測試min_dec_div_3是可以的,但是無論我把db2_min_dec_div_6設定為yes或者no,都沒看出有什麼效果,不知道是我的設定方法不對還是怎麼回事。)
如果想要最初的語句1/3得到非零值。可以使用如下方法:
(1) select 1.0/3 from sysibm.sysdummy1; ---得到小數值 結果: --0.333333333333333333333333333333
(2) select 1/3.0 from sysibm.sysdummy1; ----同樣得到小數值 結果: --0.3333333333333333333
(3) select cast(1 as float)/3 from sysibm.sysdummy1; --使用cast將1轉為float型,然後再才除以3. 結果:0.3333333333333333
(4) select dec(1,10,2)/3 from sysibm.sysdummy1; ---使用dec函式將1轉換為decimal(10,2),然後除以3 結果:0.33333333333333333333333
其實如果想要把2個數的商四捨五入儲存兩位小數,
oracle中可以直接使用round函式即可:
select round(a/b,2) from dual;
而db2中卻要繞幾個彎才行:需要使用
select dec(cast(a as float)/b+0.005,10,2) from sysibm.sysdummy1; 先用cast轉換a為float型,然後運算,再使用+0.005作為四捨五入,然後再使用dec擷取2位小數。或者:
select cast(round(cast(a as float)/b,2) as decimal(10,2)) from sysibm.sysdummy1; 先使用cast轉a為float,然後運算,再使用round四捨五入取2位小數,然後使用cast轉換為decimal(10,2)型。
哎。。。可憐的db2啊。
下邊貼乙個關於db2小數字的英文文獻供參考:
DB2之DECIMAL小數字數導致的乘法溢位
decimal值型別最長為31位,它在做乘法運算的時候,會將小數字數自動加和而擠占整數字,直到擠占完畢導致結果溢位。比如a decimal 24,6 b decimal 24,6 則a b的結果是decimal 31,12 比如a decimal 5,2 b decimal 6,3 則a b的結果是...
關於DB2的使用(DB2資料命令)
公司所用的資料庫有金倉和db2 首先要用命令視窗直接開啟db2需要在cmd中輸入 db2cmd 1 啟動db2資料庫 db2start 2 連線資料庫 db2 connect to 資料庫名稱 3 建立資料庫 db2 create db 資料庫名稱 4 刪除資料庫 db2 drop db 資料庫名稱...
關於DB2的日常學習
場景一 需要插入的資料做了id非重複的控制,但沒有做自增加,提前準備的指令碼的時候,你也不知道生產資料庫裡id到多少了。解決方式 在insert語句中嵌入select語句,實時獲取最新一條資料的id demo insert into esb2 flow ctrl dimension,keyword,...