MySQL 8.0 リファレンスマニュアル


13.1.20.6 CHECK 制約

MySQL 8.0.16 より前の CREATE TABLE では、次の限定バージョンのテーブル CHECK 制約構文のみが許可されていました。この構文は解析され、無視されます:

CHECK (expr)

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

[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]

オプションの symbol では、制約の名前を指定します。 省略すると、MySQL はテーブル名、リテラル_chk_および序数 (1、2、3 など) から名前を生成します。 制約名の最大長は 64 文字です。 大/小文字は区別されますが、アクセントは区別されません。

expr では、制約条件をブール式として指定します。この式は、テーブルの各行に対して TRUE または UNKNOWN (NULL 値の場合) に評価される必要があります。 条件が FALSE に評価されると、失敗し、制約違反が発生します。 違反の影響は、このセクションの後半で説明するように、実行されるステートメントによって異なります。

オプションの施行句は、制約が施行されるかどうかを示します:

  • 省略するか、ENFORCED として指定すると、制約が作成されて適用されます。

  • NOT ENFORCED として指定した場合、制約は作成されますが、施行されません。

CHECK 制約は、テーブル制約またはカラム制約のいずれかとして指定されます:

  • テーブル制約はカラム定義内には表示されず、任意のテーブルのカラムを参照できます。 前方参照は、後でテーブル定義に表示されるカラムに対して許可されます。

  • カラム制約はカラム定義内に表示され、そのカラムのみを参照できます。

このテーブル定義について考えます。

CREATE TABLE t1
(
  CHECK (c1 <> c2),
  c1 INT CHECK (c1 > 10),
  c2 INT CONSTRAINT c2_positive CHECK (c2 > 0),
  c3 INT CHECK (c3 < 100),
  CONSTRAINT c1_nonzero CHECK (c1 <> 0),
  CHECK (c1 > c3)
);

定義には、名前付き形式および名前なし形式のテーブル制約およびカラム制約が含まれます:

  • 最初の制約はテーブル制約です: カラム定義の外部で発生するため、複数のテーブルのカラムを参照できます (参照することもできます)。 この制約には、まだ定義されていないカラムへのフォワード参照が含まれています。 制約名が指定されていないため、MySQL は名前を生成します。

  • 次の 3 つの制約はカラム制約です: それぞれがカラム定義内で発生するため、参照できるのは定義されているカラムのみです。 いずれかの制約に明示的に名前が付けられます。 MySQL では、それぞれの名前が生成されます。

  • 最後の 2 つの制約はテーブル制約です。 これらのいずれかに明示的に名前が付けられます。 MySQL により、他方の名前が生成されます。

前述のように、MySQL は、指定されていない CHECK 制約の名前を生成します。 前述のテーブル定義に対して生成された名前を確認するには、SHOW CREATE TABLE を使用します:

mysql> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  `c3` int(11) DEFAULT NULL,
  CONSTRAINT `c1_nonzero` CHECK ((`c1` <> 0)),
  CONSTRAINT `c2_positive` CHECK ((`c2` > 0)),
  CONSTRAINT `t1_chk_1` CHECK ((`c1` <> `c2`)),
  CONSTRAINT `t1_chk_2` CHECK ((`c1` > 10)),
  CONSTRAINT `t1_chk_3` CHECK ((`c3` < 100)),
  CONSTRAINT `t1_chk_4` CHECK ((`c1` > `c3`))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

SQL 標準では、すべてのタイプの制約 (主キー、一意インデックス、外部キー、チェック) が同じネームスペースに属することが指定されています。 MySQL では、各制約タイプにスキーマ (データベース) ごとに独自のネームスペースがあります。 したがって、CHECK 制約名はスキーマごとに一意である必要があります。同じスキーマ内の複数のテーブルで CHECK 制約名を共有することはできません。 (例外: TEMPORARY テーブルは、同じ名前の TEMPORARY 以外のテーブルを非表示にするため、同じ CHECK 制約名を持つこともできます。)

生成された制約名をテーブル名で開始すると、テーブル名もスキーマ内で一意である必要があるため、スキーマの一意性が保証されます。

CHECK の条件式は、次のルールに従う必要があります。 許可されていない構造が式に含まれている場合は、エラーが発生します。

  • AUTO_INCREMENT 属性を持つカラムおよび他のテーブルのカラムを除き、生成されていないカラムおよび生成されたカラムは許可されます。

  • リテラル、決定的組込み関数および演算子を使用できます。 関数は、テーブル内の同じデータが指定された場合、接続ユーザーとは関係なく、複数の起動で同じ結果が生成される場合は決定論的です。 非決定的で、この定義に失敗する関数の例: CONNECTION_ID(), CURRENT_USER(), NOW()

  • ストアドファンクションおよびユーザー定義関数は使用できません。

  • ストアドプロシージャおよびストアドファンクションのパラメータは使用できません。

  • 変数 (システム変数、ユーザー定義変数およびストアドプログラムローカル変数) は使用できません。

  • サブクエリーは許可されません。

外部キー参照アクション (ON UPDATEON DELETE) は、CHECK 制約で使用されるカラムでは禁止されています。 同様に、CHECK 制約は、外部キー参照アクションで使用されるカラムでは禁止されています。

CHECK 制約は、INSERT, UPDATE, REPLACE, LOAD DATA および LOAD XML ステートメントに対して評価され、制約が FALSE と評価されるとエラーが発生します。 エラーが発生した場合、すでに適用されている変更の処理は、厳密な SQL モード で説明されているように、トランザクションストレージエンジンと非トランザクションストレージエンジンで異なり、厳密な SQL モードが有効になっているかどうかによっても異なります。

CHECK 制約は、INSERT IGNORE, UPDATE IGNORE, LOAD DATA ... IGNORE および LOAD XML ... IGNORE ステートメントに対して評価され、制約が FALSE と評価されると警告が発生します。 問題のある行の挿入または更新はスキップされます。

制約式が宣言されたカラム型とは異なるデータ型に評価された場合、宣言された型への暗黙的な強制は、通常の MySQL 型変換ルールに従って行われます。 セクション12.3「式評価での型変換」を参照してください。 型変換が失敗した場合、または精度が失われた場合は、エラーが発生します。

注記

制約式の評価では、評価時に有効な SQL モードが使用されます。 式のいずれかのコンポーネントが SQL モードに依存している場合、すべての使用中に SQL モードが同じでないかぎり、テーブルの使用方法によって結果が異なることがあります。


関連キーワード:  ステートメント, 制約, CREATE, CHECK, TABLE, カラム, テーブル, 定義, DROP, 生成