2010-07-24 52 views
0

我有一本名爲表。此表有3列viz id,價格和折扣。如果價格大於200,那麼折扣應該是20%。在Book表中插入數據時,應根據價格值更新折扣值。在Book表中插入或更新數據時如何處理?強制執行業務規則,甲骨文

請提供所有可能的解決方案。我不想執行存儲過程。讓我們假設當用戶在Book表中插入/更新數據時,他不執行一個函數或過程。

請提供解決方案。

+0

所有可能的解決方案。如果我只能想到一個,我應該不回答嗎? – 2010-07-24 14:04:19

+1

一種解決方案是你的家庭作業的問題複製到StackOverflow上。遞歸可能是一個問題 – deinst 2010-07-24 14:07:22

+0

爲什麼你不想使用存儲過程? – 2010-07-24 19:59:58

回答

2

如果你不希望使用存儲過程,則唯一的選擇是一個觸發器。

create or replace trigger book_discount_rule 
    before insert, update on BOOK 
    for each row 
begin 
    if :new.price > 200 
    then 
     :new.discount := 20; 
    else 
     :new.discount := 0;    
    end if; 
end; 

就我個人而言,我不喜歡這種解決方案,因爲觸發器是不可見的。也就是說,如果用戶運行此插入語句...

insert into book 
    values (book_id_seq.nextval, 250, 30) 
/

...他們可能會疑惑,爲什麼存儲的折扣是從他們提交的值不同。我寧願使用存儲過程來執行業務規則。

無論哪種方式,在現實生活中我寧願通過API,而不是硬編碼值實施的規則。但這是一個品味問題。


正如傑弗裏指出,這是一個檢查約束備份觸發(或程序)在桌子上保證折扣是合適的價格是一個好主意。

alter table book 
    add constraint book_discount_ck 
    check ((price > 200 and discount = 20) or discount = 0) 
/

應用沒有任何一個存儲過程或o觸發約束要求用戶瞭解業務規則。不幸的是,Oracle不提供將特定錯誤消息附加到我們的檢查約束的機制。使用有意義的消息來引發特定於上下文的異常是存儲過程的優勢之一。

+0

不錯,但-1沒有提供所有可能的解決方案:) – 2010-07-25 13:30:44

+0

@JeffreyKemp - 我是我自己編輯的受害者!原來的標題是無用的「PL SQL問題」。我想我應該修改我的答案,重新命名這個問題。 – APC 2010-07-25 14:18:30

1

不使用任何存儲過程:

ALTER TABLE "Book" ADD (
    CONSTRAINT discount_check 
    CHECK (price < 200 OR discount = 0.2) 
); 

這樣,沒有人可以,除非它們插入價格和折扣適當的值插入或更新一本書*

*(以是防彈的,你也可以在這些列上添加NOT NULL限制)

0

如果折扣總是簡單的價格函數,那麼我會建議在視圖中將其作爲計算列。給定一個表Books的列idprice,創建這樣一個觀點:

CREATE VIEW books_view AS (
    SELECT 
    id, 
    price, 
    CASE WHEN price > 200 THEN 0.20 ELSE 0 END discount 
    FROM books 
); 

這樣,用戶就不能打折設置爲不正確的值。使用觸發器解決方案時,可以在插入時正確設置折扣,但隨後可能會通過更新進行更改。

+0

這就是APC觸發器也覆蓋UPDATE條件的原因。 – 2010-07-26 16:42:13