在不改变环境的情况下从表中删除列

问题描述:

我正在研究Oracle SQL数据库,数据库相当大。其中一个表格(150个表格中的一个)必须更改,因为它是多余的(它可以通过连接生成)。我被要求从这张表中删除一列,以摆脱冗余。问题是,现在我不得不在任何地方改变代码,在这个表上插入/更新/等(并且不要忘记约束!)。我认为“我可以做一个视图,做正确的连接”,所以它解决了所有选择的问题,但它不适用于插入,因为我正在更新2个表格......有没有办法解决这个问题?在不改变环境的情况下从表中删除列

我的目标是我的重命名原始表original_tableoriginal_table_smaller(少了一个列),并创建一个view(或者类似的视图)被称为original_table的作用就像原始表。

这可能吗?

+0

据我知道这是不可能做'insert','update'或在视图上删除。只允许“选择”。 – 2013-05-02 08:00:03

+0

是的,这是可能的,但插入/更新/删除的现有代码将失败(您无法在视图上插入/更新/删除行)。 – 2013-05-02 08:00:12

+0

@LinusCaldwell当然你可以制作可更新的视图,例如使用'而不是'触发器。 – 2013-05-02 08:01:45

由于您的视图将包含实际表格中不存在的一列,因此您需要使用instead of触发器才能使视图更新。

事情是这样的:

create table smaller_table 
(
    id integer not null primary key, 
    some_column varchar(20) 
); 

create view real_table 
as 
select id, 
     some_column, 
     null as old_column 
from smaller_table; 

现在你的旧代码将运行是这样的:

insert into real_table 
    (id, some_column, old_column) 
values 
    (1, 'foo', 'bar'); 

导致:

ORA-01733:虚拟列不允许这里

为了解决这个问题,你需要一个INSTEAD OF触发:

create or replace trigger comp_trigger 
    instead of insert on smaller_table 
begin 
    insert into old_table 
    (id, some_column) 
    values 
    (:new.id, :new.some_column); 
end; 
/

现在的“old_column”的值将被忽略。你也需要类似的更新。

如果您的视图包含连接,那么您也可以在触发器中处理该情况。简单地做一个更新/根据数据,以两个不同的表

欲了解更多细节和例子插入,请参阅手册
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#i1006376

+0

INSTEAD OF触发器正是我所期待的。谢谢! – 2013-05-02 08:42:38

可以在视图上插入/更新。 您可能想要检查USER_UPDATABLE_COLUMNS可以插入到视图中的哪些列。

检查与此查询:

select * from user_updatable_columns where table_name = 'VIEW_NAME'; 

甲骨文使视图都可以更新的两种不同的方式: -

  1. 的观点是“重点保障”相对于您要更新什么。这意味着基础表的主键在视图中,并且该行在视图中只出现一次。这意味着Oracle可以确切地确定要更新哪个基础表行。或者您可以编写而不是触发器。