質問

fieldAとfieldBの両方をNULLにできないように、MySQLで非NULL制約を作成する最良の方法は何ですか。他のフィールドに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

他のヒント

これは質問に対する直接的な回答ではなく、追加情報です。

複数の列を処理し、すべてがヌルであるか、1つがヌルではないかを確認するとき、通常は 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操作を中止する方法がないことです。エラーを引き起こすためにトリガーでできることの1つは、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) );

少なくとも、これが構文だと思います。

ただし、テーブル間でチェック制約を作成することはできず、1つのテーブル内の列のみをチェックできることに注意してください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top