Oracle

使用降序索引跨 Oracle 表創建一個保留鍵的視圖

  • May 26, 2020

我正在嘗試在兩個具有完全相同鍵結構的 Oracle 表之間創建一個可更新視圖。現有表由 ERP 系統創建,並且:

  • 沒有主鍵 - 只有唯一索引。
  • 所有欄位都是非空的,但複合索引欄位之一是降序的。

有什麼方法可以跨這兩個表創建可更新視圖?

所涉及的真實表包含大量數據並且被大量使用,因此對索引的任何更改/添加都需要進行大量的回歸測試,因此我需要將任何解決方案限制在視圖本身。

問題似乎與 Oracle 為降序的 KEY2 欄位創建單獨的基於復合函式的索引有關。我已經嘗試向視圖中添加一些提示,但在這裡超出了我的深度,並且真的不太清楚我在做什麼。

這是一個簡化的例子。如果我從兩個 KEY2 索引欄位中刪除“desc”,則最終更新有效 - 如果我將其保留在其中,則會失敗:“ORA-01779:無法修改映射到非鍵保留表的列”。

create table TEST_KEY_PRES_A (
  KEY1 varchar2(8) not null,
  KEY2 varchar2(8) not null,
  VAL1 smallint not null,
  VAL2 varchar2(8) not null
)
;

create unique index TEST_KEY_PRES_A_IDX
on TEST_KEY_PRES_A (KEY1, KEY2 desc)
;

insert into TEST_KEY_PRES_A values ('K11', 'K21', 1, 'V2-1');
insert into TEST_KEY_PRES_A values ('K15', 'K25', 5, 'V2-5');

create table TEST_KEY_PRES_B (
  KEY1 varchar2(8) not null,
  KEY2 varchar2(8) not null,
  VAL3 varchar2(8) not null
)
;

create unique index TEST_KEY_PRES_B_IDX
on TEST_KEY_PRES_B (KEY1, KEY2 desc)
;

insert into TEST_KEY_PRES_B values ('K11', 'K21', 'V3-1');
insert into TEST_KEY_PRES_B values ('K15', 'K25', 'V3-5');

create view TEST_KEY_PRES_VW (KEY1, KEY2, VAL1, VAL2, VAL3) AS
select pa.KEY1, pa.KEY2, pa.VAL1, pa.VAL2, pb.VAL3
from   TEST_KEY_PRES_A pa
join   TEST_KEY_PRES_B pb on pa.KEY1 = pb.KEY1 and pa.KEY2 = pb.KEY2
where  pa.VAL1 > 3
;

update TEST_KEY_PRES_VW
set    VAL2 = 'V2-5-X'
where  KEY1 = 'K15'
;

解決了

按照 Eduard 的建議使用 INSTEAD OF 觸發器:

create or replace trigger TEST_KEY_PRES_VW_UPD_TR
instead of update on TEST_KEY_PRES_VW
for each row
begin
   update TEST_KEY_PRES_A
   set    VAL1 = :new.VAL1, VAL2 = :new.VAL2
   where  KEY1 = :new.KEY1 and KEY2 = :new.KEY2;

   update TEST_KEY_PRES_B
   set    VAL3 = :new.VAL3
   where  KEY1 = :new.KEY1 and KEY2 = :new.KEY2;
end;

如果您不需要創建視圖,而只是使用連接進行更新,那麼我們可以使用帶有 MERGE 語句的解決方法。

merge into TEST_KEY_PRES_A pa 
using TEST_KEY_PRES_B pb
 on (pa.KEY1 = pb.KEY1 and pa.KEY2 = pb.KEY2 and pa.VAL1 > 3 and pa.KEY1 = 'K15')
when matched then update
  set VAL2 = 'V2-5-X';

引用自:https://dba.stackexchange.com/questions/267663