创建触发器以插入另一个表

时间:2012-11-13 03:26:16

标签: oracle plsql triggers

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

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; 

无论如何要解决这个问题?或者有更好的方法来做到这一点?我需要在输入表之后在表BILL中插入一个新的Read读取ReadNo需要引用的ReadNo我刚插入。

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

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

有些事情:

SELECT * FROM dba_errors WHERE owner = 'THEOWNER_OF_YOUR_SP';

答案 2 :(得分: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;

答案 3 :(得分:0)

我们可以组合insert和select语句

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;

尝试上面的代码。