2012-12-21 124 views
0

我有一个表格给(捐助者,接收者,礼品名)列出谁给了谁礼物。我试图编写一个触发器,如果​​它是由捐助者给出的第一个礼物,接收者收到的第一个礼物,或者如果它是捐赠者和接收者的第一个礼物,就会触发。基本上我需要做的是将新捐助者的名字与所有捐助者的名单进行比较,并确保它不在那里。然后对接收机做同样的事情。这是我的尝试,但我相信这是不对的,因为我的变量现有的接受者和现有的参与者不会做我想让他们做的事。这些变量现有的接收者和现有的参与者是否会存储多个值?如果不是,我该如何完成我需要做的事情?SQL触发器列表Oracle

create or replace TRIGGER FirstGift 
BEFORE INSERT OR UPDATE OF donor,receiver ON GIVING 
FOR EACH ROW 
DECLARE 
ExistingReceivers varchar(255); 
ExistingDonors varchar(255); 

BEGIN 
select donor into existingdonors 
from giving; 

select receiver into existingreceivers 
from giving; 

--first gift for donor, first gift for receiver 
if(:new.donor not in existingdonors and :new.receiver not in existingreceivers)then 
dbms_output.put_line('This is the first gift received by ', :new.receiver, 'and the first given by ', :new.donor); 
insert into messages (intid, donor, receiver, giftname, msg) values (test_seq.nextval, :new.donor, :new.receiver, :new.giftname, 'First Gift Given and First Received!'); 


--first gift for donor, not first gift for receiver 
elsif(:new.donor not in existingdonors)then 
dbms_output.put_line('This is the first gift given by ', :new.donor); 
insert into messages (intid, donor, receiver, giftname, msg) values (test_seq.nextval, :new.donor, :new.receiver, :new.giftname, 'First Gift Given!'); 

--first gift for receiver, not first gift for donor 
elsif(:new.receiver not in existingreceivers)then 
dbms_output.put_line('This is the first gift received by ', :new.receiver); 
insert into messages (intid, donor, receiver, giftname, msg) values (test_seq.nextval, :new.donor, :new.receiver, :new.giftname, 'First Gift Received!'); 

end if; 

end; 
+0

有什么不正确有关existingdonors和existingreceivers变量?只是试图了解可能需要改变以做你想做的事情。 –

+0

据我所知,你试图查询一个表是有变异的,也就是说,一个触发器被触发在一个表上的DML操作,并且你尝试用同样的触发器来查询/更新同一个表。这可能会导致ORA-04091错误。您可能想要使用“而不是”触发器或将触发器设置为“自动事务处理”。 – dariyoosh

+0

错误(18,22):PLS-00103:在期待以下某项时遇到符号“EXISTINGDONORS”:(将符号“(”替换为“EXISTINGDONORS”继续执行 错误(18,62):PLS -00103:在期待以下某种情况时遇到符号“EXISTINGRECEIVERS”:( – user1657563

回答

2

我们更好地帮助您在星期二之前完成这项工作,是吗? (难道你,圣诞老人?)

你的方法应该可以正常工作,只需将所有礼物列表中的细节更改为更容易查询和存储的礼物数量即可。您可以查询的捐助给予的礼物,由接收器接收,并通过像这样的触发使用三个查询对交换的数量(我离开了邮件中插入位):

CREATE OR REPLACE TRIGGER FirstGift 
    BEFORE INSERT OR UPDATE OF donor, receiver ON GIVING FOR EACH ROW 
DECLARE 
    num_donor  NUMBER; 
    num_receiver NUMBER; 
    num_both  NUMBER; 
BEGIN 
    SELECT count(*) INTO num_both 
    FROM giving 
    WHERE donor = :new.donor AND receiver = :new.receiver; 

    SELECT count(*) INTO num_donor 
    FROM giving 
    WHERE donor = :new.donor;  

    SELECT count(*) INTO num_receiver 
    FROM giving 
    WHERE donor = :new.donor; 

    IF num_both = 0 THEN 
    dbms_output.put_line(:new.donor||' and '||:new.receiver); 
    ELSE 
    IF num_donor = 0 THEN 
     dbms_output.put_line(:new.donor); 
    END IF; 

    IF num_receiver = 0 THEN 
     dbms_output.put_line(:new.receiver); 
    END IF; 
END; 
/

如果表中获得巨大,你可以用一个单一的查询解决它:

CREATE OR REPLACE TRIGGER FastFirstGift 
    BEFORE INSERT OR UPDATE OF donor, receiver ON GIVING FOR EACH ROW 
DECLARE 
    num_donor  NUMBER; 
    num_receiver NUMBER; 
    num_both  NUMBER; 
BEGIN 
    SELECT SUM(CASE WHEN donor = :new.donor THEN 1 END), 
     SUM(CASE WHEN receiver = :new.receiver THEN 1 END), 
     SUM(CASE WHEN donor = :new.donor 
        AND receiver = :new.receiver THEN 1 END) 
    INTO num_donor, num_receiver, num_both 
    FROM giving; 

    IF num_both = 0 THEN 
    dbms_output.put_line(:new.donor||' and '||:new.receiver); 
    ELSE 
    IF num_donor = 0 THEN 
     dbms_output.put_line(:new.donor); 
    END IF; 

    IF num_receiver = 0 THEN 
     dbms_output.put_line(:new.receiver); 
    END IF; 
    END IF; 
END; 
/

希望这回答你的问题......