2012-11-25 84 views
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; 
/
+0

你問這是什麼最有效的要求?即觸發器還是函數? – w0051977

+0

@ w0051977是的,上面哪個更好用 – Shimmerstrike

+0

@ w0051977得到我的答案感謝您的幫助 – Shimmerstrike

回答

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

+0

感謝您的幫助有任何方式,我可以在觸發器中包括一個函數。每次第3次訪問,第6次訪問和第9次訪問都會給予折扣。 – Shimmerstrike

+0

你可以包含一個函數,但我不確定你在問什麼。 – GolezTrol

+0

感謝您的回覆,我可以做選擇計數和應用折扣等功能?這會使它有效嗎? – Shimmerstrike