PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Der zusammengesetzte PRIMARY KEY erzwingt NOT NULL-Einschränkungen für die beteiligten Spalten

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 &lt> -1)
 , CHECK (x_id &lt> -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.