오라클 VARCHAR2 숫자 비교 - olakeul VARCHAR2 susja bigyo

데이터타입: VARCHAR2 에 숫자를 넣으면?

     숫자를 VARCHAR2 나 CHAR 에 넣어도 된다.

     숫자를 사용하는 목적은 연산을 하기 위해서 인데, 문자형 데이터 타입을

     사용하면 연산을 할 수 없다.

     그런데, 사실은 문자 타입도 연산을 할 수 있다.

     오라클이 내부적으로 문자 타입을 숫자 타입으로 변환하기 때문이다.

     이 변환은 오라클 버전 별로 차이가 있으므로 항상 적용되는 것은 아니다.

     사칙연산은 물론이고 SUM(), AVG(), 심지어 표준편차를 구하는 STDDEV() 함수도

     문자가 적용된다.

     확인해 보자.

     테이블을 만들자.
     CREATE TABLE TTT
     (
          VC1 VARCHAR2(10)
        , VC2 VARCHAR2(10)  
     );

     값을 넣자. 소숫점도 넣어보자.

     INSERT INTO TTT VALUES ('5','7');
     INSERT INTO TTT VALUES ('8.5','11.3');
     INSERT INTO TTT VALUES ('10','20');
     INSERT INTO TTT VALUES ('15','25');
     COMMIT;

     더하기를 해보자.

     SELECT VC1, VC2, VC1+VC2 FROM TTT;    

VC1 VC2 VC1+VC2
5 7 12
8.5 11.3 19.8
10 20 30
15 25 40
     

더하기가 잘 됐다.

     표를 잘 보면 문자 정렬이 VC1, VC2 값은 왼쪽 정렬, 더한 값은 오를쪽 정렬로 되어 있다.

     이는 문자를 숫자로 변환했음을 알 수 있다.

     곱하기를 해보자.

     SELECT VC1, VC2, VC1*VC2 FROM TTT;

VC1 VC2 VC1*VC2
5 7 35
8.5 11.3 96.05
10 20 200
15 25 375

     잘 된다.

     나누기를 해보자.

     SELECT VC1, VC2, VC1/VC2 FROM TTT;

VC1 VC2 VC1/VC2
5 7 0.714285714
8.5 11.3 0.752212389
10 20 0.5
15 25 0.6

     역시, 잘 된다.

     빼기를 해보자.   

     SELECT VC1, VC2, VC1-VC2 FROM TTT;

VC1 VC2 VC1-VC2
5 7 -2
8.5 11.3 -2.8
10 20 -10
15 25 -10

     너무 잘된다.

     SUM() 은 될까?

     SELECT SUM(VC1), SUM(VC2) FROM TTT;

SUM(VC1) SUM(VC2)
38.5 63.3

     기대를 저버리지 않고 잘 됐다.

     그럼, 평균은?

     SELECT AVG(VC1), AVG(VC2) FROM TTT;

AVG(VC1) AVG(VC2)
9.625 15.825

     두말하면 잔소리. 역시 잘된다.

     이왕 하는 김에 표준편차도 해보자.

     SELECT STDDEV(VC1), STDDEV(VC2) FROM TTT;

STDDEV(VC1) STDDEV(VC2)
4.150803135 8.164302379

     하여간 잘된다.

     최소값을 가져오는 MIN() 함수도 해볼까. 잘 될꺼야.

     원래 값과 비교해 볼려고 UNION ALL 을 썼다.

     SELECT VC1, VC2 FROM TTT
     UNION ALL
     SELECT MIN(VC1), MIN(VC2) FROM TTT;

VC1 VC2
5 7
8.5 11.3
10 20
15 25
10 11.3
    

어! 결과가 좀 이상하다. 제일 작은 숫자가 5 인데. 왜 10 이 제일 작은 숫자로 나왔지?

     왜 이렇게 나왔지? 앞에 함수들은 잘 됐는데...

     혹시... 버그가 있는게 아닐까?.....

     이왕 테슽 해보는거 최대값을 가져오는 MAX() 도 해보자.

     SELECT VC1, VC2 FROM TTT
     UNION ALL
     SELECT MAX(VC1), MAX(VC2) FROM TTT;

