우리는 프로그래밍 할때 숫자를 BYTE 단위로 나누어서 쓰는 것을 즐겨 사용하곤 했었습니다.
int _tmain(int argc, _TCHAR* argv[])
{
  int nValue = 65535;
 
  int nLowValue = LOBYTE( nValue );
  int nHighValue = HIBYTE( nValue );
 
  cout << "nLowValue : " << nLowValue << endl;
  cout << "nHighValue : " << nHighValue << endl;
 
  return 0;
}

C++ 코딩에서는 위와 같이 매크로를 이용해서 BYTE 단위로 쪼개기도 하고,
int _tmain(int argc, _TCHAR* argv[])
{
  int nValue = 65535;
 
  int nLowValue = nValue & 0xFF;
  int nHighValue = (nValue >> 8) & 0xFF;
 
  cout << "nLowValue : " << nLowValue << endl;
  cout << "nHighValue : " << nHighValue << endl;
 
  return 0;
}

위와 같이 쉬프트 연산자와 & | 연산자를 이용하기도 하였습니다.

그러나 DB의 select 문에서는 위와 같은 방식을 사용할 수 없습니다.
SELECT (256 * 256)

위의 결과는 65535가 정상적으로 출력됩니다. 그럼 문제가 되는 구문을 살펴 보겠습니다.

SELECT (256 * 256 * 256 * 256)

이 구문은 논리적으로 오류가 없어 보입니다. 적어도 C++ 관점에서 본다면 그렇지요.

하지만, 문제점이 있습니다. DB는 기본적으로 select에 대한 계산식은 명시적으로 지정하지 않으면 int 연산으로 casting 하게 됩니다.

따라서 이와 같은 메시지가 나오게 되었습니다.  
서버: 메시지 8115, 수준 16, 상태 2, 줄 1
expression을() 데이터 형식 int()로 변환하는 중 산술 오버플로 오류가 발생했습니다.

그렇다면 어떻게 해결하면 될까요? 답은 간단합니다.
SELECT cast(256 AS bigint) * cast(256 AS bigint) * cast(256 AS bigint) * cast(256 AS bigint)

오버플로우가 발생하지 않도록 더 큰 자료형인 bigint로 캐스팅해서 연산해주면 됩니다.

저런 문제점이 발생한 배경은 bigint 자료형을 HILONG, LOLONG으로 나누고 싶었는데, 256을 4번 곱한 값으로 나누기 연산을 수행했을때, 위와 같은 문제점이 발생하였습니다.

이 문제에 대한 해결책을 알려주신 최선호(약올라)님에게 감사의 말씀을 드립니다.

-- 4번 곱하기가 눈에 거슬리시는 분들을 위한 팁
SELECT power( cast(256 AS bigint), 4)
 
2008/02/19 01:17 2008/02/19 01:17

글 걸기 주소 : 이 글에는 트랙백을 보낼 수 없습니다

덧글을 달아 주세요