web-dev-qa-db-ja.com

MySQLのCHECK制約が機能していません

まず、次のようなテーブルを作成しました

CREATE TABLE Customer (
  SD integer CHECK (SD > 0),
  Last_Name varchar (30),
  First_Name varchar(30)
);

そして、そのテーブルに値を挿入しました

INSERT INTO Customer values ('-2','abc','zz');

MySQLはエラーを表示せず、値を受け入れました。

123
JohnRaja

MySQL 8.0.16 は、CHECK制約をサポートする最初のバージョンです。

読み取り https://dev.mysql.com/doc/refman/8.0/en/create-table-check-constraints.html

MySQL 8.0.15以前を使用している場合、 MySQLリファレンスマニュアル は次のように述べています。

CHECK句は解析されますが、すべてのストレージエンジンによって無視されます。

トリガーを試してください...

mysql> delimiter //
mysql> CREATE TRIGGER trig_sd_check BEFORE INSERT ON Customer 
    -> FOR EACH ROW 
    -> BEGIN 
    -> IF NEW.SD<0 THEN 
    -> SET NEW.SD=0; 
    -> END IF; 
    -> END
    -> //
mysql> delimiter ;

お役に立てば幸いです。

133
David Kerins

残念ながら、MySQLはSQLチェック制約をサポートしていません。互換性の理由からDDLクエリで定義できますが、無視されます。

簡単な代替手段があります

BEFORE INSERTおよびBEFORE UPDATEトリガーを作成すると、データの要件が満たされない場合にエラーを発生させるか、フィールドをデフォルト値に設定できます。

MySQL 5.5以降で動作するBEFORE INSERTの例

DELIMITER $$
CREATE TRIGGER `test_before_insert` BEFORE INSERT ON `Test`
FOR EACH ROW
BEGIN
    IF CHAR_LENGTH( NEW.ID ) < 4 THEN
        SIGNAL SQLSTATE '12345'
            SET MESSAGE_TEXT := 'check constraint on Test.ID failed';
    END IF;
END$$   
DELIMITER ;  

MySQL 5.5より前は、エラーを発生させる必要がありました。未定義のプロシージャを呼び出します。

どちらの場合も、これにより暗黙的なトランザクションのロールバックが発生します。 MySQLは、プロシージャおよびトリガー内でROLLBACKステートメント自体を許可しません。

トランザクションをロールバックしたくない場合(失敗した「チェック制約」でもINSERT/UPDATEがパスする必要があります。SET NEW.ID = NULLを使用して値を上書きできます。 id thoに意味をなす

編集:浮遊引用を削除しました。

:=演算子について:

=とは異なり、:=演算子は比較演算子として解釈されません。つまり、有効なSQLステートメント(SETステートメントだけでなく)で:=を使用して、変数に値を割り当てることができます。

https://dev.mysql.com/doc/refman/5.6/en/assignment-operators.html

バックティック識別子の引用に関して:

識別子の引用文字はバックティック(「 `」)です

ANSI_QUOTES SQLモードが有効になっている場合、二重引用符で囲まれた識別子を引用することもできます

http://dev.mysql.com/doc/refman/5.6/en/identifiers.html

72
Michel Feldheim

CHECK制約は、ドキュメントのごくわずかなコメントで説明されているように、MySQLによって無視されます。CREATE TABLE

CHECK句は解析されますが、すべてのストレージエンジンによって無視されます。

50
ypercubeᵀᴹ

CHECK制約はMySQLに実装されていないようです。

このバグレポートを参照してください: https://bugs.mysql.com/bug.php?id=3464

15
ryanprayogo

Joanq MariaDBで述べたように、他の利点の中でもCHECK制約をサポートするようになりました:

「CHECK CONSTRAINTのサポート( MDEV-756 )。」

https://mariadb.com/kb/en/mariadb/mariadb-1021-release-notes/

8
Markus Barthlen

チェック制約はバージョン8.0.15でサポートされています(まだリリースされていません)

https://bugs.mysql.com/bug.php?id=3464

[1月23日16時24分]ポール・デュボア

開発者による投稿:8.0.15で修正。

以前は、MySQLはCHECK制約構文の制限された形式を許可していましたが、解析して無視しました。 MySQLは、すべてのストレージエンジンに対して、テーブルおよび列のCHECK制約のコア機能を実装しています。制約は、CREATE TABLEおよびALTER TABLEステートメントを使用して定義されます。

1
James

checksを使用するようにMySQL 8.0.16に更新します。

MySQL 8.0.16の時点で、CREATE TABLEはすべてのストレージエンジンに対して、テーブルおよび列のCHECK制約のコア機能を許可します。 CREATE TABLEは、テーブル制約と列制約の両方に対して、次のCHECK制約構文を許可します

MySQL Checks Documentation

1
sdlins