【问题标题】:Oracle drop column from compressed table - behind the scenes "set unused"Oracle 从压缩表中删除列 - 在幕后“设置未使用”
【发布时间】:2017-07-10 16:34:51
【问题描述】:

使用 Oracle 11.2.0.4.0 并尝试从多个 OLTP 压缩表中删除列,期望得到 ORA-39726: unsupported add/drop column operation on compressed tables。但是,它运行没有错误,但未使用列

我想知道是否可以避免这种行为 - 我想得到错误,以避免混淆(人们在不知情的情况下将未使用的列到处乱放)。

我找不到对此的参考,需要提高我的搜索技能。在我只看到的文档中:

您可以从使用 COMPRESS BASIC 的表中设置未使用的列,但是 您不能删除该列。但是,该条款的所有条款 drop_column_clause 对于使用 COMPRESS FOR OLTP 的表有效。 有关更多信息,请参阅 table_compression 的语义。 http://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_3001.htm#i2103683

请问您知道任何配置它以引发错误的方法吗? 场景:

create table test_radu_a(col1 number, col2 number) compress for oltp;
alter table test_radu_a drop (col2);
select * from user_unused_col_tabs where table_name = 'TEST_RADU_A';

【问题讨论】:

    标签: oracle compression


    【解决方案1】:

    这似乎是预期的行为;来自 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
    ...
    

    但我认为这会令人困惑,因为该消息不是真的。提出您自己的定制异常可能更安全、更清洁。

    【讨论】:

      猜你喜欢
      • 2011-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-21
      • 2017-11-09
      • 2016-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多