web-dev-qa-db-fra.com

Pourquoi les clés étrangères composites ont-elles besoin d'une contrainte unique distincte?

Voici un tableau simple où les enregistrements peuvent référencer les enregistrements parents dans le même tableau:

CREATE TABLE foo (
    id         SERIAL  PRIMARY KEY,
    parent_id  INT     NULL,
    num        INT     NOT NULL,
    txt        TEXT    NULL,
    FOREIGN KEY (parent_id) REFERENCES foo(id)
);

Avec l'exigence supplémentaire que l'une des autres valeurs de champ (num) doit être identique entre les enregistrements parent et enfant, j'ai pensé qu'une clé étrangère composite devrait faire l'affaire. J'ai changé la dernière ligne en

    FOREIGN KEY (parent_id, num) REFERENCES foo(id, num)

et obtenu ERREUR: il n'y a pas de contrainte unique correspondant aux clés données pour la table référencée "foo".

Je peux facilement ajouter cette contrainte, mais je ne comprends pas pourquoi elle est nécessaire, alors qu'une des colonnes référencées (id) est déjà garantie unique? D'après moi, la nouvelle contrainte serait redondante.

10
Zilk

C'est une limitation du SGBD - pour autant que je sache. Et pas seulement lors de l'ajout d'une colonne mais également lors de la réorganisation des colonnes. Si nous avons une contrainte UNIQUE sur (a1, a2), Nous ne pouvons pas ajouter un FOREIGN KEY Que REFERENCES (a2, a1) sauf s'il existe une contrainte unique sur ce (a2, a1) Qui est essentiellement redondant.

Il ne serait pas terriblement difficile d'ajouter ceci en tant que fonctionnalité:

Lorsqu'il existe une contrainte UNIQUE sur (a), Toute combinaison (a, b, c, ..., z) Ou (b,c, ...a, ...z) Est également garantie UNIQUE.

ou la généralisation:

Lorsqu'il existe une contrainte UNIQUE sur (a1, a2, ..., aN), Alors toute combinaison (a1, a2, ..., aN, b1, b2, ..., bM) Ou tout réarrangement est également garanti UNIQUE.

Il semble qu'il n'ait pas été demandé ou qu'il n'ait pas été jugé suffisamment prioritaire pour être mis en œuvre.

Vous pouvez toujours faire une demande - dans le canal respectif - pour que la fonctionnalité soit implémentée. Ou même l'implémenter vous-même, si le SGBD est open source, comme Postgres.

11
ypercubeᵀᴹ

Les clés étrangères en général (pas seulement composites) DOIVENT pointer vers une CLÉ UNIQUE d'une certaine sorte dans une autre table. Sinon, il n'y aurait pas d'intégrité des données relationnelles.

Cela se plaint car, alors que vous avez une clé unique sur (id) .. vous n'avez PAS de clé unique sur (id, num) .. Ainsi, en ce qui concerne la base de données, la paire (id, num) est pas GARANTI d'être unique. Nous, en tant qu'humains, pouvons comprendre que ce sera unique, mais je suis sûr qu'il y aurait beaucoup de code supplémentaire qu'ils devraient ajouter pour rendre Postgres assez intelligent pour voir que "oh hé .. id est censé être unique , donc id, num doit également être unique "..

Je serais très surpris s'ils ajoutaient ce code lorsque tout ce que vous avez à faire est de créer un autre index unique sur les deux colonnes pour résoudre le problème.

Juste pour être clair, le code qu'ils devraient ajouter ne serait pas seulement ce cas simple ... il devrait gérer tous les cas, même ceux où la clé étrangère est sur 4+ colonnes, etc. Je suis sûr la logique serait assez complexe.

5
Joishi Bodio