Максимальная точность, которую я могу явно указать для нового столбца, составляет 38
...
Если 38 - максимум, как я уменьшаю точность, устанавливая это число?
Это максимум, который вы можете объявить как ограничение p в NUMBER ( p , s ). Часто считается, что Oracle не допускает числа более 38 цифр, даже если они не ограничены, но это не совсем так. Даже если вы ограничиваете масштаб, вы можете иметь больше; например со столбцом типа данных INTEGER, который не имеет ограничения точности, но имеет масштаб 0.
Документация для типа данных NUMBER (12cR2) включает в себя:
Oracle гарантирует переносимость чисел с точностью до 20 цифр от 100 до 100, что эквивалентно 39 или 40 десятичным цифрам
С колонкой с неограниченной точностью вы можете иметь более 38 значащих цифр. Некоторые примеры таблиц для демонстрации:
create table t1 (num number);
create table t2 (num integer);
create table t3 (num number(38));
create table t4 (num number(38,0));
select table_name, column_name, data_type, data_length, data_precision, data_scale
from user_tab_columns
where table_name in ('T1', 'T2', 'T3', 'T4');
TABLE_NAME COLUMN_NAME DATA_TYPE DATA_LENGTH DATA_PRECISION DATA_SCALE
---------- ------------ --------- ----------- -------------- ----------
T1 NUM NUMBER 22
T2 NUM NUMBER 22 0
T3 NUM NUMBER 22 38 0
T4 NUM NUMBER 22 38 0
тогда это разрешено:
insert into t1 values (power(10, 39)+1);
как, собственно, это:
insert into t1 values (power(10, 40)+1);
1 row inserted.
Когда вы смотрите на данные, как указано в рабочем листе SQL Developer с numwidth
, установленным на 42, вы видите:
select num, length(to_char(num)) from t1;
NUM LENGTH(TO_CHAR(NUM))
------------------------------------------ ------------------------------------------
1000000000000000000000000000000000000001 40
10000000000000000000000000000000000000000 40
Первая строка имеет 40 значащих цифр, и точное значение сохраняется. (Вторая строка потеряла +1 от вставки, так как теперь она слишком велика для внутренней точности в приведенной выше цитате. Длина по-прежнему указывается как 40 без явной маски форматирования, что немного интересно. В противном случае эта строка не полезно ...)
Столбец INTEGER, который является НОМЕРОМ (, 0), допускает то же самое:
insert into t2 values (power(10, 39)+1);
1 row inserted.
select num, length(to_char(num)) from t2;
NUM LENGTH(TO_CHAR(NUM))
------------------------------------------ ------------------------------------------
1000000000000000000000000000000000000001 40
Но как только вы ограничите точность, которая больше не разрешена:
insert into t3 values (power(10, 39)+1);
ORA-01438: value larger than specified precision allowed for this column
insert into t3 values (power(10, 38)+1);
ORA-01438: value larger than specified precision allowed for this column
insert into t3 values (power(10, 37)+1);
1 row inserted.
select num, length(to_char(num)) from t3;
NUM LENGTH(TO_CHAR(NUM))
------------------------------------------ ------------------------------------------
10000000000000000000000000000000000001 38
Если вы также ограничите масштаб до нуля, он будет вести себя одинаково; вставка и запрос t4
дает те же результаты.
Итак, суть в том, что простой столбец NUMBER
равен , а не , как столбец NUMBER(38, 0)
, и ваш оператор alter
равен , фактически снижая теоретическую максимальную точность колонны. Oracle не проверяет фактические значения в столбце перед выдачей ORA-01440, поэтому не имеет значения, что ни одно из существующих значений фактически не превышает точность, которую вы пытаетесь указать, - он просто знает, что они могут .