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