web-dev-qa-db-fra.com

Différences entre MATCH FULL, MATCH SIMPLE et MATCH PARTIAL?

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 les autres clauses MATCH aux FOREIGN KEY fonction de contrainte?

32
user32234

Vérifier la CREATE TABLE page du manuel :

Il existe trois types de correspondance: MATCH FULL, MATCH PARTIAL, et MATCH SIMPLE (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 laquelle des colonnes 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, NOT NULL des 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 est garanti d'échouer un MATCH 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 comme NOT 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.

43
Erwin Brandstetter

FULL vs SIMPLE vs PARTIAL

Bien que la réponse choisie soit correcte, si cela est nouveau pour vous, vous voudrez peut-être la voir avec du code - je pense qu'il est plus facile de faire comme ça.

-- 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 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 de (42,NULL) - c'est la partie que j'ai toujours trouvé confuse à propos de MATCH SIMPLE,

-- works
INSERT INTO t_simple (a,b) VALUES (42,NULL);

Le comportement ci-dessus ne PAS fonctionnera avec le MATCH PARTIAL Non implémenté, qui fait probablement ce que vous voulez pour un index composé où se trouve la colonne la plus à droite NULLed out. Cependant, certaines personnes considèrent cela comme une méthode d'ouverture d'une boîte de Pandore à une mauvaise conception.

Définitions et mnémoniques simples

  • MATCH FULL Tout doit correspondre entièrement , ou toutes les colonnes doivent être NULL
  • MATCH SIMPLE Si une chose est NULL la contrainte est simplement ignorée.
  • MATCH PARTIAL Si une chose est NULL le fait que tout n'est pas NULL est partiellement récupéré par faire quelque chose de sensé aux fins de la contrainte.

Notes de spécification SQL

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

11
Evan Carroll