2011-05-05 18 views
18

我有一個刪除標誌一個簡單的表(記錄應在此列中更新,而不是刪除):ORA-38104:在ON子句中引用的列不能更新

create table PSEUDODELETETABLE 
(
    ID  NUMBER(8) not null, -- PKEY 
    NAME  VARCHAR2(50) not null, 
    ISDELETED NUMBER(1) default 0 not null 
) 

當插入新記錄我必須檢查,是否已經有一個匹配主鍵但ISDELETED = 1的記錄。在這種情況下,我必須將ISDELETED更改爲0並更新其他列。所以我使用以下合併-聲明:

merge into ET.PSEUDODELETETABLE TARGET 
using (select 1 as ID, 'Horst' as NAME from sys.dual) SOURCE 
on (TARGET.ISDELETED = 1 and SOURCE.ID = TARGET.ID) 
when matched then 
    update set ISDELETED = 0, NAME = SOURCE.NAME 
when not matched then 
    insert values (SOURCE.ID, SOURCE.NAME, 0); 

上的SQL-服務器它的偉大工程,但Oracle說:

ORA-38104: Columns referenced in the ON Clause cannot be updated: TARGET.ISDELETED 

如果沒有與IDELETED = 0匹配的記錄,我想主鍵違規作爲例外,這就是爲什麼我無法將「on-clause」中的「TARGET.ISDELETED = 1」移動到update-statement。

+0

我在SQL Server(和可恥的是甲骨文:) – onedaywhen 2011-05-06 10:47:05

+0

感謝上偉大的作品確認,我已經改變了命令,如下所示: '開始 更新ET.PSEUDODELETETETABLE set ISDELETED = 0,NAME ='Horst' 其中ISDELETED = 1且ID = 1;如果(sql%rowcount = 0),則 插入到ET.PSEUDODELETETABLE值(1,'Horst',0); end if; end;' – FreeAndNil 2011-05-06 13:47:09

回答

3

我懷疑你在這種情況下最好用射擊再看看算法。

根據你所期望的是更頻繁的情況下,無論是:

  • 更新,如果沒有行被更新,插入;或
  • 插入,如果有密鑰違規,更新。
+0

+1,好多了,因爲你不能做OP想要做的事情;-)至少,不是沒有一些中間臨時表,如在這裏發佈的答案:http://asktom.oracle。 com/pls/asktom/f?p = 100:11:0 :::: P11_QUESTION_ID:556373000346392260 – DCookie 2011-05-05 20:34:15

34

相反的是接受答覆,其實就是拉這一關的方式:移動違規位了ON子句,進入更新語句的WHERE子句:

merge into ET.PSEUDODELETETABLE TARGET 
using (select 1 as ID, 'Horst' as NAME from sys.dual) SOURCE 
on (SOURCE.ID = TARGET.ID) 
when matched then 
    update 
     set ISDELETED = 0, 
     NAME = SOURCE.NAME 
    where TARGET.ISDELETED = 1 -- Magic! 
when not matched then 
    insert 
     values (SOURCE.ID, SOURCE.NAME, 0); 
+1

這不適用於每種情況。在ISDELETED可以有3個不同值的情況下,它不做更新,如果ISDELETED獲得第三個可能的值和相同的ID,你將跳過你的插入。 例如,如果ISDELETED = 2具有相同的ID。你將會更新0,你會跳過你的插入。 – 2016-06-23 17:39:29

1

我們需要考慮以下情況爲好,

如果存在與IDELETED = 0匹配的記錄,我想主鍵衝突作爲例外,這就是爲什麼我不能移動「TARGET.ISDELETED = 1「從on-clause到update-statement。

所以確切的解決方案如下,

begin 
    update ET.PSEUDODELETETABLE set ISDELETED = 0, NAME = 'Horst' 
    where ISDELETED = 1 and ID = 1; 
    if (sql%rowcount = 0) then 
     insert into ET.PSEUDODELETETABLE values (1, 'Horst', 0); 
    end if; 
end; 
相關問題