2015-09-18 24 views
0

我做了如下的觸發器。 test_suc_func總是返回varchar2「00」。Oracle 11g - 想知道當前行信息,尤其是PK

create or replace procedure call_func (v_a_id IN NUMBER) 
is 
begin 
update A_TBL set created = test_suc_func() where a_id = v_a_id; 
end; 


CREATE OR REPLACE TRIGGER a_trigger 
    AFTER 
    INSERT ON A_TBL 
    -- FOR EACH ROW  
BEGIN 
    call_func(a_seq.currVal); 
exception 
    when others then 
    update A_TBL set rc='99' 
    where a_id = a_id; 
END; 

我期待這個PLSQL執行如下。

  1. 當數據插入到A_TBL時,它調用一個函數。
  2. 當它失敗時,它更新該COLUMN。

問題是當我在exception語句中寫道時,更新了A_TBL中的所有行。

由於A_TBL的PK是序列,我可以用a_seq.currVal得到,但正如你所看到的,在where語句中不能使用序列。

問:如何在JavaScript中引用當前行數據,如this關鍵字?

我試過:new:old,但它在sqldeveloper中彈出一個奇怪的窗口。謝謝:d BB

=================== 2015年09 18

我編輯的職位,因爲我得到了一個錯誤。部分a_seq改爲a_id s。

+0

您不能在觸發了觸發器的表上運行'UPDATE'語句。你不需要它。 ':new.created:= test_suc_func();'是你所需要的觸發器 –

+0

@a_horse_with_no_name這段代碼是簡單的版本。實際上,它會調用遠程數據庫中的一個函數。 - 我沒有得到你的第一個陳述。我提供的代碼實際上是作品。問題是它更新所有行,因爲我寫了我的where子句,比如'a_id = a_id'。我想寫的東西就像'a_id = this.a_id'或'a_id = a_seq.currVal'。無論如何感謝b –

+0

在一個語句級別觸發器中,不存在「當前行」這樣的事情,因爲它是針對_statement_而不是針對每一行觸發的。聲明可能影響了數百萬行。 –

回答

0

據我所知,你需要修改插入記錄的列。
對於這種情況,您不需要觸發器中的更新語句。
您只需要BEFORE INSERT觸發器與FOR EACH ROW選項。
在這種情況下,您可以爲 :new.created:new.rc分配新值,並將它們插入到createdrc列中。
事情是這樣的:

CREATE OR REPLACE TRIGGER a_trigger 
    BEFORE 
    INSERT ON A_TBL 
    FOR EACH ROW  
BEGIN 
    :new.created = test_suc_func(); 
exception 
    when others then 
    :new.rc = '99'; 
END; 

您不能修改,新的變量AFTER觸發和不FOR EACH ROW選項不能訪問它們。你也不能在同一個表上觸發FOR EACH ROW的某個表上調用DML(插入/更新/刪除)(表是變異的)。

+0

感謝您的回答。但是,在我的情況下,必須在插入後更新。在這個項目中,先插入我的數據庫表,然後再調用返回響應代碼的遠程函數。收到來自遠程的響應代碼後,更新原始行(已插入)。 –

+0

有兩種解決此任務的方法: 1)將a_tbl.rowtype傳遞給你的函數,或者只是將你需要的列的列表(在這種情況下,你不需要在你的函數中查詢這行)使用BEFORE觸發器)。然後使用:new。觸發器中的變量設置從函數傳遞的新值。 (不要在觸發器或函數中使用UPDATE) 2)從觸發器運行作業,它將在插入提交後啓動,然後函數需要更新此行。 (但是在這種情況下,在函數更新此行之前,在提交之後會有間隙,並且在未定義這兩列時提交結果) –

0

我相信有比這更好的方法。但是我發現了一條彎路。

CREATE OR REPLACE TRIGGER a_trigger 
    AFTER 
    INSERT ON A_TBL 
    -- FOR EACH ROW  
DECLARE 
    tmp_id number; 
BEGIN 
    select a_seq.currVal into tmp_id from dual; 
    call_func(tmp_id); 
exception 
    when others then 
    update A_TBL set rc='99' 
    where a_id = tmp_id; 
END; 

我已經在觸發器中聲明瞭一個臨時變量。 並參考。當我失敗時,現在只更新當前行。

我仍然在爲這個問題尋找更高效,更聰明的答案。謝謝

+0

如果插入了多行,這不會起作用。我仍然不明白爲什麼你不能(或不想)使用行級觸發器並直接賦值':new'值 –

+0

@a_horse_with_no_name我是PLSQL的新手,但是有沒有任何情況會插入多行立刻?我假設在插入語句中,目標一次只有一條記錄。我會檢查我可以在事件發生後使用行級觸發器。 –