2016-02-25 122 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%的时间你可能会破坏数据库。 –