sql >> データベース >  >> RDS >> PostgreSQL

Postgresの一意性制約とインデックス

    この基本的で重要な問題について疑問があったので、例を挙げて学ぶことにしました。

    テストテーブルマスターを作成しましょう 2つの列、 con_id 一意の制約とind_id 一意のインデックスでインデックス付けされます。

    create table master (
        con_id integer unique,
        ind_id integer
    );
    create unique index master_unique_idx on master (ind_id);
    
        Table "public.master"
     Column |  Type   | Modifiers
    --------+---------+-----------
     con_id | integer |
     ind_id | integer |
    Indexes:
        "master_con_id_key" UNIQUE CONSTRAINT, btree (con_id)
        "master_unique_idx" UNIQUE, btree (ind_id)
    

    テーブルの説明(psqlでは\ d)で、一意のインデックスから一意の制約を区別できます。

    独自性

    念のため、一意性を確認しましょう。

    test=# insert into master values (0, 0);
    INSERT 0 1
    test=# insert into master values (0, 1);
    ERROR:  duplicate key value violates unique constraint "master_con_id_key"
    DETAIL:  Key (con_id)=(0) already exists.
    test=# insert into master values (1, 0);
    ERROR:  duplicate key value violates unique constraint "master_unique_idx"
    DETAIL:  Key (ind_id)=(0) already exists.
    test=#
    

    期待どおりに機能します!

    外部キー

    次に、詳細を定義します masterの2つの列を参照する2つの外部キーを持つテーブル 。

    create table detail (
        con_id integer,
        ind_id integer,
        constraint detail_fk1 foreign key (con_id) references master(con_id),
        constraint detail_fk2 foreign key (ind_id) references master(ind_id)
    );
    
        Table "public.detail"
     Column |  Type   | Modifiers
    --------+---------+-----------
     con_id | integer |
     ind_id | integer |
    Foreign-key constraints:
        "detail_fk1" FOREIGN KEY (con_id) REFERENCES master(con_id)
        "detail_fk2" FOREIGN KEY (ind_id) REFERENCES master(ind_id)
    

    まあ、エラーはありません。それが機能することを確認しましょう。

    test=# insert into detail values (0, 0);
    INSERT 0 1
    test=# insert into detail values (1, 0);
    ERROR:  insert or update on table "detail" violates foreign key constraint "detail_fk1"
    DETAIL:  Key (con_id)=(1) is not present in table "master".
    test=# insert into detail values (0, 1);
    ERROR:  insert or update on table "detail" violates foreign key constraint "detail_fk2"
    DETAIL:  Key (ind_id)=(1) is not present in table "master".
    test=#
    

    両方の列は外部キーで参照できます。

    インデックスを使用した制約

    既存の一意のインデックスを使用してテーブル制約を追加できます。

    alter table master add constraint master_ind_id_key unique using index master_unique_idx;
    
        Table "public.master"
     Column |  Type   | Modifiers
    --------+---------+-----------
     con_id | integer |
     ind_id | integer |
    Indexes:
        "master_con_id_key" UNIQUE CONSTRAINT, btree (con_id)
        "master_ind_id_key" UNIQUE CONSTRAINT, btree (ind_id)
    Referenced by:
        TABLE "detail" CONSTRAINT "detail_fk1" FOREIGN KEY (con_id) REFERENCES master(con_id)
        TABLE "detail" CONSTRAINT "detail_fk2" FOREIGN KEY (ind_id) REFERENCES master(ind_id)
    

    これで、列制約の説明に違いはありません。

    部分インデックス

    テーブル制約宣言では、部分インデックスを作成できません。これは、create table ...の定義から直接取得されます。 。一意のインデックス宣言では、WHERE clauseを設定できます 部分インデックスを作成します。式(列だけでなく)にインデックスを作成し、他のパラメータ(照合、並べ替え順序、NULL配置)を定義することもできます。

    あなたはできません 部分インデックスを使用してテーブル制約を追加します。

    alter table master add column part_id integer;
    create unique index master_partial_idx on master (part_id) where part_id is not null;
    
    alter table master add constraint master_part_id_key unique using index master_partial_idx;
    ERROR:  "master_partial_idx" is a partial index
    LINE 1: alter table master add constraint master_part_id_key unique ...
                                   ^
    DETAIL:  Cannot create a primary key or unique constraint using such an index.
    


    1. 収集方法:OracleデータベースのEXISTS関数

    2. データベースの歴史

    3. SQL Serverはどの程度健全ですか?プロアクティブなデータベース監視が重要

    4. SQLでHAVING句を使用する方法