Вопрос

Какой лучший способ создать ненулевое ограничение в MySQL, чтобы fieldA и fieldB не могли быть равны NULL. Мне все равно, если одно из них само по себе равно NULL, так как другое поле имеет значение, отличное от NULL. И если они оба имеют ненулевые значения, то это даже лучше.

Это было полезно?

Решение

В MySQL 5.5 появился SIGNAL , поэтому мы не нужна дополнительная колонка в ответе Билла Карвина. Билл указал, что вам также нужен триггер для обновления, поэтому я тоже включил его.

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

Другие советы

Это не ответ непосредственно на ваш вопрос, а некоторая дополнительная информация.

При работе с несколькими столбцами и проверке, все ли они равны 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 после этого блаженно игнорирует ограничение

ALTER TABLE `generic` 
ADD CONSTRAINT myConstraint 
CHECK (
  `FieldA` IS NOT NULL OR 
  `FieldB` IS NOT NULL
) 

Я сделал нечто подобное в SQL Server, я не уверен, будет ли это работать напрямую в MySQL, но:

ALTER TABLE tableName ADD CONSTRAINT constraintName CHECK ( (fieldA IS NOT NULL) OR (fieldB IS NOT NULL) );

По крайней мере, я считаю, что это синтаксис.

Однако помните, что вы не можете создавать проверочные ограничения для разных таблиц, вы можете проверять только столбцы в одной таблице.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top