ORACLE NUMBER類型Scale為0引發的問題


今天遇到了一個很有意思的NUMBER類型Scale引發的問題,我用一個簡單的測試用例來展示一下這個案例。假如有個TEST的表,有個字段類型為NUMBER,我插入下面兩條數據

CREATE TABLE TEST
(
     Category VARCHAR(12),
     QTY  NUMBER
)
 
INSERT INTO TEST
SELECT 'M', 12 FROM DUAL UNION ALL
SELECT 'C', 0.99999999999999999 FROM DUAL;
 
COMMIT;

此時直接查詢表TEST,發現QTY字段值為1,

clip_image001

使用下面SQL語句統計時,SUM_QTY的值也是1

clip_image002

但是如果在游標里面獲取該值的時候,你會發現字段QTY的值為原來的值.99999999999999999

DECLARE  CURSOR c_test
IS
   SELECT Category, SUM(QTY) AS SUM_QTY FROM TEST
   GROUP BY Category;
   
   c_row c_test%rowtype;
   
 begin 
       for c_row in c_test loop
           dbms_output.put_line('the result is ' || c_row.SUM_QTY);
       end loop;
 end;

the result is .99999999999999999

the result is 12

為什么會有這個奇怪的現象呢? 其實我們遇到這個案例時是按這個順序反着的,最后發現是插入的值是0.999999999. 當然這個過程是非常糾結的。遠非我們例子里面那樣輕松簡單。要解釋這個問題,要從NUMBER類型說起,NUMBER (p, s) 聲明一個定點數 p(precision)為精度,s(scale)表示小數點右邊的數字個數,精度最大值為38,scale的取值范圍為-84到127。Number(p) 表示聲明一個整數相當於Number(p, 0), 如果不指定p和s,NUMBER類型,它的默認精度值為38, 默認的scale值為0. 所以出現在SELECT語句中,一個值為.99999999999999999 的顯示為1,但是在游標中,它獲取的是這個字段的真實值,沒有經過轉化。所以出現了這個稀奇古怪的問題。雖然事后理順過后覺得非常簡單,但是當時不了解情況下,覺得非常不可思議,非常納悶!

 

另外附上定點數的精度(p)和刻度(s)遵循以下規則:
 當一個數的整數部分的長度 > p-s 時,Oracle就會報錯
 當一個數的小數部分的長度 > s 時,Oracle就會舍入。
 當s(scale)為負數時,Oracle就對小數點左邊的s個數字進行舍入。
 當s > p 時, p表示小數點后第s位向左最多可以有多少位數字,如果大於p則Oracle報錯,小數點后s位向右的數字被舍入


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM