92

私は MySQL データベースを Pg (9.1) に移行しており、Pg で新しいデータ型を作成し、それを列定義として使用して MySQL ENUM データ型をエミュレートしています。私の質問 - 代わりに CHECK CONSTRAINT を使用できますか? 行に特定の値のエントリを適用するために、MySQL ENUM 型が実装されています。それはCHECK CONSTRAINTで行うことができますか?はいの場合、それはより良い(またはより悪い)でしょうか?

4

6 に答える 6

153

ここでのコメントと回答、およびいくつかの基本的な調査に基づいて、Postgres-erati からのコメントに提供する次の要約があります。ご意見をお待ちしております。

Postgres データベース テーブル列のエントリを制限するには、3 つの方法があります。「赤」、「緑」、または「青」のみを有効なエントリにする「色」を格納するテーブルを考えてみましょう。

  1. 列挙データ型

    CREATE TYPE valid_colors AS ENUM ('red', 'green', 'blue');
    
    CREATE TABLE t (
        color VALID_COLORS
    );
    

    利点は、タイプを一度定義すると、必要な数のテーブルで再利用できることです。標準クエリは ENUM 型のすべての値を一覧表示でき、アプリケーション フォーム ウィジェットの作成に使用できます。

    SELECT  n.nspname AS enum_schema,  
            t.typname AS enum_name,  
            e.enumlabel AS enum_value
    FROM    pg_type t JOIN 
            pg_enum e ON t.oid = e.enumtypid JOIN 
            pg_catalog.pg_namespace n ON n.oid = t.typnamespace
    WHERE   t.typname = 'valid_colors'
    
     enum_schema | enum_name     | enum_value 
    -------------+---------------+------------
     public      | valid_colors  | red
     public      | valid_colors  | green
     public      | valid_colors  | blue
    

    欠点は、ENUM 型がシステム カタログに格納されるため、その定義を表示するには上記のようなクエリが必要になることです。これらの値は、テーブル定義を表示してもわかりません。また、ENUM 型は実際には組み込みの NUMERIC および TEXT データ型とは別のデータ型であるため、通常の数値および文字列演算子および関数は機能しません。したがって、次のようなクエリを実行することはできません

    SELECT FROM t WHERE color LIKE 'bl%'; 
    
  2. 制約をチェック

    CREATE TABLE t (
        colors TEXT CHECK (colors IN ('red', 'green', 'blue'))
    );
    

    2 つの利点は、1 つは「見たままの結果が得られる」ということです。つまり、列の有効な値がテーブル定義に正しく記録されることと、2 つはネイティブの文字列または数値演算子がすべて機能することです。

  3. 外部キー

    CREATE TABLE valid_colors (
        id SERIAL PRIMARY KEY NOT NULL,
        color TEXT
    );
    
    INSERT INTO valid_colors (color) VALUES 
        ('red'),
        ('green'),
        ('blue');
    
    CREATE TABLE t (
        color_id INTEGER REFERENCES valid_colors (id)
    );
    

    基本的に ENUM 型を作成するのと同じですが、ネイティブの数値演算子または文字列演算子が機能し、有効な値を見つけるためにシステム カタログを照会する必要はありません。color_idを目的のテキスト値にリンクするには結合が必要です。

于 2012-06-11T17:42:16.803 に答える
40

他の回答が指摘しているように、チェック制約には柔軟性の問題がありますが、整数 ID に外部キーを設定するには、ルックアップ中に結合する必要があります。許可された値を参照テーブルの自然キーとして使用しないのはなぜですか?

punkish's answerからスキーマを適応させるには:

CREATE TABLE valid_colors (
    color TEXT PRIMARY KEY
);

INSERT INTO valid_colors (color) VALUES 
    ('red'),
    ('green'),
    ('blue');

CREATE TABLE t (
    color TEXT REFERENCES valid_colors (color) ON UPDATE CASCADE
);

値はチェック制約の場合のようにインラインで格納されるため、結合はありませんが、新しい有効な値のオプションを簡単に追加でき、既存の値のインスタンスを介して更新できますON UPDATE CASCADE(たとえば、「赤」が実際には「赤」である必要があると判断された場合は、更新します)。valid_colors変更が自動的に反映されます)。

于 2017-01-14T21:39:03.920 に答える
5

外部キーとチェック制約の大きな欠点の 1 つは、レポートまたは UI 表示で ID をテキストに解決するために結合を実行する必要があることです。

小規模なシステムでは、これは大したことではありませんが、非常に多くの小さなルックアップ テーブルを使用する人事システムや同様のシステムで作業している場合、テキストを取得するためだけに多数の結合が行われるため、これは非常に大きな問題になる可能性があります。

値が少なく、めったに変化しない場合は、テキスト フィールドに制約を使用することをお勧めします。それ以外の場合は、整数 ID フィールドに対してルックアップ テーブルを使用します。

于 2015-05-23T18:47:40.697 に答える
3

PostgreSQL には列挙型があり、正常に動作します。列挙型が制約よりも「優れている」かどうかはわかりませんが、両方とも機能します。

于 2012-06-08T05:01:28.257 に答える
3

私の観点からすると、同じ一連の値が与えられた場合

  1. 複数の列で使用する場合は、列挙型の方が優れたソリューションです
  2. アプリケーションで 1 つの列の値のみを制限する場合は、チェック制約の方が優れたソリューションです。

もちろん、意思決定プロセスに忍び寄るパラメータは他にもたくさんあります (通常、組み込み演算子が使用できないという事実) が、これら 2 つが最も一般的なものだと思います。

于 2019-09-16T15:07:50.983 に答える
2

なぜ一方が他方よりも好ましいのかについて、誰かがPostgreSQLデータベース側から良い答えを出してくれることを願っています。

ソフトウェア開発者の観点からは、チェック制約を使用することを少し好みます。これは、PostgreSQL 列挙型では更新/挿入を行うために SQL で次のようにキャストする必要があるためです。

INSERT INTO table1 (colA, colB) VALUES('foo', 'bar'::myenum)

ここで、「myenum」は PostgreSQL で指定した列挙型です。

これは確かに SQL の移植性をなくします (ほとんどの人にとっては大したことではないかもしれません) が、アプリケーションの開発中に対処しなければならないもう 1 つの問題でもあります。制約。

補足として、MySQL 列挙型はこのタイプのキャストを必要としないことに気付いたので、これは私の経験では PostgreSQL に特有のものです。

于 2012-06-09T17:54:29.707 に答える