Database ORA-01440在包含数据的空精度列上设置精度为38时出错?
在我使用的Oracle数据库中,许多数字列最初是以NULL精度创建的。我的理解是,这些列具有隐含的最大精度。(根据Oracle:“如果未指定精度,则列存储给定的值。”)它们当前包含数据 我可以为新列显式指定的最大精度为38。但是,当我试图修改这些现有列以设置此显式精度时,Oracle会抛出一个错误:Database ORA-01440在包含数据的空精度列上设置精度为38时出错?,database,oracle,Database,Oracle,在我使用的Oracle数据库中,许多数字列最初是以NULL精度创建的。我的理解是,这些列具有隐含的最大精度。(根据Oracle:“如果未指定精度,则列存储给定的值。”)它们当前包含数据 我可以为新列显式指定的最大精度为38。但是,当我试图修改这些现有列以设置此显式精度时,Oracle会抛出一个错误: ALTER TABLE test_table MODIFY column NUMBER(38); ORA-01440:要修改的列必须为空,以降低精度或比例 如果38是最大值,我如何通过设置该数字来
ALTER TABLE test_table
MODIFY column NUMBER(38);
ORA-01440:要修改的列必须为空,以降低精度或比例
如果38是最大值,我如何通过设置该数字来降低精度
与modify语句相比,更改此类型的其他方法(例如,创建新列、复制数据、删除/重新添加约束等)相当费劲
我可以为新列显式指定的最大精度为38
如果38是最大值,我如何通过设置该数字来降低精度
这是您可以声明的最大值,作为数量(p,s)中的p约束。人们经常认为这意味着Oracle不允许超过38位的数字,即使是不受限制的数字,但事实并非如此。即使只约束比例,也可以获得更多;e、 g.数据类型为INTEGER的列,该列没有精度约束,但刻度为0
(12cR2)包括:
Oracle保证数字的可移植性,精度高达20位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,没有显式的格式掩码,这有点有趣。否则该行没有帮助…)
整数列(即数字(,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之前不会检查列中的实际值,因此,现有值中没有一个实际超过您试图指定的精度并不重要,它只知道它们可能会超过精度。您引用Oracle的说法是正确的
如果未指定精度,该列将按给定值存储值
及
我可以为新列显式指定的最大精度为38
但是并不意味着Oracle可以存储的最大精度是38
这里是一个简单的示例-假设您的列是在没有精度
和比例
为零的情况下定义的:
create table MyTable
(num1 NUMBER(*,0)
);
您可以在Discitionary表中对此进行验证
select COLUMN_NAME, DATA_PRECISION, DATA_SCALE
from user_tab_columns where table_name = 'MYTABLE';
COLUMN_NAME DATA_PRECISION DATA_SCALE
------------------------------ -------------- ----------
NUM1 0
现在让我们填写一些数据
insert into MyTable(num1) values(sqrt(2)*power(10,38) );
实际上,您的精度为39(我在Windows上,这种行为可能依赖于操作系统,但Oracle必须考虑到这种可能性)
因此,您不能简单地用38的最大允许精度覆盖精度
——这可能意味着实际的降低
类似的情况是,如果列定义为而没有比例和精度
create table MyTable
(num1 NUMBER
);
select COLUMN_NAME, DATA_PRECISION, DATA_SCALE
from user_tab_columns where table_name = 'MYTABLE';
COLUMN_NAME DATA_PRECISION DATA_SCALE
------------------------------ -------------- ----------
NUM1
与流行的观点相反,在这种情况下,不成立:
如果未指定比例,则比例为零
相反,刻度可能高于38,如下例所示:
insert into MyTable(num1) values(sqrt(2)/10);
select num1 from MyTable;
0,141421356237309504880168872420969807857
图中有39位小数
摘要
如果不重新组织表格,则无法设置精度。编号(38,6)
?当前列是否有此编号类型的刻度?如果不指定一个刻度,则您将刻度设置为0,这可能是一种减少。事实上,尽管该列没有刻度。这是一个很好的答案,谢谢。“如果不重新组织表格,就无法设置精度。”-->不幸的是,这正是我试图避免的。这是一个与上面的答案一样好的答案,我希望我能选择两者。非常感谢。
insert into MyTable(num1) values(sqrt(2)/10);
select num1 from MyTable;
0,141421356237309504880168872420969807857