web-dev-qa-db-ja.com

カスタムの一意の列制約。1つの列に特定の値がある場合にのみ適用されます

次のようにカスタムの一意の列制約を持つことは可能ですか? subsettypeの2つのcolsが両方とも文字列であると仮定します(データ型はおそらく問題ではありません)。

typeが「true」の場合、typesubsetの組み合わせを一意にする必要があります。それ以外の場合、制約はありません。 DebianでPostgreSQL 8.4を使用しています。

19
Faheem Mitha

言い換えれば、subsettype = 'true'
A 部分的な一意のインデックス はそれを行います:

CREATE UNIQUE INDEX tbl_some_name_idx ON tbl (subset) WHERE type = 'true';

このように、NULLと組み合わせて一意にすることもできます。これは、他の方法では不可能です-この関連する回答で詳しく説明しています。
PostgreSQLの複数列の一意制約とNULL値

31

これは上記のErwinの回答を補足するものですが、PostgreSQLはさまざまなタイプのインデックスをサポートしています。これらは一般的に相互に排他的ではありません。これらは次のようなものと考えることができます。

  • インデックス方式(btree、Gist、GINなど)。必要に応じて1つ選択します(btreeがデフォルトです)
  • 部分的または完全。 where句を部分的に使用する場合
  • 直接または機能。関数の出力にインデックスを付けることができます。
  • ユニークまたは非ユニーク

これらはすべてさまざまな方法で組み合わせることができます。ここで行っているのは、一意で部分的な機能を使用しているだけなので、部分的に一意のインデックスが得られます(これは、見つけ出すときに非常に役立ちます)。

しかし、typeがtrueであるサブセットフィールドに大文字と小文字を区別しないインデックスを設定するとします。次に、機能定義を追加します。

CREATE INDEX my_index_name_idx_u ON tbl (lower(subset)) WHERE type;

これにより、typeがtrueであるサブセット属性で呼び出されるlower()関数のoutputに一意のインデックスが作成されます。

6
Chris Travers