为什么这个 Oracle DROP COLUMN 会改变另一列的默认值?

Why does this Oracle DROP COLUMN alter the default value of another column?

我们在 Oracle 数据库中的 table 上遇到了一个奇怪的情况,其中删除一列会导致更改另一列的默认值。这是场景。

我有我的 table,里面有一些示例数据:

select * from SAMPLE_TABLE ;

ID                                       BUSINESS_KEY
---------------------------------------- ---------------
e59bf31c-49a4-4638-bf6e-7d1be60f4dbb                   1
c0dabf78-d9ca-4072-832e-aeb618c7ed14                   2

我添加带有检查约束的列 TYPE1TYPE1_VAL1TYPE1_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_VAL1TYPE2_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 数据库 11g 版本 11.2.0.4.0 - Linux.

上的 64 位生产

在我们本地的 CentOS/Oracle XE 版本上我们没有这个问题。

知道是什么导致了这种情况以及我们如何防止这种情况发生。这是设计使然/错误/我们的错误吗?

这是一个 Oracle 错误。

通过向现有 table.

添加具有 NOT NULL 约束和 DEFAULT 值的列来触发

为了快速添加列,Oracle 11g 将默认值存储在数据字典中。甲骨文称之为 "add column optimization".

这比将默认值写入每个 table 行要快。然后,查询引擎应该用数据字典中的默认值替换 table 行中的任何 NULL。不幸的是,有几个与此相关的错误。您的实例似乎是:

17325413 Drop column with DEFAULT value and NOT NULL definition ends up with dropped column data hitting disk leading to corruption

您可以像这样检查添加了哪些列:

 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来关闭这个"optimisation"。或者,您可以升级到解决了这些错误的更高版本的 Oracle。

升级或设置上述参数不会修复您现有的 table,它已损坏。您必须重新创建 table.