MySQL은 숫자 표현식을 평가하는 과정에서 오버플로우(overflow)가 발생하면 기본적으로 에러를 반환합니다. 예를 들어, 부호 있는 BIGINT의 최댓값은 9223372036854775807이므로, 이 값에 1을 더하는 다음과 같은 연산은 에러를 발생시킵니다.
mysql> Select 9223372036854775807 + 1; ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807+1)'
MySQL은 이러한 오버플로우 문제를 크게 두 가지 방법으로 우회하여 처리할 수 있습니다.
1. 값을 UNSIGNED로 변환하기
첫 번째 방법은 값을 부호 없는 정수(UNSIGNED)로 변환하는 것입니다. CAST 함수를 사용하면 부호 비트까지 계산 범위에 포함시킬 수 있어, 동일한 자릿수에서 더 넓은 양수 범위를 표현할 수 있습니다.
mysql> Select CAST(9223372036854775807 AS UNSIGNED) +1; +------------------------------------------+ | CAST(9223372036854775807 AS UNSIGNED) +1 | +------------------------------------------+ | 9223372036854775808 | +------------------------------------------+ 1 row in set (0.07 sec)
위 예제에서 볼 수 있듯이, 값이 UNSIGNED로 변환되면 최대 허용 범위가 늘어나기 때문에 에러 없이 정상적으로 결과 9223372036854775808이 출력됩니다.
2. 정확한 값 산술(Exact-Value Arithmetic) 사용하기
두 번째 방법은 DECIMAL 타입을 활용한 정확한 값 산술입니다. MySQL에서 오버플로우 발생 여부는 피연산자의 데이터 타입과 그 범위에 따라 결정됩니다. 따라서 정수 리터럴 대신 소수점을 붙인 DECIMAL 값으로 표현식을 작성하면, 정수형의 범위 제한을 받지 않고 연산을 수행할 수 있습니다.
mysql> Select 9223372036854775807.0 + 1; +---------------------------+ | 9223372036854775807.0 + 1 | +---------------------------+ | 9223372036854775808.0 | +---------------------------+ 1 row in set (0.01 sec)
DECIMAL 값에 소수점(.0)만 추가했을 뿐인데도 MySQL은 해당 연산을 정확한 값 산술로 처리하여, BIGINT 범위를 초과하는 결과를 에러 없이 반환합니다.
정리
BIGINT 최댓값을 초과하는 연산에서 오버플로우 에러가 발생한다면, CAST(... AS UNSIGNED)로 부호 없는 정수로 변환하거나, DECIMAL 값을 사용해 정확한 값 산술로 처리하는 두 가지 방법을 상황에 맞게 활용하면 됩니다.