Oracle Trigger子查询问题

时间:2011-09-22 17:32:05

标签: oracle plsql triggers subquery

CREATE OR REPLACE TRIGGER "DISC_CLIENT"
BEFORE INSERT ON "PURCHASE"
FOR EACH ROW
DECLARE
checkclient PURCHASE.CLIENTNO%TYPE;
BEGIN
SELECT Clientno INTO checkclient
FROM PURCHASE
GROUP BY ClientNo
HAVING SUM(Amount)=(SELECT MAX(SUM(Amount)) FROM PURCHASE GROUP BY Clientno);
IF :new.ClientNo = checkclient
new.Amount := (:old.Amount * 0.90);
END IF;
END;
/

这个触发器似乎有问题。我知道我不能在子查询中使用WHEN()子句,所以我希望这可以工作,但它不会!想法有人吗? :/

如果客户端与顶级客户端匹配,基本上我试图让这个触发器在插入之前对金额值应用折扣! :)

2 个答案:

答案 0 :(得分:2)

这有一个非常漂亮但简单的方法,创建一个视图并更新它。然后,您可以显式声明触发器中的所有列并将它们放在表中。您最好还是创建一个1行2列表max_amount,然后每次插入最大量clientno。您还应该在购买表中确实有一个折扣金额列,因为您应该知道您给谁打折。收费金额为amount - discount。这可以绕过变异表,无法更新:new.amount,也可以更快,更快地进行查询。如果当前的交易是最高的,那么你实际上并没有实际应用折扣,只有当客户放置了之前的最高价时,所以我就这样写了。

create or replace view purchase_view as
  select *
    from purchase;

CREATE OR REPLACE TRIGGER TR_PURCHASE_INSERT
  BEFORE INSERT ON PURCHASE_VIEW
  FOR EACH ROW

  DECLARE

  checkclient max_amount.clientno%type;
  checkamount max_amount.amount%type;
  discount    purchase.discount%type;

  BEGIN

    SELECT clientno, amount
      INTO checkclient, checkamount
      FROM max_amount;

   IF :new.clientno = checkclient then
      discount := 0.1 * :new.amount;
   ELSIF :new.amount > checkamount then
      update max_amount
         set clientno = :new.clientno
           , maxamount = :new.amount
             ; 
    END IF;

    -- Don-t specify columns so it breaks if you change
    -- the table and not the trigger
    insert into purchase 
    values ( :new.clientno
           , :new.amount
           , discount
           , :new.other_column );
END TR_PURCHASE_INSERT;
/

答案 1 :(得分:1)

我记得一个触发器无法从表中选择它被触发。 否则你会得到ORA-04091:表XXXX正在变异,触发/功能可能看不到它。汤姆advises我们不要在触发器中加入过多的逻辑。

如果我理解你的查询,它应该是这样的:

SELECT Clientno INTO checkclient
FROM PURCHASE
GROUP BY ClientNo
HAVING SUM(Amount)=(select max (sum_amount) from (SELECT SUM(Amount) as sum_amount FROM PURCHASE GROUP BY Clientno));

通过这种方式,它将归还花费最多的客户。

但我觉得最好这样做:

select ClientNo
from (
  select ClientNo, sum (Amount) as sum_amount
  from PURCHASE
  group by ClientNo)
order by sum_amount
where rownum