0

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

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 时,才应允许 bids 表中的行。在 MySQL 中执行此操作的最简单方法是什么?

4

3 回答 3

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)

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

于 2012-07-31T11:44:14.167 回答
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.html和http://rpbouman.blogspot.nl/2006/02/dont-you-需要正确的错误处理.html

于 2012-07-31T11:59:13.353 回答
0

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

于 2012-07-31T11:38:45.073 回答