Pregunta

¿Cuál es la mejor manera de crear una restricción que no sea NULL en MySQL, de modo que fieldA y fieldB no puedan ser NULL? No me importa si alguno de ellos es NULL solo, siempre que el otro campo no tenga un valor NULL. Y si ambos tienen valores distintos de NULL, entonces es aún mejor.

¿Fue útil?

Solución

MySQL 5.5 introdujo SIGNAL , por lo que no Necesito más la columna extra en la respuesta de Bill Karwin. Bill señaló que también necesita un desencadenante para la actualización, así que también lo he incluido.

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

Otros consejos

Esto no es una respuesta directamente a su pregunta, sino información adicional.

Cuando se manejan varias columnas y se comprueba si todas son nulas o una no es nula, normalmente uso COALESCE () : es breve, fácil de leer y fácil de mantener si la lista crece:

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

Esto se puede usar en tu activador.

@Sklivvz: Probando con MySQL 5.0.51a, encuentro que analiza una restricción CHECK, pero no la aplica. Puedo insertar (NULL, NULL) sin error. Probado tanto MyISAM como InnoDB. Posteriormente, al usar SHOW CREATE TABLE se muestra que una restricción CHECK no está en la definición de la tabla, aunque no se dio ningún error cuando definí la tabla.

Esto coincide con el manual de MySQL que dice: " La cláusula CHECK se analiza, pero es ignorada por todos los motores de almacenamiento. "

Entonces, para MySQL, tendría que usar un disparador para hacer cumplir esta regla. El único problema es que los activadores de MySQL no tienen forma de generar un error o de cancelar una operación INSERT. Una cosa que puede hacer en el activador para causar un error es establecer una columna NOT NULL en 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

También necesita un desencadenador similar ANTES DE ACTUALIZAR

Esta es la sintaxis estándar para una restricción de este tipo, pero MySQL ignora la restricción posteriormente

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

He hecho algo similar en SQL Server, no estoy seguro de si funcionará directamente en MySQL, pero:

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

Al menos creo que esa es la sintaxis.

Sin embargo, tenga en cuenta que no puede crear restricciones de verificación en las tablas, solo puede verificar las columnas dentro de una tabla.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top