PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

La CHIAVE PRIMARIA composita applica i vincoli NOT NULL alle colonne coinvolte

Se hai necessità per consentire valori NULL, utilizzare un UNIQUE vincolo invece di una PRIMARY KEY (e aggiungi una colonna PK surrogata, ti suggerisco un serial ). Ciò consente alle colonne di essere NULL:

CREATE TABLE distributor (
   distributor_id serial PRIMARY KEY
 , m_id integer
 , x_id integer
 , UNIQUE(m_id, x_id)
);

Nota , tuttavia (per documentazione):

Ai fini di un vincolo univoco, i valori nulli non sono considerati uguali.

Nel tuo caso, puoi inserire qualcosa come (1, NULL) per (m_id, x_id) qualsiasi numero di volte senza violare il vincolo. Postgres non considera mai due valori NULL uguali - come da definizione nello standard SQL.

Se devi trattare NULL valori uguali per non consentire tali "duplicati", Vedo due opzioni :

1. Due indici parziali

Inoltre al UNIQUE vincolo sopra:

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;

Ma questo sfugge rapidamente di mano con più di due colonne che possono essere NULL. Vedi:

  • Crea un vincolo univoco con colonne null

2. Un UNIQUE a più colonne indice sulle espressioni

Invece del vincolo UNICO. Abbiamo bisogno di un valore predefinito gratuito che non sia mai presente nelle colonne coinvolte, come -1 . Aggiungi CHECK vincoli per non consentirlo:

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))

Come gestiscono determinati RDBMS non è sempre un indicatore utile per un comportamento corretto. Il manuale di Postgres suggerisce questo:

Ciò significa che anche in presenza di un vincolo univoco è possibile memorizzare righe duplicate che contengono un valore nullo in almeno una delle colonne vincolate. Questo comportamento è conforme allo standard SQL, ma abbiamo sentito che altri database SQL potrebbero non seguire questa regola .Quindi fai attenzione quando sviluppi applicazioni destinate a essere portatili.

Enfasi in grassetto la mia.