Frage

Was ist der beste Weg, um ein nicht-NULL in MySQL zu erstellen, so dass FieldA und FieldB können beide nicht NULL sein. Ich interessiere mich nicht, wenn einer von selbst NULL ist, nur so lange, wie das andere Feld, das einen Nicht-NULL-Wert hat. Und wenn sie beide nicht-NULL-Werte haben, dann ist es noch besser.

War es hilfreich?

Lösung

MySQL 5.5 eingeführt SIGNAL , so dass wir nicht brauchen die zusätzliche Spalte in Bill Karwin Antwort mehr. Bill wies darauf hin, Sie auch einen Auslöser für Updates benötigen, damit ich das auch aufgenommen habe.

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

Andere Tipps

Dies ist keine Antwort direkt auf Ihre Frage, aber einige zusätzliche Informationen.

Wenn Sie mit mehreren Spalten zu tun und zu überprüfen, ob alle null sind oder ein nicht null ist, verwende ich normalerweise COALESCE() - es ist kurz, lesbar und leicht zu pflegende, wenn die Liste wächst:

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

Dies kann in Ihrem Trigger verwendet werden.

@Sklivvz: Testen mit MySQL 5.0.51a, finde ich es ein CHECK-Integritäts parst, sich aber nicht durchsetzen. Ich kann einfügen (NULL, NULL) ohne Fehler. Getestet sowohl MyISAM und InnoDB. Anschließend Tabelle mit SHOW CREATE zeigt, dass eine CHECK-Einschränkung nicht in der Tabellendefinition ist, obwohl kein Fehler gegeben wurde, wenn ich die Tabelle definiert.

Dies entspricht dem MySQL-Handbuch , die sagt: „Die CHECK-Klausel wird analysiert, sondern von all Speicher-Engines ignoriert.“

Also für MySQL, Sie würden einen Trigger verwenden, um diese Regel zu erzwingen. Das einzige Problem ist, dass MySQL löst keine Möglichkeit, einen Fehler zu heben oder eine INSERT-Operation abgebrochen wird. Eine Sache, die Sie im Trigger tun können, um einen Fehler zu verursachen ist eine NOT NULL-Spalte auf NULL zu setzen.

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

Sie müssen auch einen ähnlichen Trigger BEFORE UPDATE.

Dies ist die Standard-Syntax für eine solche Einschränkung, aber MySQL ignoriert wohlig die Einschränkung danach

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

ich etwas ähnliches in SQL Server getan haben, ich bin nicht sicher, ob es in MySQL direkt funktionieren wird, aber:

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

Wenigstens glaube ich, dass die Syntax.

Doch bedenken Sie, dass Sie nicht Check-Einschränkungen für Tabellen erstellen können, müssen Sie nur die Spalten innerhalb einer Tabelle überprüfen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top