2016-02-25 50 views
2

我試圖創建一個Oracle觸發器,該觸發器基於觸發器中運行的select語句設置表B上列的值。Oracle觸發器 - 基於表A的條件更新表B

我希望能夠在執行表A上的插入後,基於select語句將表B'is_active'列的值設置爲'N'。

我的查詢如下:

CREATE OR REPLACE TRIGGER INACTIVE_STATE 
AFTER INSERT ON 
COMMENTS 
FOR EACH ROW 
DECLARE 
    inactive_id number; 
BEGIN 
    SELECT distinct b.id 
    into inactive_id 
    from comments a, 
      modules b 
    where a.module_name=b.name 
    and  a.type_id='FUNCTIONAL' 
    and  a.module_id=b.id; 
update modules 
set is_active='N' 
where ID=:inactive_id 
END INACTIVE_STATE; 
/

當我嘗試和complpile這個觸發,我得到以下錯誤:

Error(15,1): PL/SQL: SQL Statement ignored 
Error(17,10): PLS-00049: bad bind variable 'INACTIVE_ID' 
Error(17,15): PL/SQL: ORA-00933: SQL command not properly ended 
Error(19,1): PLS-00103: Encountered the symbol "/" when expecting one of the following:  (begin case declare end exception exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge 

看來它不喜歡的更新語句,或該過程中不會分析綁定變量。

如果我將這些語句分成2個命令(使用var來處理綁定變量:inactive_id),它將按預期工作。

VAR INACTIVE_ID number 
begin 
    select distinct b.id into :INACTIVE_ID 
    from comments a, 
      modules b 
    where a.module_name=b.name 
    and  a.type_id='FUNCTIONAL' 
    and  a.module_id=b.id; 
    end; 
    /

PL/SQL procedure successfully completed. 

SQL> 
SQL> update modules 
    set is_active='N' 
    where ID=:INACTIVE_ID 
    /

    1 row updated. 

任何想法,我可能會忽略?

+4

where子句應該是'觸發器的其中ID = inactive_id' - 沒有冒號。 –

+0

謝謝Tony,tigger編譯成功!但是,執行我的更新語句時,我得到以下:表COMMENTS是變異,觸發器/函數可能不會看到它 - 任何想法我如何處理這個? – Huskie69

+2

首先,select語句的目的是什麼?它是否真的應該查看所有評論,或者您剛剛插入的這個特定評論?如果所有評論你應該能夠刪除'FOR EACH ROW'並且避免突變問題。 –

回答

1

正如託尼·安德魯斯在原崗位的評論中指出。

正確的代碼應該是:

CREATE OR REPLACE TRIGGER INACTIVE_STATE 
AFTER INSERT ON 
COMMENTS 
DECLARE 
    inactive_id number; 
BEGIN 
    SELECT distinct b.id 
    into inactive_id 
    from comments a, 
      modules b 
    where a.module_name=b.name 
    and  a.type_id='FUNCTIONAL' 
    and  a.module_id=b.id; 
update modules 
set is_active='N' 
where ID=inactive_id 
END INACTIVE_STATE; 
/
-2

嘗試使用,我用冒號正確的where子句中的「inactive_id」變量之前

PRAGMA AUTONOMOUS_TRANSACTION; 

之前開始

+0

千萬別這麼做! –

+0

如果觸發器具有DML語句並且您想提交事務;那麼沒有設置雜注自治,它不會允許你這樣做。基本上,沒有硬性規定。是否使用編注自主或不完全取決於要求。 –

+0

好吧,「99%的時間,不要那樣做」!我可以想到的唯一有效的情況是,如果您出於某種原因想要記錄觸發觸發器的操作,即使您然後回滾了主事務並且實際上並未發生。如果你這樣做的話,99%的時間你可能會破壞數據庫。 –