2012-07-31 92 views
0

我有這兩個表的拍賣程序(這是高度簡化,顯然):MySQL的基於時間的約束

create table auctions (
    auction_id int, 
    end_time datetime 
); 

create table bids (
    bid_id int, 
    auction_id int, 
    user_id int, 
    amount numeric, 
    bid_time timestamp, 
    constraint foreign key (auction_id) references auctions (auction_id) 
); 

我不希望在一個拍賣的出價拍賣結束後。換句話說,只有在bid_time早於該拍賣的end_time時,才允許出價表中的行。在MySQL中執行此操作最簡單的方法是什麼?

回答

1

Ufortunately MySQL沒有一個CHECK約束功能。但是你應該能夠使用觸發器強制執行此操作。但是,MySQL觸發器支持並不像其他RDBMS一樣先進或優化,如果以這種方式進行操作,您將遭受相當大的性能影響。所以如果這是一個具有大量併發用戶的實時交易系統,那麼您應該尋找另一種解決方案。

CREATE TRIGGER bir_bids 
BEFORE INSERT ON bids 
FOR EACH ROW 
BEGIN 
    DECLARE v_end_time datetime; 
    -- declare a custom error condition. 
    -- SQLSTATE '45000' is reserved for that. 
    DECLARE ERR_AUCTION_ALREADY_CLOSED CONDITION FOR SQLSTATE '45000'; 

    SELECT end_time INTO v_end_time 
    FROM auctions 
    WHERE auction_id = NEW.auction_id; 

    -- the condition is written like this so that a signal is raised 
    -- only in case the bid time is greater than the auction end time. 
    -- if either bid time or auction end time are NULL, no signal will be raised. 
    -- You should avoid complex NULL handling here if bid time or auction end time 
    -- must not be NULLable - simply define a NOT NULL column constraint for those cases. 
    IF NEW.bid_time > v_end_time THEN 
     SIGNAL ERR_AUCTION_ALREADY_CLOSED; 
    END IF; 
END: 

注意,SIGNAL語法只能從MySQL 5.5(目前GA)。觸發器自MySQL 5.0起可用。因此,如果您需要在5.5版之前的MySQL版本中實現這一點,則需要繞過無法提升信號的方式。您可以通過對數據進行一些更改來確保INSERT失敗。例如,你可以寫:

IF NEW.bid_time > v_end_time THEN 
     SET NEW.auction_id = NULL; 
    END IF; 

由於acution_id聲明表中NOT NULL,數據的狀態,將使得它無法插入。缺點是你會得到NOT NULL約束衝突,並且應用程序將不得不猜測這是由於該觸發器觸發還是由於「真正的」NOT NULL約束衝突。

欲瞭解更多信息,請參見:http://rpbouman.blogspot.nl/2009/12/validating-mysql-data-entry-with_15.htmlhttp://rpbouman.blogspot.nl/2006/02/dont-you-need-proper-error-handling.html

0

而是做一個簡單的事情創建一個列名狀態。將其類型設置爲枚舉。當你想阻止它更新它的值爲0.默認應該是1意味着打開。 0表示關閉

1
Insert into bids (auction_id, user_id, amount, bid_time) 
Select auction_id, [USER_ID], [AMOUNT], [TIMESTAMP] 
From auctions 
WHERE UNIX_TIMESTAMP() <= UNIX_TIMESTAMP(end_time) 

當然,你必須更換 '[]' 值

+0

你能提供一些更多的背景?這是否必須在每次新出價時執行?我希望設置一個約束條件,以便我不必每次都以特定方式輸入出價。 – 2012-07-31 12:01:29

+0

這應該是你的插入語句,所以是的,這將在每次新的出價時執行。但是你可以使用'UNIX_TIMESTAMP()'而不是用其他輸入替換[TIMESTAMP]。 你可以像@Roland Bouman給出的那樣使用觸發器,但我認爲我的答案更容易。 – arnoudhgz 2012-07-31 12:13:59

+0

謝謝。鑑於Roland概述的限制,我可能會使用像這樣的插入語句。 – 2012-07-31 17:41:49