PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Composite PRIMARY KEY applique les contraintes NOT NULL sur les colonnes impliquées

Si vous avez besoin pour autoriser les valeurs NULL, utilisez un UNIQUE contrainte au lieu d'une PRIMARY KEY (et ajoutez une colonne PK de substitution, je suggère un serial ). Cela permet aux colonnes d'être NULL :

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

Remarque , cependant (par documentation):

Dans le cadre d'une contrainte unique, les valeurs nulles ne sont pas considérées comme égales.

Dans votre cas, vous pouvez entrer quelque chose comme (1, NULL) pour (m_id, x_id) n'importe quel nombre de fois sans violer la contrainte. Postgres ne considère jamais deux valeurs NULL égales - selon la définition de la norme SQL.

Si vous devez traiter NULL valeurs égales pour interdire ces "doublons", je vois deux options :

1. Deux index partiels

De plus à l'UNIQUE contrainte ci-dessus :

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;

Mais cela devient rapidement incontrôlable avec plus de deux colonnes qui peuvent être NULL. Voir :

  • Créer une contrainte unique avec des colonnes nulles

2. Un UNIQUE multi-colonnes index sur les expressions

Au lieu de la contrainte UNIQUE. Nous avons besoin d'une valeur par défaut gratuite qui n'est jamais présente dans les colonnes impliquées, comme -1 . Ajouter CHECK contraintes pour l'interdire :

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

Comment certains RDBMS gèrent les choses n'est pas toujours un indicateur utile d'un comportement approprié. Le manuel de Postgres y fait allusion :

Cela signifie que même en présence d'une contrainte unique, il est possible de stocker des lignes en double qui contiennent une valeur nulle dans au moins une des colonnes contraintes. Ce comportement est conforme à la norme SQL, mais nous avons entendu dire que d'autres bases de données SQL pourraient ne pas suivre cette règle .Soyez donc prudent lorsque vous développez des applications destinées à être portables.

J'insiste sur moi.