J'ai remarqué un MATCH SIMPLE
et MATCH FULL
, mais je ne comprends pas ce qu'ils font. Je vois que la valeur par défaut est MATCH SIMPLE
; mais comment fonctionnent les autres MATCH
clauses de la FOREIGN KEY
contrainte?
J'ai remarqué un MATCH SIMPLE
et MATCH FULL
, mais je ne comprends pas ce qu'ils font. Je vois que la valeur par défaut est MATCH SIMPLE
; mais comment fonctionnent les autres MATCH
clauses de la FOREIGN KEY
contrainte?
Réponses:
Consultez la CREATE TABLE
page du manuel :
Il existe trois types de match:
MATCH FULL
,MATCH PARTIAL
etMATCH SIMPLE
( ce qui est la valeur par défaut).MATCH FULL
ne permettra pas qu'une colonne d'une clé étrangère multicolonne soit nulle à moins que toutes les colonnes de clé étrangère soient nulles; s'ils sont tous nuls, la ligne n'a pas besoin d'avoir une correspondance dans la table référencée.MATCH SIMPLE
permet à n'importe quelle colonne de clé étrangère d'être nulle; si l'un d'eux est nul, la ligne n'a pas besoin d'avoir une correspondance dans la table référencée.MATCH PARTIAL
n'est pas encore implémenté. (Bien sûr, desNOT NULL
contraintes peuvent être appliquées aux colonnes de référence pour empêcher ces cas de se produire.)
Aussi, dans le chapitre sur les clés étrangères :
Normalement, une ligne de référence n'a pas besoin de satisfaire la contrainte de clé étrangère si l'une de ses colonnes de référence est nulle. Si
MATCH FULL
est ajouté à la déclaration de clé étrangère, une ligne de référence ne s'échappe en satisfaisant à la contrainte que si toutes ses colonnes de référence sont nulles (donc un mélange de valeurs nulles et non nulles garantit l'échec d'uneMATCH FULL
contrainte). Si vous ne voulez pas que les lignes de référence puissent éviter de satisfaire la contrainte de clé étrangère, déclarez la ou les colonnes de référence commeNOT NULL
.
Et assurez-vous de consulter le manuel actuel ou la version correspondant à votre installation. Ne craignez pas les liens Google obsolètes vers des versions obsolètes.
FULL
vs SIMPLE
vsPARTIAL
Bien que la réponse choisie soit correcte, si c'est nouveau pour vous, vous voudrez peut-être la voir avec du code - je pense qu'il est plus facile de procéder de cette façon.
-- one row with (1,1)
CREATE TABLE foo ( a int, b int,
PRIMARY KEY (a,b)
);
INSERT INTO foo (a,b) VALUES (1,1);
--
-- two child tables to reference it
--
CREATE TABLE t_full ( a int, b int,
FOREIGN KEY (a,b) REFERENCES foo MATCH FULL
);
CREATE TABLE t_simple ( a int, b int,
FOREIGN KEY (a,b) REFERENCES foo MATCH SIMPLE
);
Logiquement, avec FULL
et SIMPLE
, nous pouvons insérer une correspondance complète.
-- works
INSERT INTO t_full (a,b) VALUES (1,1);
INSERT INTO t_simple (a,b) VALUES (1,1);
Le problème survient lorsque l'une des colonnes l'est NULL
.
-- works
INSERT INTO t_simple (a,b) VALUES (1,NULL);
-- fails
INSERT INTO t_full (a,b) VALUES (1,NULL);
L'insertion dans t_full
génère l'erreur suivante,
ERROR: insert or update on table "t_full" violates foreign key constraint "t_full_a_fkey"
DETAIL: MATCH FULL does not allow mixing of null and nonnull key values.
INSERT 0 1
Ok, alors qu'en est-il (42,NULL)
- c'est la partie qui m'a toujours dérouté MATCH SIMPLE
,
-- works
INSERT INTO t_simple (a,b) VALUES (42,NULL);
Le comportement ci-dessus ne fonctionnerait PAS avec le non implémenté MATCH PARTIAL
, qui fait probablement ce que vous voulez pour un index composé où la colonne la plus à droite est NULL
supprimée. Cependant, certaines personnes considèrent cela comme une méthode d'ouverture d'une boîte de Pandore à une mauvaise conception.
MATCH FULL
tout doit correspondre parfaitement , ou toutes les colonnes doivent êtreNULL
MATCH SIMPLE
si une chose est NULL
la contrainte est simplement ignorée.MATCH PARTIAL
si une chose est NULL
le fait que tout ne soit pas NULL
est partiellement récupéré en faisant quelque chose de sensé dans le but de la contrainte.Pour la postérité, voici les définitions de la spécification SQL sur le <match type>
MATCH SIMPLE
si au moins une colonne de référence est nulle, la ligne de la table de référence passe la vérification des contraintes. Si toutes les colonnes de référence ne sont pas nulles, la ligne passe la vérification des contraintes si et seulement s'il existe une ligne de la table référencée qui correspond à toutes les colonnes de référence.MATCH PARTIAL
: si toutes les colonnes de référence sont nulles, la ligne de la table de référence passe la vérification des contraintes. Si au moins une colonne de référence n'est pas nulle, la ligne passe la vérification des contraintes si et seulement s'il existe une ligne de la table référencée qui correspond à toutes les colonnes de référence non nulles.MATCH FULL
: si toutes les colonnes de référence sont nulles, la ligne de la table de référence passe la vérification des contraintes. Si toutes les colonnes de référence ne sont pas nulles, la ligne passe la vérification des contraintes si et seulement s'il existe une ligne de la table référencée qui correspond à toutes les colonnes de référence. Si une colonne de référence est nulle et une autre colonne de référence n'est pas nulle, la ligne de la table de référence viole la vérification des contraintes.
Bien que cela ne soit pas spécifique à PostgreSQL, ces exemples sont illustrés avec PostgreSQL