CHECK
MySQLは制約を強制しません。制約の構文CHECK
が受け入れられ、ドキュメントとしてメタデータに保持されます。しかし、MySQLはそれらを強制しません。(もちろん、BEFOREINSERTトリガーとBEFOREUPDATEトリガーの両方を使用して、トリガーを使用してそのタイプの制約を自分で適用することもできます。)
ENUM
ただし、値を1つだけ選択する場合は、データ型の単一の列を選択する方がはるかに優れています。データ型では、事前定義された値のリストから1つENUM
の値のみを割り当てることができます。そしてMySQLはそれを強制します。
(「strict」のSQLモードが有効になっていない場合、MySQLは少し緩いです。無効な値が割り当てられると、例外をスローするのではなく、MySQLは代わりに「値なし」のプレースホルダーをサイレントに置き換えます。)
ENUMは、個別に格納されたブール列と比較して、行のスペースを大幅に節約します(ただし、単一文字であるかTINYINTであるかにかかわらず、ブール型の格納を実装することを計画しています)。
パフォーマンスについても質問されました。
個別に格納された「ブール」列よりも単一の列の方がパフォーマンスが向上します。ENUM
行が短く、NULLインジケーターが少なく、ブロックあたりの行数が多く、複数の列ではなく1つの列のインデックスが自動的に適用されます。 「1つだけ」とストアドプログラム(トリガー)の呼び出しのオーバーヘッド。
設計に関しては、ENUM
データ型の使用は、ルックアップテーブルへの外部キーに対して完全に受け入れられます。特に、通常はルックアップテーブルへの結合を実行して、画面またはレポートに表示する文字列値を取得する場合はそうです。
注意点は次のとおりです。「エンティティ」テーブルを削除しない限り、「ルックアップ」テーブルを削除しても問題ありません。「エンティティ」テーブルとは、「人、場所、物、概念、またはイベントを表す行を保持するテーブルを意味します。これらは一意に識別でき、ビジネスにとって重要です」。
したがって、たとえば、「open」、「closed」、「pending」、「canceled」、「delayed」などを含む「status」列は、ENUM,
これらが個別に識別可能な「エンティティ」ではないため、の完全な候補です。私たちが本当に関心を持っている実際の「エンティティ」とは異なり、顧客、注文、出荷、支払いなどです。
ファローアップ
ENUMの有効な値のリストを取得するための便利なメカニズムはありません。私の経験では、ほとんどの開発者は、通常のパターンに従って「ルックアップ」クエリを実行できるテーブルを用意することを好みます。
「ルックアップ」テーブルに追加するものの1つは、seq
(シーケンス)列です。これは、ドロップダウンリストに表示する順序を指定します(アルファベット順ではない順序でリストする必要がある場合があるため、保存された文字列値から簡単に導き出すことはできません。)
ENUM
ルックアップテーブルへの外部キーの代わりにデータ型を正常に実装しました。これにより、わずかにクリーンなデータモデルが提供され(図に描かれる不必要に気が散る不要な関係線が回避されます)、ルックアップテーブルへのJOINが回避されるため、アプリケーションのパフォーマンスが向上します。クライアント側からは、select / insert / updateの点で、VARCHAR列と同じように機能します。