PL / SQL触发器无法正常工作

时间:2011-11-23 14:56:00

标签: oracle plsql triggers

我遇到触发器问题。创建触发器后,它会给我提供消息

  

BD1.UTILIZADOR处于变异状态,触发器无法读取或执行

我有这张桌子

    create table UTILIZADOR 
    (
       U_ID                 NUMBER(6)            not null,
       U_NOME               VARCHAR2(60)         not null,
       U_SEXO               VARCHAR2(10)         not null,
       U_IDADE              NUMBER(3)            not null,
       U_ALTURA             NUMBER(3)            not null,
       U_PESO               NUMBER(6)            not null,
       U_IMC                NUMBER(2,2),
       U_PRIVILEGIOS        NUMBER(1)            not null,
       U_PASSWORD           VARCHAR2(10)         not null,
       constraint PK_UTILIZADOR primary key (U_ID)
    );

如果我这样做:

INSERT INTO UTILIZADOR (U_ID,U_NOME,U_SEXO,U_IDADE,U_ALTURA,U_PESO,U_PRIVILEGIOS,U_PASSWORD) VALUES (1,'my name','Male',32,174,74000,0,'password');

然后

SELECT * FROM UTILIZADOR;

我可以看到一切都如预期一样。

我想做什么,当插入或更新U_ALTURA或U_PESO时,字段U_IMC会自动更新/插入。

以下是完成的事情:

CREATE OR REPLACE TRIGGER CALCULA_IMC
AFTER INSERT OR UPDATE OF U_ALTURA, U_PESO ON UTILIZADOR
FOR EACH ROW
BEGIN
    UPDATE UTILIZADOR
        SET U_IMC = (U_PESO / 1000) /  (POWER(U_ALTURA / 100,2));
END;
/

有人可以告诉我我做错了吗?

3 个答案:

答案 0 :(得分:5)

您的触发器代码正在更新UTILIZADOR表中的每条记录,这将包括您刚刚插入INSERT语句的记录,我假设您不希望表格中的每条记录每当您在其中插入新记录时都会更新。

当你在插入或更新后触发它时,它实际上是无限地递归调用自己,你真的不想要它。

在有效地完成你想做的事情之前,你需要先了解一下触发器。

http://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm

http://www.techonthenet.com/oracle/triggers/

这是一篇关于变异表和触发器的精彩文章,其中包含一些解决问题的建议:

http://www.oracle-base.com/articles/9i/MutatingTableExceptions.php

可能有更好的方法来实现您的目标,例如您可以使用BEFORE INSERT OR UPDATE触发器并将更新分配给:NEW值,而不是发布新的UPDATE你的触发器等等。

行级触发器无法读取或写入触发的表。但是,语句级触发器可以。

希望它有所帮助...

答案 1 :(得分:3)

我假设您要更新正在更新的记录的字段而不是整个表:

CREATE OR REPLACE TRIGGER CALCULA_IMC
AFTER INSERT OR UPDATE OF U_ALTURA, U_PESO ON UTILIZADOR
FOR EACH ROW
BEGIN
    :NEW.U_IMC = (:NEW.U_PESO / 1000) /  (POWER(:NEW.U_ALTURA / 100,2));
END;
/

答案 2 :(得分:1)

您的触发器正在尝试更新已经更新的行,想一想,在更新后的触发器中,您尝试进行另一次更新,再次触发触发器,导致另一次更新,然后再次触发触发器.......

Oracle不喜欢尝试更改或检查已经更改的内容。

尝试直接在插入/更新语句中设置u_imc。