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 UPDATE
、ON 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 モードが同じでないかぎり、テーブルの使用方法によって結果が異なることがあります。