必要の場合 NULL値を許可するには、 UNIQUE
を使用します 制約 PRIMARY KEY
の代わりに (そして代理PK列を追加します。serial
をお勧めします )。これにより、列をNULLにすることができます:
CREATE TABLE distributor (
distributor_id serial PRIMARY KEY
, m_id integer
, x_id integer
, UNIQUE(m_id, x_id)
);
注 ただし、(ドキュメントごとに):
一意性制約の目的で、null値は等しいとは見なされません。
あなたの場合、(1, NULL)
のようなものを入力することができます (m_id, x_id)
の場合 制約に違反することなく何度でも。 Postgresは2つのNULL値を等しいと見なすことはありません -SQL標準の定義に従います。
NULL
を処理する必要がある場合 このような「重複」を禁止するのと同じ値、2つのオプションが表示されます :
1。 2つの部分インデックス
さらに UNIQUE
へ 上記の制約:
CREATE UNIQUE INDEX dist_m_uni_idx ON distributor (m_id) WHERE x_id IS NULL;
CREATE UNIQUE INDEX dist_x_uni_idx ON distributor (x_id) WHERE m_id IS NULL;
しかし、これはNULLになる可能性のある3つ以上の列ですぐに手に負えなくなります。参照:
- null列を使用して一意の制約を作成する
2。複数列のUNIQUE
式のインデックス
UNIQUE制約の代わりに。 -1
のように、関連する列には決して存在しない無料のデフォルト値が必要です。 。 CHECK
を追加します それを禁止するための制約:
CREATE TABLE distributor (
distributor serial PRIMARY KEY
, m_id integer
, x_id integer
, CHECK (m_id <> -1)
, CHECK (x_id <> -1)
);
CREATE UNIQUE INDEX distributor_uni_idx ON distributor (COALESCE(m_id, -1)
, COALESCE(x_id, -1))
特定のRDBMSが物事を処理する方法 は、適切な動作を示すための有用な指標であるとは限りません。 Postgresのマニュアルはこれを示唆しています:
つまり、一意の制約が存在する場合でも、制約された列の少なくとも1つにnull値を含む重複行を格納することが可能です。この動作はSQL標準に準拠していますが、他のSQLデータベースがこのルールに従わない可能性があると聞いています 。したがって、ポータブルを目的としたアプリケーションを開発する場合は注意が必要です。
大胆な強調鉱山。