Wenn Sie brauchen Um NULL-Werte zuzulassen, verwenden Sie einen UNIQUE
Einschränkung anstelle eines PRIMARY KEY
(und füge eine Ersatz-PK-Spalte hinzu, ich schlage eine serial
vor ). Dadurch können Spalten NULL sein:
CREATE TABLE distributor (
distributor_id serial PRIMARY KEY
, m_id integer
, x_id integer
, UNIQUE(m_id, x_id)
);
Hinweis , jedoch (laut Dokumentation):
Zum Zweck einer Eindeutigkeitsbeschränkung werden Nullwerte nicht als gleich angesehen.
In Ihrem Fall könnten Sie so etwas wie (1, NULL)
eingeben für (m_id, x_id)
beliebig oft, ohne die Beschränkung zu verletzen. Postgres betrachtet niemals zwei NULL-Werte als gleich - gemäß Definition im SQL-Standard.
Wenn Sie NULL
behandeln müssen Werte gleich, um solche "Duplikate" zu verbieten, ich sehe zwei Möglichkeiten :
1. Zwei Teilindizes
Zusätzlich zum UNIQUE
Beschränkung oben:
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;
Bei mehr als zwei Spalten, die NULL sein können, gerät dies jedoch schnell außer Kontrolle. Siehe:
- Eindeutigkeitsbeschränkung mit Nullspalten erstellen
2. Ein mehrspaltiger UNIQUE
Index für Ausdrücke
Anstelle der UNIQUE-Einschränkung. Wir brauchen einen freien Standardwert, der niemals in beteiligten Spalten vorhanden ist, wie -1
. Fügen Sie CHECK
hinzu Einschränkungen, um dies zu verbieten:
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))
Wie bestimmte RDBMS mit Dingen umgehen ist nicht immer ein brauchbarer Indikator für richtiges Verhalten. Das Postgres-Handbuch weist darauf hin:
Das bedeutet, dass es selbst bei Vorliegen einer Eindeutigkeitsbeschränkung möglich ist, doppelte Zeilen zu speichern, die in mindestens einer der beschränkten Spalten einen Nullwert enthalten. Dieses Verhalten entspricht dem SQL-Standard, aber wir haben gehört, dass andere SQL-Datenbanken dieser Regel möglicherweise nicht folgen .Seien Sie also vorsichtig, wenn Sie Anwendungen entwickeln, die portabel sein sollen.
Fettdruck von mir.