NUMBER | 오라클 NUMBER 타입은 38자리 정밀도까지 숫자를 저장 할 수 있다. 기본적 데이터 형식은 묶음 10진수 데이터타입은 길이가 0~22바이트인 가변길이 형식 사용되는 가장 일반적인 형식 |
BINARY_FLOAT | IEEE에서 정의한 단정도 부동소수점 숫자다. 디스크에서 5바이트 저장공간을 차지 |
BINARY_DOUBLE | IEEE에서 정의한 배정도 부동소수점 숫자다. 디스크에서 9바이트 저장공간을 차지 |
-- 숫자 타입
SQL> DROP TABLE T;
테이블이 삭제되었습니다.
SQL>
SQL> CREATE TABLE T
2 (
3 NUM_COL NUMBER,
4 FLOAT_COL BINARY_FLOAT,
5 DBL_COL BINARY_DOUBLE
6 );
테이블이 생성되었습니다.
SQL> INSERT INTO T (NUM_COL, FLOAT_COL, DBL_COL)
2 VALUES(1234567890.0987654321
3 ,1234567890.0987654321
4 ,1234567890.0987654321);
1 개의 행이 만들어졌습니다.
SQL> SET NUMFORMAT 9999999999.9999999999
SQL>
SQL> SELECT * FROM T;
NUM_COL FLOAT_COL DBL_COL
---------------------- ---------------------- ----------------------
1234567890.0987654321 1234567940.0000000000 1234567890.0987654000
-- NUM : 정확한 숫자보존
-- BINARU_FLOAT : 7자리까지 정확하게 표현
-- BINARY_DOUBLE : 17자리까지 정확하게 표현
SQL> DELETE FROM T;
0 행이 삭제되었습니다.
SQL> INSERT INTO T (NUM_COL, FLOAT_COL, DBL_COL)
2 VALUES(9999999999.9999999999
3 ,9999999999.9999999999
4 ,9999999999.9999999999);
1 개의 행이 만들어졌습니다.
SQL>
SQL>
SQL> SELECT * FROM T;
NUM_COL FLOAT_COL DBL_COL
---------- ---------- ----------
1.0000E+10 1.0E+010 1.0E+010
SQL> SET NUMFORMAT 9999999999.9999999999
SQL> SELECT * FROM T;
NUM_COL FLOAT_COL DBL_COL
---------------------- ---------------------- ----------------------
9999999999.9999999999 ###################### ######################
-- NUM_COL: 정확한 표현
-- FLOAT_COL : 정확하지 않은 표현
-- DBL_COL : 정확하지 않은 표현
SQL> DELETE FROM T;
1 행이 삭제되었습니다.
SQL> INSERT INTO T (NUM_COL) VALUES (123*1e20+123*1e-20);
1 개의 행이 만들어졌습니다.
SQL> SET NUMFORMAT 999999999999999999999999.999999999999999999999999
SQL> SELECT NUM_COL, 123*1e20, 123*1e-20 FROM T;
NUM_COL
--------------------------------------------------
123*1E20
--------------------------------------------------
123*1E-20
--------------------------------------------------
12300000000000000000000.000000000000000000000000
12300000000000000000000.000000000000000000000000
.000000000000000001230000
-- 매우 큰숫자(123*1E20), 매우 작은 숫자(123*1E-20) 시 38자리 정밀도를 초과하므로 정확한 표현하지못함
SQL> SELECT NUM_COL FROM T
2 WHERE NUM_COL = 123*1e20;
NUM_COL
--------------------------------------------------
12300000000000000000000.000000000000000000000000
-- NUM_COL의 값은 123*1e20이지, 입력값(123*1e20+123*1e-20)은 아니다.
SQL> DROP TABLE T;
테이블이 삭제되었습니다.
SQL> CREATE TABLE T(NUM_COL NUMBER(5,0));
테이블이 생성되었습니다.
SQL>
SQL> INSERT INTO T(NUM_COL) VALUES(12345);
1 개의 행이 만들어졌습니다.
SQL> INSERT INTO T(NUM_COL) VALUES(123456);
INSERT INTO T(NUM_COL) VALUES(123456)
*
1행에 오류:
ORA-01438: 이 열에 대해 지정된 전체 자릿수보다 큰 값이 허용됩니다.
-- 데이터 무결성 강화하기 위해 PERCISION을 사용가능.
-- 5자리보다 큰 숫자는 허용되지 않음.
SQL> DROP TABLE T;
테이블이 삭제되었습니다.
SQL> CREATE TABLE T(MSG VARCHAR2(10), NUM_COL NUMBER(5,2));
테이블이 생성되었습니다.
SQL>
SQL> INSERT INTO T(MSG,NUM_COL) VALUES('123.45',123.45);
1 개의 행이 만들어졌습니다.
SQL> INSERT INTO T(MSG,NUM_COL) VALUES('123.456',123.456);
1 개의 행이 만들어졌습니다.
SQL> SELECT * FROM T;
MSG NUM_COL
-------------------- --------------------------------------------------
123.45 123.450000000000000000000000
123.456 123.460000000000000000000000
SQL> SET NUMFORMAT 0
SQL> SELECT * FROM T;
MSG NUM_COL
-------------------- -------
123.45 ##
123.456 ##
SQL> SET NUMFORMAT 9999999999.99
SQL> SELECT * FROM T;
MSG NUM_COL
-------------------- --------------
123.45 123.45
123.456 123.46
-- 숫자 123.456은 5자리보다 크지만 입력된다.
-- 근데 왜 45가 아니라 46이지???
MSG NUM_COL
-------------------- --------------
123.410 123.41
123.429 123.43
123.438 123.44
123.447 123.45
123.456 123.46
123.465 123.47
123.474 123.47
123.483 123.48
123.492 123.49
123.401 123.40
10 개의 행이 선택되었습니다.
-- 형태의 데이타를 확인결과 .000 자리의 숫자를 반올림 처리하는걸 확인 할 수 있다.
SQL> INSERT INTO T(MSG, NUM_COL) VALUES('1234',1234);
INSERT INTO T(MSG, NUM_COL) VALUES('1234',1234)
*
1행에 오류:
ORA-01438: 이 열에 대해 지정된 전체 자릿수보다 큰 값이 허용됩니다.
-- 숫자 1234.00은 전체 5자리 보다 크다.
-- SCALE를 2로 지정하였으므로 십진수자리는 3자리이다.
SQL> DROP TABLE T;
테이블이 삭제되었습니다.
SQL> CREATE TABLE T(MSG VARCHAR2(10), NUM_COL NUMBER(5,-2));
테이블이 생성되었습니다.
SQL> INSERT INTO T(MSG, NUM_COL) VALUES('123.45', 123.45);
1 개의 행이 만들어졌습니다.
SQL> INSERT INTO T(MSG, NUM_COL) VALUES('123.456', 123.456);
1 개의 행이 만들어졌습니다.
SQL> SELECT * FROM T;
MSG NUM_COL
-------------------- --------------
123.45 100.00
123.456 100.00
-- 두 숫자 모두 100으로 반올림되었다.
-- 5자리 PRECISION이지만 10진수 7자리 (10의 자리까지0)까지
SQL> INSERT INTO T(MSG,NUM_COL) VALUES('1234567',1234567);
1 개의 행이 만들어졌습니다.
SQL> SELECT * FROM T;
MSG NUM_COL
-------------------- --------------
123.45 100.00
123.456 100.00
1234567 1234600.00
SQL> SET NUMFORMAT 999999999999
SQL> SELECT * FROM T;
MSG NUM_COL
-------------------- -------------
123.45 100
123.456 100
1234567 1234600
SQL> INSERT INTO T(MSG, NUM_COL) VALUES('12345678',12345678);
INSERT INTO T(MSG, NUM_COL) VALUES('12345678',12345678)
*
1행에 오류:
ORA-01438: 이 열에 대해 지정된 전체 자릿수보다 큰 값이 허용됩니다.
-- PRECISION은 반올림 후 얼마나 많은 자릿수를 허용하지는지 나타내고
-- SCALE은 어느 자리까지 반올림 할것인지 결정한다.
-- PRECISION은 무결성을 검토하고, SCALE은 값의 표현과 관련 있다.
SQL> DROP TABLE T;
테이블이 삭제되었습니다.
SQL> CREATE TABLE T(X NUMBER, Y NUMBER);
테이블이 생성되었습니다.
SQL>
SQL> INSERT INTO T(X)
2 SELECT TO_NUMBER(RPAD('9',ROWNUM*2,'9'))
3 FROM ALL_OBJECTS
4 WHERE ROWNUM <= 14;
14 개의 행이 만들어졌습니다.
SQL> UPDATE T SET Y = X+1;
14 행이 갱신되었습니다.
SQL> SET NUMFORMAT 999999999999999999999999999999
SQL> COLUMN V1 FORMAT 99
SQL> COLUMN V2 FORMAT 99
SQL> SELECT X,Y,VSIZE(X) V1, VSIZE(Y) V2
2 FROM T
3 ORDER BY X;
X Y V1 V2
------------------------------- ------------------------------- --- ---
99 100 2 2
9999 10000 3 2
999999 1000000 4 2
99999999 100000000 5 2
9999999999 10000000000 6 2
999999999999 1000000000000 7 2
99999999999999 100000000000000 8 2
9999999999999999 10000000000000000 9 2
999999999999999999 1000000000000000000 10 2
99999999999999999999 100000000000000000000 11 2
9999999999999999999999 10000000000000000000000 12 2
X Y V1 V2
------------------------------- ------------------------------- --- ---
999999999999999999999999 1000000000000000000000000 13 2
99999999999999999999999999 100000000000000000000000000 14 2
9999999999999999999999999999 10000000000000000000000000000 15 2
14 개의 행이 선택되었습니다.
-- NUMBER 타입은 가변길이 데이터 0~22바이트 저장공간은 차지
-- 오라클 NUMBER 타입은 가변 길이 문자열과 유사하다.
-- 두 개의 유효 숫자는 1바이트의 저장공간을 차지한다.
-- 그러나 X보다 1이 더 큰 Y 컬럼은 값에 상관없이 모두 2바이트를 차지한다.
SQL> SELECT TO_CHAR(0.3f+0.1f, '0.99999999999999') FROM DUAL;
TO_CHAR(0.3F+0.1F,'0.9999999999999'
----------------------------------
0.40000000600000
-- 0.3 + 0.1을 더하면 0.4이자만 부동소수점에서는 0.4보다 조금 큰 값이다.
-- 부동소수점 IEEE 숫자 방식에서 나타나는 현상
SQL> DROP TABLE T;
테이블이 삭제되었습니다.
SQL> CREATE TABLE T
2 (
3 NUM_TYPE NUMBER,
4 FLOAT_TYPE BINARY_FLOAT,
5 DOUBLE_TYPE BINARY_DOUBLE
6 )
7 ;
테이블이 생성되었습니다.
SQL> INSERT /*+ APPEND */ INTO T
2 SELECT ROWNUM , ROWNUM, ROWNUM
3 FROM ALL_OBJECTS;
71578 개의 행이 만들어졌습니다.
SELECT SUM(LN(NUM_TYPE)) FROM T;
call count cpu elapsed disk query current rows
------- ---------- ---------- ---------- ----------- ----------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 1.25 1.26 0 242 0 1
------- ---------- ---------- ---------- ----------- ----------- ---------- ----------
Total 4 1.25 1.26 0 242 0 1
SELECT SUM(LN(FLOAT_TYPE)) FROM T;
call count cpu elapsed disk query current rows
------- ---------- ---------- ---------- ----------- ----------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.02 0 241 0 1
------- ---------- ---------- ---------- ----------- ----------- ---------- ----------
Total 4 0.00 0.02 0 241 0 1
SELECT SUM(LN(DOUBLE_TYPE)) FROM T;
call count cpu elapsed disk query current rows
------- ---------- ---------- ---------- ----------- ----------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.02 0.02 0 241 0 1
------- ---------- ---------- ---------- ----------- ----------- ---------- ----------
Total 4 0.02 0.02 0 241 0 1
-- NUMBER타입은 부동소수점 타입보다 CPU시간을 더 많이 사용 한것을 볼 수 있다.
SQL> SET NUMFORMAT 999999.9999999999999999
SQL>
SQL> SELECT SUM(LN(NUM_TYPE)) FROM T;
SUM(LN(NUM_TYPE))
------------------------
728566.2621548182059859
SQL>
SQL> SELECT SUM(LN(DOUBLE_TYPE)) FROM T;
SUM(LN(DOUBLE_TYPE))
------------------------
728566.2621548145500000
-- 부동소수점 숫자는 6에서 13자리 정밀도를 가진, 숫자의 근삿값이다.
-- NUMBER타입의 결과는 부동소수점보다 더 정확하다.
-- 데이터 마이닝이나 과학 데이터의 복잡한 수학적인 분석을 수행시 정확도를 일부 포기하고 빠른 수행을 위해 사용
SELECT SUM(CAST(NUM_TYPE AS BINARY_DOUBLE)) FROM T;
call count cpu elapsed disk query current rows
------- ---------- ---------- ---------- ----------- ----------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.06 0.05 0 241 0 1
------- ---------- ---------- ---------- ----------- ----------- ---------- ----------
Total 4 0.06 0.05 0 241 0 1
-- CAST 함수를 사용하여 부동소수점으로 변환하여 NUMBER타입도 부동소수점의 성능을 낼 수 있다.