在MySQL中创建非NULL约束的最佳方法是什么,fieldA和fieldB不能都是NULL.我不关心其中任何一个本身是NULL,只要其他字段具有非NULL值.如果它们都具有非NULL值,那么它甚至更好.
这不是您问题的直接答案,而是一些其他信息.
当处理多个列并检查是否所有列都为null或者一个不为null时,我通常使用COALESCE()
- 如果列表增长,它是简短的,可读的并且易于维护:
COALESCE(a, b, c, d) IS NULL -- True if all are NULL COALESCE(a, b, c, d) IS NOT NULL -- True if any one is not null
这可以在您的触发器中使用.
@Sklivvz:使用MySQL 5.0.51a进行测试,我发现它解析了CHECK约束,但没有强制执行.我可以插入(NULL,NULL)而没有错误.测试了MyISAM和InnoDB.随后使用SHOW CREATE TABLE显示CHECK约束不在表定义中,即使我在定义表时没有给出错误.
这与MySQL手册相符,该手册说:"CHECK子句被解析但被所有存储引擎忽略."
因此对于MySQL,您必须使用触发器来强制执行此规则.唯一的问题是MySQL触发器无法引发错误或中止INSERT操作.您可以在触发器中执行导致错误的一件事是将NOT NULL列设置为NULL.
CREATE TABLE foo ( FieldA INT, FieldB INT, FieldA_or_FieldB TINYINT NOT NULL; ); DELIMITER // CREATE TRIGGER FieldABNotNull BEFORE INSERT ON foo FOR EACH ROW BEGIN IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN SET NEW.FieldA_or_FieldB = NULL; ELSE SET NEW.FieldA_or_FieldB = 1; END IF; END// INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
在更新之前,您还需要一个类似的触发器.
MySQL 5.5引入了SIGNAL,因此我们不再需要Bill Karwin的答案中的额外列.比尔指出你还需要一个更新触发器,所以我也包括了.
CREATE TABLE foo ( FieldA INT, FieldB INT ); DELIMITER // CREATE TRIGGER InsertFieldABNotNull BEFORE INSERT ON foo FOR EACH ROW BEGIN IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null'; END IF; END// CREATE TRIGGER UpdateFieldABNotNull BEFORE UPDATE ON foo FOR EACH ROW BEGIN IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null'; END IF; END// DELIMITER ; INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error UPDATE foo SET FieldA = NULL; -- gives error