0

我在执行下面的触发器时遇到了一些问题:

CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW 

DECLARE

varReadNo   Int;
varMeterID  Int;
varCustID   Varchar(10);

BEGIN 

SELECT SeqReadNo.CurrVal INTO varReadNo FROM DUAL;

Select MeterID INTO varMeterID
From Reading 
Where ReadNo = varReadNo;

Select CustID INTO varCustID
From Address A
Join Meter M 
on A.postCode = M.postCode
Where M.MeterID = varMeterID;

INSERT INTO BILL VALUES 
(SEQBILLNO.NEXTVAL, SYSDATE, 'UNPAID' , 100 , varCustID , SEQREADNO.CURRVAL); 

END;

错误信息:

*原因:触发器(或此语句中引用的用户定义的 plsql 函数)试图查看(或修改)正在被触发它的语句修改的表。

*操作:重写触发器(或函数),使其不读取该表。

这是否意味着我不应该从表格阅读中检索任何详细信息?

我相信当我在插入值时从表读取中检索数据时会出现问题:

SELECT SeqReadNo.CurrVal INTO varReadNo FROM DUAL;

Select MeterID INTO varMeterID
From Reading 
Where ReadNo = varReadNo; 

反正有办法解决这个吗?还是有更好的方法来做到这一点?进入表 Reading 后,我需要在表 BILL 中插入一个新行,其中 ReadNo 需要引用我刚刚插入的 ReadNo。

4

4 回答 4

4

您不能在行触发器中从同一个表中检索记录。您可以使用 :new 和 :old 访问实际记录中的值(这是您的情况吗?)。然后可以将触发器重写为

CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW 

DECLARE

  varCustID   Varchar(10);

BEGIN 

  Select CustID INTO varCustID
    From Address A
    Join Meter M 
      on A.postCode = M.postCode
    Where M.MeterID = :new.MeterID;

  INSERT INTO BILL VALUES 
  (SEQBILLNO.NEXTVAL, SYSDATE, 'UNPAID' , 100 , varCustID , SEQREADNO.CURRVAL); 

END;

如果您需要从 READING 表中查询其他记录,则必须使用语句触发器、行触发器和 PLSQL 集合的组合。AskTom.oracle.com就是一个很好的例子

于 2012-11-13T06:11:18.670 回答
0

在您的触发器中添加异常处理并查看发生了什么,这样您就可以轻松跟踪异常。

CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW 

DECLARE

  varCustID   Varchar(10);

BEGIN 

  -- your code

EXCEPTION
    WHEN NO_DATA_FOUND
    THEN
        DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20299)));
    WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20298)));

END;
于 2012-11-13T06:32:20.290 回答
0

确保您对所有表具有必要的权限,并且可以访问您在插入中使用的序列。

我有一段时间没有做过 Oracle,但您也可以尝试查询 dba_errors(或 all_errors),以尝试获取有关您的 SP 未编译的原因的更多信息。

适合的东西:

SELECT * FROM dba_errors WHERE owner = 'THEOWNER_OF_YOUR_SP';
于 2012-11-13T03:39:36.543 回答
0

我们可以结合插入和选择语句

CREATE OR REPLACE TRIGGER AFTERINSERTCREATEBILL
AFTER INSERT
ON READING
FOR EACH ROW 

DECLARE

varCustID   Varchar(10);

BEGIN 

 insert into bill 
 values 
 select SEQBILLNO.NEXTVAL, 
        SYSDATE, 
        'UNPAID' , 
        100 ,
        CustID,SEQREADNO.CURRVAL 
 From  Address A
 Join  Meter M 
 on    A.postCode = M.postCode
 Where M.MeterID = :new.MeterID; 

END;

试试上面的代码。

于 2014-07-23T11:05:01.517 回答