这似乎是预期的行为;来自 MOS 文档 ID 1068820.1:
在 11g 中,如果兼容设置为 11.1 或更高版本,并且表是使用“为所有 OLTP 压缩”选项创建的,则允许从压缩表中删除列,但即使在这种情况下,也没有真正的删除,但在数据库内部设置列 UNUSED 以避免长时间运行的解压缩和重新压缩操作。
另见文档 1223705.1、2171802.1 等。真正删除该列的唯一方法似乎是解压缩并重新压缩,如文档 1987500.1 中所示,但这是上面引用中所避免的。
似乎没有任何方法可以得到您期望的错误。
我认为最接近的方法是使用 DDL 触发器:
create or replace trigger radu_trigger
before alter
on schema
declare
l_compress_for user_tables.compress_for%type;
begin
select max(compress_for) into l_compress_for
from user_tables
where ora_dict_obj_type = 'TABLE' and table_name = ora_dict_obj_name;
if l_compress_for is null or l_compress_for != 'OLTP' then
return;
end if;
for r in (
select column_name from user_tab_columns
where table_name = ora_dict_obj_name
)
loop
if ora_is_drop_column(r.column_name) then
raise_application_error(-20001,
'Do not drop columns from an OLTP-compressed table');
end if;
end loop;
end radu_trigger;
/
然后,当您尝试在任何 OLTP 压缩表中删除列时 - 在该架构中 - 您将收到错误:
alter table test_radu_a drop (col2);
alter table test_radu_a drop (col2)
Error report -
ORA-00604: error occurred at recursive SQL level 1
ORA-20001: Do not drop columns from an OLTP-compressed table
ORA-06512: at line 18
...
如果您不想检查所有压缩表,当然可以查找特定的 ora_dict_obj_name 值。
你可以模仿真正的例外:
create or replace trigger radu_trigger
before alter
on schema
declare
l_compress_for user_tables.compress_for%type;
l_exception exception;
pragma exception_init (l_exception, -39726);
begin
...
loop
if ora_is_drop_column(r.column_name) then
raise l_exception;
end if;
end loop;
end radu_trigger;
/
alter table test_radu_a drop (col2);
Error report -
ORA-00604: error occurred at recursive SQL level 1
ORA-39726: unsupported add/drop column operation on compressed tables
ORA-06512: at line 20
...
但我认为这会令人困惑,因为该消息不是真的。提出您自己的定制异常可能更安全、更清洁。