不幸的是 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