2012-11-13 71 views
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函数在 这条语句)试图查看(或修改)一个表,该表在被发布它的语句修改的过程中是 。

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

这是否意味着我不想从表Reading中检索任何细节?

我相信这个问题会发生,因为我从表中读取检索数据,同时它插入值:

SELECT SeqReadNo.CurrVal INTO varReadNo FROM DUAL; 

Select MeterID INTO varMeterID 
From Reading 
Where ReadNo = varReadNo; 

它的存在,无论如何要解决这个问题?还是有更好的方法来做到这一点?在输入表之后,我需要在表格BILL中插入一个新的行读取ReadNo需要引用我刚插入的ReadNo的位置。

+0

您需要找出'编译/授权失败的触发器'期间发生了什么错误然后给我们那个错误信息。如果您有TOAD,请转到Schema Browser中的触发器,右键单击并编译,它应该会显示错误消息。如果你只是在SQLPLUS中运行脚本,我想它应该给你一个错误信息。另外我建议你在你的INSERT语句中添加一个列表来减少可能的错误。 –

+0

你可以尝试在触发器外面插入表'BILL'吗?并检查您是否具有您在触发器中使用的表的读/写权限。这将帮助您调试问题。 – user75ponic

+0

我试图插入表格比尔无触发器,它似乎工作正常。我试着对触发器中的值进行硬编码,它的工作也很好,我相信问题在于下面的语句:SELECT SeqReadNo.CurrVal INTO varReadNo FROM DUAL; Select MeterID INTO varMeterID From Reading Where ReadNo = varReadNo; – FirstTimer

回答

4

您不能检索连续触发来自同一个表中的记录。你可以使用new和old来访问实际记录中的值(这是你的情况吗?)。如果您需要查询从阅读表中的其他记录,你必须使用语句触发器,行触发器和PLSQL集合的组合触发然后可以改写为

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; 

。这方面的好例子是AskTom.oracle.com

+3

甚至可以将插入和选择组合到一个语句中。 –

0

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

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

某事的调整:

SELECT * FROM dba_errors WHERE owner = 'THEOWNER_OF_YOUR_SP'; 
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; 
+0

我测试了例外;新的读数将被插入,但是账单不会被创建。解决这个问题的任何想法? – FirstTimer

+0

账单到底是什么?一些身份证号码正在生成? – user75ponic

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; 

尝试上面的代码。

相关问题