¿Cuál es la mejor manera de crear una restricción no nula en MySQL de modo que fieldA y fieldB no puedan ser ambos NULL. No me importa si ninguno de los dos es NULL por sí solo, siempre que el otro campo tenga un valor no NULL. Y si ambos tienen valores no NULL, entonces es aún mejor.O O restricciones no nulas en MySQL
Respuesta
MySQL 5.5 introdujo SIGNAL, por lo que ya no necesitamos la columna adicional en la respuesta de Bill Karwin. Bill señaló que también necesita un desencadenador para la actualización, así que lo he incluido también.
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
que he hecho algo similar en SQL Server, no estoy seguro de si va a trabajar directamente en MySQL, pero:
ALTER TABLE tableName ADD CONSTRAINT constraintName CHECK ((fieldA IS NOT NULL) OR (fieldB IS NOT NULL));
Al menos yo creo que 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 misma tabla.
Ésta es la sintaxis estándar para una restricción tal, pero MySQL ignora felizmente la restricción después
ALTER TABLE `generic`
ADD CONSTRAINT myConstraint
CHECK (
`FieldA` IS NOT NULL OR
`FieldB` IS NOT NULL
)
@Sklivvz: Prueba con MySQL 5.0.51a, lo encuentro analiza una restricción CHECK, pero no hace cumplir eso. Puedo insertar (NULL, NULL) sin error. Probado tanto MyISAM como InnoDB. El uso posterior de SHOW CREATE TABLE muestra que una restricción CHECK no está en la definición de la tabla, aunque no se proporcionó ningún error cuando definí la tabla.
Esto coincide con MySQL manual que dice: "La cláusula CHECK es analizada pero ignorada por todos los motores de almacenamiento".
Así que para MySQL, tendría que usar un disparador para hacer cumplir esta regla. El único problema es que los desencadenadores MySQL no tienen forma de generar un error o abortar una operación INSERTAR. Una cosa que puede hacer en el desencadenador 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 disparador similar ANTES DE ACTUALIZAR.
Factura, corrigió mi respuesta en consecuencia, gracias, – Sklivvz
En lugar de usar una columna 'NOT NULL' para forzar un error, puede hacer algo como' SET NEW.FieldA = 1/0' que arrojará un error de división por cero . No es un mensaje de error muy * útil *, pero al menos no tiene que agregar columnas especiales. Realmente me gustaría que MySQL soportara las restricciones adecuadas de 'CHECK', o al menos tuviera una mejor manera de lanzar errores desde los desencadenadores. :( – friedo
@friedo: Como la pregunta del OP era sobre imponer algunas condiciones especiales no nulas, pensé que sería apropiado un mensaje de error de violación nula. Otro truco que puedes hacer en un disparador de MySQL es declarar una variable entera en el disparador y probar para asignarle una cadena. Se genera un mensaje de error que incluye la cadena que utiliza. :) –
Esta no es una respuesta directa a su pregunta, pero sí cierta información adicional.
Cuando se trata de varias columnas y comprobar si todos son nulos o uno no es nula, normalmente utilizo COALESCE()
- es breve, legible 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 puede ser usado en tu disparador
- 1. Mongoose JS consulta todas las que vuelven nulas o vacías
- 2. Funciones en mysql o php
- 3. Enum o Bool en mysql?
- 4. MySQL "O" Condición
- 5. MySQL INSERT o SELECCIONAR
- 6. Cassandra o MySQL/PostgreSQL?
- 7. MySQL TEXT o VARCHAR
- 8. ¿Mysql o/y precedencia?
- 9. Restricciones de MySQL y verificación
- 10. ¿Cómo aplicar restricciones únicas en MySQL?
- 11. Usando el operador correcto, o preferible, no igual en MySQL
- 12. Para usar una clave externa en MySQL o no?
- 13. MySQL terminología "restricciones" vs diferencia "claves externas"?
- 14. Esta instrucción if no debe detectar 0; solo cadenas vacías o nulas
- 15. Caso Mysql con o condición
- 16. Lógica: base de datos o aplicación/2 (comprobación de restricciones)
- 17. Verificando las restricciones usando IDisposable - ¿locura o genio?
- 18. rendimiento MySQL ¿ELIMINAR o ACTUALIZAR?
- 19. Restricciones de los criterios de Hibernate Y/O combinación
- 20. Sqlite o MySql? ¿Cómo decidir?
- 21. Firmado o sin firmar en MySQL
- 22. ¿Lógica empresarial en PHP o MySQL?
- 23. Cursores en MySQL - Bueno o malo
- 24. MySQL mayor o igual que el operador está ignorando su obligación o igual a
- 25. columnas MySQL con nulo predeterminado - opción estilística, ¿o no?
- 26. alter table mysql fuera de línea o no?
- 27. MySQL DONDE: cómo escribir "! =" O "no es igual"?
- 28. MYSQL: método SELECT - pero no muestra duplicados/GROUP o DISTINCT?
- 29. mysql no se reconoce como un comando interno o externo, programa operable o lote
- 30. mysql Consulta lenta - Búsqueda de IP (prohibida o no)
Dado que esta es la sintaxis SQL estándar, esto debería funcionar también con otras bases de datos basadas en SQL. (Definitivamente funciona para PostgreSQL.) – Neall
El manual de MySQL dice: "La cláusula CHECK es analizada pero ignorada por todos los motores de almacenamiento". Lo intenté y es verdad. –
¿Incluso se ignora para las tablas InnoDB? Eso apesta. – Neall