我们在Oracle数据库中的表上有一种奇怪的情况,其中删除列会导致更改另一列的默认值。这是场景。
我的表中有一些示例数据:
select * from SAMPLE_TABLE ;
ID BUSINESS_KEY
---------------------------------------- ---------------
e59bf31c-49a4-4638-bf6e-7d1be60f4dbb 1
c0dabf78-d9ca-4072-832e-aeb618c7ed14 2
我添加了 TYPE1 列,其中包含检查约束( TYPE1_VAL1 或 TYPE1_VAL2 )和默认值 TYPE1_VAL2 :
alter table SAMPLE_TABLE add TYPE1 varchar(10) default 'TYPE1_VAL2' not null check(TYPE1 in ('TYPE1_VAL1', 'TYPE1_VAL2'));
Table altered.
我看到默认值( TYPE1_VAL2 )已正确填写:
select * from SAMPLE_TABLE ;
ID BUSINESS_KEY TYPE1
---------------------------------------- --------------- ----------
e59bf31c-49a4-4638-bf6e-7d1be60f4dbb 1 TYPE1_VAL2
c0dabf78-d9ca-4072-832e-aeb618c7ed14 2 TYPE1_VAL2
我添加了另一个列TYPE2,其中包含另一个检查约束( TYPE2_VAL1 或 TYPE2_VAL2 )和默认值 TYPE2_VAL2 :
alter table SAMPLE_TABLE add TYPE2 varchar(15) default 'TYPE2_VAL2' not null check(TYPE2 in ('TYPE2_VAL1', 'TYPE2_VAL2'));
Table altered.
再次看到默认值( TYPE2_VAL2 )是正确的:
SYSTEM(SYSTEM) @ DB_USER > select * from SAMPLE_TABLE ;
ID BUSINESS_KEY TYPE1 TYPE2
---------------------------------------- --------------- ---------- ---------------
e59bf31c-49a4-4638-bf6e-7d1be60f4dbb 1 TYPE1_VAL2 TYPE2_VAL2
c0dabf78-d9ca-4072-832e-aeb618c7ed14 2 TYPE1_VAL2 TYPE2_VAL2
现在是奇怪的部分。当我删除第一列时,它似乎将删除列中的默认值应用到剩余列:
ALTER TABLE SAMPLE_TABLE DROP COLUMN TYPE1;
Table altered.
select * from SAMPLE_TABLE ;
ID BUSINESS_KEY TYPE2
---------------------------------------- --------------- ---------------
e59bf31c-49a4-4638-bf6e-7d1be60f4dbb 1 TYPE1_VAL2
c0dabf78-d9ca-4072-832e-aeb618c7ed14 2 TYPE1_VAL2
所以在 TYPE2 列包含 TYPE2_VAL2 之前,突然之后它包含 TYPE1_VAL2 。就好像已删除列的检查约束移动到此列。
这发生在我们运行Oracle Database 11g 11.2.0.4.0版的测试环境中 - 在Linux上运行64位。
在我们当地的CentOS / Oracle XE版本上,我们没有这个问题。
任何想法可能导致这种情况以及我们如何防止这种情况发生。这是设计/错误/我们的错误吗?
答案 0 :(得分:4)
这是一个Oracle错误。
通过向现有表格添加NOT NULL
约束和DEFAULT
值的列来触发它。
要快速添加列,Oracle 11g会将默认值存储在数据字典中。 Oracle称之为“添加列优化”。
这比将默认值写入每个表行要快。然后,查询引擎应该使用数据字典中的默认值替换表行中的任何NULL。不幸的是,有几个与此相关的错误。您的似乎是以下的实例:
17325413具有DEFAULT值和NOT NULL定义的删除列结束 将丢失的列数据击中磁盘导致损坏
您可以检查已添加的列如下:
select owner, object_name, name
from dba_objects, col$
where bitand(col$.PROPERTY,1073741824)=1073741824
and object_id=obj#;
在我们的案例中,我们被一个不同的错误所诱惑,该错误返回了SELECT FOR UPDATE
的错误结果。
我们设置参数_add_col_optim_enabled=FALSE
以关闭此“优化”。或者,您可以升级到稍后解决这些错误的Oracle版本。
升级或设置上述参数不会修复已损坏的现有表。您必须重新创建该表。