VC1 VC2
5 7
8.5 11.3
10 20
15 25
8.5 7

     헉!  이것도 이상하네.. 15, 25 가 나와야 하는데  8.5, 7 이 나왔네...

     더구나 7은 가장 작은 수인데....

     정말 버그가 있는걸까?...  

     그런데,  아주 많은 사람들이 쓰고 있는 오라클인데 설마 이런 버그가 있을리가...

     버그가 있었어도 벌써 고쳤겠지... 지금까지 그대로 있을려구...

     에구.. 잘 모르겠다.

     커피 한잔 하며 좀 쉬어야 겠다.


오라클 VARCHAR2 숫자 비교 - olakeul VARCHAR2 susja bigyo

     잠깐, 앞에 함수들과 뭔가 다른게 있나?.....

     잘 생각해 보자. 앞에 쓴 SUM(), AVG(), STDDEV() 함수는 모두 숫자를 계산하는 함수들인데.

     MIN() 도 마찬가지 아닌가?

     작다, 크다... 아!.... 문자도 해당되는거 같은데.. A 와 B 를 비교할 수 있나?.

     A = B,  A > B,  A < B 이런 것들...

     해보면 되지..

     SELECT 'A' = 'B'  FROM DUAL;

     ORA-00923: FROM 키워드가 필요한 위치에 없습니다.

     앵!.. 왠 에러가?.....

     이렇게는 할 수 없나보네...

     그럼, WHERE 절에 넣어볼까...

     SELECT * FROM DUAL
     WHERE 'A' = 'B';
     이 건 에러는 않나는데.. 결과도 없네..

     비교 테스트 해보는 것도 쉽지 않군...

     어떻게 비교하지?....

     아!  CASE 를 써 볼까...

     우선 'A' 하고 'A' 를 비교해서 같으면 'TRUE' 를, 다르면 'FALSE' 를 보여주게 하자.

     SELECT CASE WHEN 'A' = 'A' THEN 'TRUE' ELSE 'FALSE' END   FROM DUAL;    

CASEWHEN'A'='A'THEN'TRUE'ELSE'FALSE'END
TRUE

     오호! 잘된다.

     그럼, 'A' = 'B' 를 비교해보자.

     SELECT CASE WHEN 'A' = 'B' THEN 'TRUE' ELSE 'FALSE' END   FROM DUAL;

CASEWHEN'A'='B'THEN'TRUE'ELSE'FALSE'END
FALSE

     맞네.. 'A' 와 'B' 는 다르지.

     그럼, 'A' > 'B',  'A' < 'B'  도 비교해보자.

     SELECT CASE WHEN 'A' > 'B' THEN 'TRUE' ELSE 'FALSE' END   FROM DUAL;

CASEWHEN'A'>'B'THEN'TRUE'ELSE'FALSE'END
FALSE


     SELECT CASE WHEN 'A' < 'B' THEN 'TRUE' ELSE 'FALSE' END   FROM DUAL;

CASEWHEN'A'<'B'THEN'TRUE'ELSE'FALSE'END
TRUE

     문자도 비교가 되는군.

     그럼, MIN(), MAX() 함수는 문자도 비교해서 보여주는 구나.

     여기서 VC1, VC2 모두 문자 데이터 타입이니, 문자로 비교해서 보여주면...

     결과를 다시 살펴보자.

VC1 VC2
5 7
8.5 11.3
10 20
15 25
10 11.3

     문자는 맨 앞자부터 비교하니 VC1 에서는 1로 시작하는게 10, 15 이고 이중 2번째 문자를

     비교하니 10 이 가장 작군.  VC2 의 11.3 도 마찬가지네.

     그럼, 여기서 MIN(), MAX() 함수는 원래 VC1, VC2 의 데이터 타입이 문자이니

     그대로 문자의 크고, 작음을 비교했구나....

     원래 문제로 돌아가 보자.

     문자 데이터 타입에 숫자를 넣을 수 있다고 해서 그렇게 하는게 맞는가?

     오라클이 내부적으로 문자를 숫자로 변환하므로 내부 연산이 필요해서 적지만 성능에

     악 영향을 미친다. 그리고 더 큰 문제는 앞의 테스트에서 처럼 MIN(), MAX() 같이

     예상치 못한 결과가 나올 수 있다.

     그러므로 문자는 문자 데이터 타입에, 숫자는 숫자 데이터 타입에 넣어야 한다.