MySQL基于时间的约束

时间:2012-07-31 11:28:46

标签: mysql constraints

我有这两个表的拍卖应用程序(这显然是高度简化的):

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中最简单的方法是什么?

3 个答案:

答案 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)

当然你必须替换'[]'值

答案 1 :(得分:1)

很遗憾,MySQL没有CHECK约束功能。但是您应该能够使用触发器强制执行此操作。但是,MySQL触发器支持不像其他RDBMS-es那样先进​​或优化得很好,如果你这样做,你将遭受相当大的性能损失。因此,如果这是一个拥有大量并发用户的实时交易系统,您应该寻找另一种解决方案。

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

答案 2 :(得分:0)

而是做一个简单的事情创建一个列名状态。将其类型设置为枚举。当你想阻止它时,将其值更新为0.默认值应为1表示打开。 0表示已关闭