我怎样才能做得更好?

时间:2012-11-25 21:42:43

标签: oracle function plsql triggers procedure

下面我创建了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;
/

1 个答案:

答案 0 :(得分:1)

第二个是错的。如果值为>= 9,则还为>=6>=3。因此,永远不会达到那些精神。

在第一个中,您编写输出,但前提是没有添加折扣。感觉就像你只是把那行放在那里因为没有它就不会编译,但是你也可以添加一行包含null;的行来进行空语句块编译。

有更多技巧可以让这个触发更快。首先,您不必查询所有记录,因为您知道该组。并且您可以在查询中进行计算,但这不会使速度更快。

您的触发器可能如下所示:

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