Declare @a numeric(25, 10)
Declare @b numeric(25, 10)
Declare @c numeric(25, 10)
Declare @Result numeric(25, 10)
Set @a = 12.34
Set @b = 5.0
Set @c = 0.0000124
Set @Result = @a * @b * @c
Select @Result as Result
위의 쿼리를 돌렸을때 값은 0.0007650000 이렇게 나옵니다
근데 실제로 윈도우 계산기로 계산을 해보면 0.00076508 나옵니다.
이게 왜 틀린지 잘 모르겠네요 분명 소수점 10자리 까지 라고 선언을 했는데 말이지요
도움 부탁 드리겠습니다. ㅜㅡ
Comment 8
-
catchv
2013.08.16 09:51
-
minsouk
2013.08.16 22:20
숫자의 곱 나누기 문자열 더하기는 더했을때 초과 할 수 있고 거기에 따른 제약이 따릅니다.
예를들면 0.01 * 0.01 = 0.0001, select cast(.0000009 as numeric(38,10)) * cast(1.0 as numeric(38,10)) = 0.000001
이렇게 나올 수 있는데요, 이것은 아래 BOL 을 참고해 제한이 생기면
어떻게 프로그램 되어 있는지 알고 있는게 좋을듯 합니다. 문자열도 비슷한거 많잖아요~
http://technet.microsoft.com/en-us/library/ms190476.aspx
http://sqlsql.tistory.com/23 참고해 보세요~
-
맨즈밤
2013.08.18 17:45
minsouk 님께서 올려주신 http://technet.microsoft.com/en-us/library/ms190476.aspx 의 하단에 보면
e1 * e2
p1 + p2 + 1
s1 + s2
이런 공식이 있는데요.
CREATE TABLE TEST
( A numeric(8, 3) ,
B numeric(8, 3) ,
C numeric(8, 3) ,
D AS (A*B*C) )
GO
SP_HELP TESTD의 자료형의 크기는 전체크기 : (p1 + p2 + 1)+p3+1 에의해 26 자리
D의 소수점 크기 : s1+s2+s3 에 의해 9자리가 나옵니다.
그런데 문제는 공식으로 산출된 자료형의 크기값이 numeric 최대값인 38을 넘어 갈때가 문제인데요. 실제 계산값에 상관없이 정의된 자료형이 넘어가면 오버플로가 됩니다. 위 질문에서 남겨주신 계산식에서 SET NUMERIC_ROUNDABORT ON 해보면 (25,10) 이 넘지
않았음에도 오버플로 메시지가 뜹니다.
여튼 이런경우에 SQL 내부적인 어떤 공식에 의해서 컬럼 크기가 결정되는듯 합니다. 가령
CREATE TABLE TEST
( A numeric(25, 10) ,
B numeric(25, 10) ,
C numeric(25, 10) ,
D AS (A*B*C) )
GO
SP_HELP TEST
이와 같이 만들경우 D의 자료형은 (38 ,6)으로 나오게 되고, 좀 바꿔서CREATE TABLE TEST
( A numeric(25, 20) ,
B numeric(25, 20) ,
C numeric(25, 20) ,
D AS (A*B*C) )
GO
SP_HELP TEST이럴경우 D는 (38,21)로 나오게 됩니다.
전체자리수와 소수점 자릿수, 계산에 포함된 컬럼의 갯수등을 조합해서 저런 크기가 나오는듯 합니다.
저런 상황일때의 공식을 찾아봤는데, 못찾겠더라구요.
-
minsouk
2013.08.19 09:07
네 정확한 rule을 찾으면 공유 하도록 하겠습니다.
소중한 답변 감사합니다.
-
수봉
2013.08.19 08:59
감사합니다 뒤의
수치를 조정해서 일단 해결은 했습니다
답변주신 모든분 복받으세요 ^^
-
minsouk
2013.08.19 14:51
전체 자릿수가 38을 넘고 정수 자릿수가 38을 안넘으면 전체 자릿수 38, 소수점 자리수는 38-((p1-s1)+(p2-s2)+1)
전체 자릿수가 38을 넘고 정수 자릿수가 38을 넘으면 전체 자릿수 38, 소수점 자릿수가 s1+s2 > 6이면 6 아니면 s1+s2
-
맨즈밤
2013.08.19 14:58
와~ 대단하십니다. 좋은 정보 공유 감사드립니다.~~~~~
-
minsouk
2013.08.19 15:01
아는 형님(안인옥)이 알려줬어요~
혹시 naver japan 라인 메신저 그룹채팅인 SQLTAG dba 그룹에 가입하고 싶으면 minsouk1 친구 추가하고 연락 주세요 dba 36명이 라이브로 붙어있어요~
신기하네요~~!!!
테스트 해보다가 찾은 해결책(?)은
전체 자릿수 - 소수 자릿수 >= 10 이상이면 말씀하신 것 처럼 동작을 하네요.
numeric(25, 16) 은 9차이니깐 문제 없는데 numeric(25,15이하) 은 10 차이가 나서 문제가 발생하네요.
numeric(19이하, 10) 은 9 차이니깐 문제 없는데 numeric(20이상,10)은 10 차이가 나서 문제가 발생하네요.
아마도 내부적으로 저장할때 정밀도 문제가 있는 것 같은데...
MS SQL 부동소수점 문제로 float이나 double을 안쓰고 deciaml을 썼는데 이것도 조심해야 겠네요...^^;