为什么这个 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
我添加带有检查约束的列 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 数据库 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.
我们在 Oracle 数据库中的 table 上遇到了一个奇怪的情况,其中删除一列会导致更改另一列的默认值。这是场景。
我有我的 table,里面有一些示例数据:
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 数据库 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.