5

Postgresに多対多の結合テーブルがあり、A)パフォーマンスを(明らかに)向上させ、B)一意性を強制するためにインデックスを作成したいと思います。例えば:

a_id | b_id
1    | 2     <- okay
1    | 3     <- okay
2    | 3     <- okay
1    | 3     <- not okay (same as row 2)

値の一意性を強制する2つの列に単一のインデックスを設定することは可能ですか?どのタイプのインデックスを使用する必要がありますか?

4

2 に答える 2

12

主キーとして

その一意が主キーである場合は、これを実行します。

create table tbl(
   a_id int not null,
   b_id int not null,
   constraint tbl_pkey primary key(a_id,b_id)
);

主キーではありません

その一意が非主キーである場合は、これを実行します。

create table tbl(

   -- other primary key here, e.g.:
   -- id serial primary key,

   a_id int not null,
   b_id int not null,
   constraint tbl_unique unique(a_id,b_id)
);

既存のテーブル

既存のテーブルがある場合は、代わりに次のようにします。

alter table tbl
      add constraint tbl_unique unique(a_id, b_id)

その変更テーブルには、次のメッセージが表示されます。

NOTICE:  ALTER TABLE / ADD UNIQUE will create implicit index "tbl_unique" for table "tbl"


Query returned successfully with no result in 22 ms.

落とす

その制約を削除したい場合(3つのフィールドの組み合わせを一意にしたい場合があります):

ALTER TABLE tbl DROP CONSTRAINT tbl_unique;

インデックスと制約とヌル

インデックスに関しては、Postgres docから:

テーブルに一意性制約または主キーが定義されると、PostgreSQLは自動的に一意性インデックスを作成します

出典:http ://www.postgresql.org/docs/9.1/static/indexes-unique.html


一意性がいくつかのルールに依存する場合はCREATE UNIQUE INDEX、たとえば、次を使用する必要があります。

これを考えると:

CREATE TABLE tbl
(
  a_id integer NOT NULL,
  b_id integer NULL  
);

alter table tbl
    add constraint tbl_unique unique(a_id, b_id);

その一意のものはこれらの重複をキャッチできます。これはデータベースによって拒否されます。

insert into tbl values
(1,1),
(1,1);

しかし、そのUNIQUECONSTRAINTは重複するnullをキャッチできません。ヌルは不明として機能し、ワイルドカードとして機能します。そのため、一意の制約で複数のヌルを使用できます。これはデータベースによって受け入れられます:

insert into tbl values
(1,1),
(1,null), -- think of this null as wildcard, some real value can be assigned later.
(1,null); -- and so is this. that's why both of these nulls are allowed

UNIQUE CONSTRAINTこれにより、一意性の延期が可能になるため、上記のnull値を受け入れることができると考えてください。

一意性制約を除いて、a_idごとに1つのワイルドカード(null b_id)のみが必要な場合は、を追加する必要がありますUNIQUE INDEX。UNIQUECONSTRAINTはそれらを表現することはできません。 INDEXそしてUNIQUE INDEXできます。これは、複数のnullを拒否するための完全なDDLになります。

これが完全なDDLになります。

CREATE TABLE tbl
(
  a_id integer NOT NULL,
  b_id integer NULL  
);
alter table tbl
    add constraint tbl_unique unique(a_id, b_id);

create unique index tbl_unique_a_id on tbl(a_id) where b_id is null;      

これはデータベースによって拒否されます:

insert into tbl values
(1,1),
(1,null),
(1,null);

これは許可されます:

insert into tbl values
(1,1),
(1,null);

http://www.ienablemuch.com/2010/12/postgresql-said-sql-server2008-said-non.htmlに関連

于 2012-05-06T06:35:58.127 に答える
5

PRIMARY KEY@Michael Buenによって説明されている構文と構文を使用することに加えてUNIQUE、明示的なインデックスを作成することもできます。

CREATE UNIQUE INDEX foo_a_b ON tbl(a_id, b_id);

これは、通常の複数列のbツリーインデックスです(これは、KEY構文が暗黙的に作成するものです)。

于 2012-05-06T06:38:54.550 に答える