0

以下に、割引を適用する2つのトリガーを作成しました。一方は関数を使用し、もう一方は使用しません。これを効率的/より良いものにする他の方法はありますか?

 CREATE OR REPLACE TRIGGER APPLY_DISCOUNT
 BEFORE INSERT OR UPDATE OF INV_NO,C_NO ON INVOICE
 FOR EACH ROW

 DECLARE

 CURSOR C_APPTMNT
 IS
 SELECT C_NO,COUNT(C_NO) 
 FROM APPOINTMENT GROUP BY C_NO;

 V_C_NO APPOINTMENT.C_NO%TYPE;
 VISIT NUMBER(2);

 BEGIN

 VISIT:=CNT_VISIT(:NEW.C_NO);

 IF VISIT BETWEEN 2 AND 4 
 AND :NEW.C_NO = V_C_NO THEN
 :NEW.BILL := :NEW.BILL * 0.9;

 ELSIF VISIT BETWEEN 5 AND 8 
 AND :NEW.C_NO = V_C_NO THEN
 :NEW.BILL := :NEW.BILL * 0.8;

 ELSIF VISIT >=9 AND :NEW.C_NO = V_C_NO THEN:NEW.BILL := :NEW.BILL * 0.7;

 ELSE DBMS_OUTPUT.PUT_LINE('no discount added');

 END IF;

 CLOSE C_APPTMNT;
 END;
 /

////////////////////////////////////////////////// //////////////

 CREATE OR REPLACE FUNCTION ADD_DISCOUNT(
 I_C_NO INVOICE.C_NO%TYPE, I_BILL INVOICE.BILL%TYPE)
 RETURN NUMBER
 IS
 V_BILL invoice.bill%type;

 CURSOR C_APPTMNT
 IS
SELECT C_NO,COUNT(C_NO)
 FROM APPOINTMENT GROUP BY C_NO;

V_C_NO INVOICE.C_NO%TYPE;
VISIT NUMBER;

BEGIN

OPEN C_APPTMNT;
FETCH C_APPTMNT INTO V_C_NO,VISIT;

 IF VISIT >=3
AND I_C_NO = V_C_NO THEN
V_BILL := I_BILL * 0.9;

ELSIF VISIT >=6
AND I_C_NO = V_C_NO THEN
V_BILL := I_BILL * 0.8;

 ELSIF VISIT >=9 AND I_C_NO = V_C_NO THEN V_BILL := I_BILL * 0.7;
 ELSE V_BILL:= I_BILL;
END IF;

CLOSE C_APPTMNT;

RETURN V_BILL;

END;
/


CREATE OR REPLACE TRIGGER DIS_BILL
BEFORE INSERT OR UPDATE OF INV_NO,C_NO ON INVOICE
FOR EACH ROW
DECLARE
BEGIN
:NEW.BILL:=ADD_DISCOUNT(:NEW.C_NO,:NEW.BILL);
END;
/
4

1 に答える 1

1

2つ目は間違っています。値がそうである場合、>= 9それはまた>=6>=3です。したがって、それらの他のものに到達することは決してありません。

最初のものでは、割引が追加されていない場合にのみ、出力を書き込みます。その行がないとコンパイルされないため、その行をそこに置いたように感じますが、を含む行を追加null;して、空のステートメントブロックをコンパイルすることもできます。

このトリガーを高速化するためのトリックは他にもあります。1つは、グループを知っているので、すべてのレコードを照会する必要はありません。また、クエリで計算を行うこともできますが、それほど速くはなりません。

トリガーは次のようになります。

CREATE OR REPLACE TRIGGER APPLY_DISCOUNT
  BEFORE INSERT OR UPDATE OF INV_NO, C_NO ON INVOICE
  FOR EACH ROW

BEGIN

  SELECT 
    CASE 
      WHEN COUNT(C_NO) >= 9 THEN 0.7
      WHEN COUNT(C_NO) >= 6 THEN 0.8
      WHEN COUNT(C_NO) >= 3 THEN 0.9
    ELSE 1
    END * :NEW.BILL
  INTO
    :NEW.BILL
  FROM 
   APPOINTMENT 
  WHERE
    C_NO = :NEW.C_NO;

END;
/

うまくいくSELECT INTO :NEW.BILLはずですが、うまくいかない場合は、変数に選択してからに割り当てることができます:NEW.BILL

于 2012-11-25T21:55:32.170 に答える