Sql 为什么此Oracle DROP列会更改另一列的默认值?

Sql 为什么此Oracle DROP列会更改另一列的默认值?,sql,oracle,oracle11g,ddl,check-constraints,Sql,Oracle,Oracle11g,Ddl,Check Constraints,Oracle数据库中的一个表出现了一种奇怪的情况,删除一列会导致更改另一列的默认值。下面是一个场景 我的表格中有一些示例数据: select * from SAMPLE_TABLE ; ID BUSINESS_KEY ---------------------------------------- --------------- e59bf31c-49a4-4638-bf6e-7d1be60f4dbb

Oracle数据库中的一个表出现了一种奇怪的情况,删除一列会导致更改另一列的默认值。下面是一个场景

我的表格中有一些示例数据:

select * from SAMPLE_TABLE ;

ID                                       BUSINESS_KEY
---------------------------------------- ---------------
e59bf31c-49a4-4638-bf6e-7d1be60f4dbb                   1
c0dabf78-d9ca-4072-832e-aeb618c7ed14                   2
我添加列TYPE1,带有检查约束(TYPE1\u VAL1TYPE1\u VAL2)和默认值TYPE1\u VAL2

alter table SAMPLE_TABLE add TYPE1 varchar(10) default 'TYPE1_VAL2' not null check(TYPE1 in ('TYPE1_VAL1', 'TYPE1_VAL2'));

Table altered.
alter table SAMPLE_TABLE add TYPE2 varchar(15) default 'TYPE2_VAL2' not null check(TYPE2 in ('TYPE2_VAL1', 'TYPE2_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\u VAL1TYPE2\u VAL2)以及默认值TYPE2\u VAL2

alter table SAMPLE_TABLE add TYPE1 varchar(10) default 'TYPE1_VAL2' not null check(TYPE1 in ('TYPE1_VAL1', 'TYPE1_VAL2'));

Table altered.
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之后突然下降。这就好像删除的列的check约束移动到此列一样

这发生在我们的测试环境中,我们在Linux上运行Oracle Database 11g 11.2.0.4.0版-64位产品

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

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

这是Oracle的缺陷

通过向现有表中添加一个同时具有
notnull
约束和
DEFAULT
值的列来触发

为了快速添加列,Oracle 11g将默认值存储在数据字典中。Oracle称之为“添加列优化”

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

17325413具有默认值且非空定义的Drop列结束 丢失的列数据击中磁盘导致损坏

您可以按如下方式检查已添加的列:

 select owner, object_name, name 
 from dba_objects, col$
 where bitand(col$.PROPERTY,1073741824)=1073741824
 and object_id=obj#;
在我们的例子中,我们被另一个bug刺痛,该bug为
选择更新返回了不正确的结果

我们设置参数
\u add\u col\u optim\u enabled=FALSE
以关闭此“优化”。或者,您也可以升级到更高版本的Oracle,在该版本中,这些错误可以得到解决


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

闻起来您需要打开SR。这在Solaris上的11.2.0.4上对我有效。看起来像是一个非常特殊的bug。正如Luc M所说,您可能需要打开一个SR(另外,我不知道为什么有人投票结束这个问题——这对于这个网站来说是一个完全正确的问题。)这可能与默认值现在存储为元数据这一事实有关(虽然在中没有明确说明,但我认为这是隐含的)如果使用not null约束创建默认值。我的猜测是,您的版本中存在一个错误,在删除列时会弄乱元数据,使第二列指向第一列的默认值元数据。有趣的是,如果您将TYPE2的默认值设置为长度15(因为您将TYPE2定义为长度15,将TYPE1定义为长度10),然后放下TYPE2,看看Oracle是否尝试用TYPE2的默认值(太大)填充TYPE1……如果你得到一个ora-600,那么我肯定会说是一个bug;)