Решение проблемы потери точности для колонок Oracle NUMBER без указания precision

Описание проблемы

При выгрузке данных из таблиц Oracle, если колонка объявлена как NUMBER без указания precision и scale (то есть просто NUMBER, а не NUMBER(p,s)), может возникнуть проблема с потерей точности.

В этом случае драйвер ORACLE интерпретирует тип NUMBER как DOUBLE и из-за особенностей хранения чисел с плавающей точкой происходит округление после примерно 15-17 значащего разряда. В результате выгруженные данные могут не совпадать с исходными значениями, хранящимися в Oracle.

Пример
Декларация в Oracle Распознанный тип Результат
NUMBER DOUBLE Округление после 15 знака: потеря точности
NUMBER(38,0) DECIMAL(38,0) Точное значение сохраняется


В Oracle объявление колонки как NUMBER без указания (p,s) подразумевает, что данные должны трактоваться как есть, без автоматического округления. Однако тип DOUBLE — это тип с плавающей точкой, который не способен хранить большие целые числа или значения с высокой точностью без округления.

Причина проблемы

По умолчанию Oracle ODBC-драйвер (а также некоторые ETL-коннекторы) обрабатывают тип NUMBER без указания precision как DOUBLE. Это приводит к автоматическому преобразованию в число с плавающей точкой и, соответственно, к округлению значений, если число содержит более 15-17 значащих цифр;

колонка хранит большие целые или высокоточные значения.

Решение

Чтобы сохранить полную точность для колонок NUMBER, объявленных без (p,s), необходимо включить в настройках драйвера опцию
Bind NUMBER as FLOAT:

ODBC%20driver%20config

При активированной опции драйвер связывает значения NUMBER как FLOAT, что позволяет считать и обрабатывать данные без округления, полностью соответствующие источнику.

Поведение после включения опции
Декларация в Oracle Распознанный тип Результат
NUMBER FLOAT Точность сохраняется, округления нет
NUMBER(38,0) DECIMAL(38,0) Без изменений (точное представление сохраняется)


Выводы:
Сценарий Поведение по умолчанию При включённой Bind NUMBER as FLOAT
NUMBER без (p,s) Интерпретируется как DOUBLE: округление после 15 цифры Интерпретируется как FLOAT: без округления
NUMBER(p,s) Интерпретируется как DECIMAL(p,s) Без изменений


Рекомендации

Если в вашей схеме Oracle присутствуют колонки, объявленные как NUMBER без указания precision и scale и важно сохранить точные значения (например, для идентификаторов, финансовых данных или ключей), рекомендуется включить опцию драйвера Bind NUMBER as FLOAT.

Это обеспечит сохранение точности числовых данных и предотвратит расхождения между исходными и выгруженными значениями.


Если у вас есть другие вопросы, пожалуйста, свяжитесь с нами: support@convertum.ru