Differenze tra MATCH FULL, MATCH SIMPLE e MATCH PARTIAL?


Risposte:


38

Controlla la CREATE TABLEpagina del manuale :

Ci sono tre tipi di corrispondenza: MATCH FULL, MATCH PARTIAL, e MATCH SIMPLE (che è l'impostazione predefinita). MATCH FULLnon consentirà che una colonna di una chiave esterna a più colonne sia nulla a meno che tutte le colonne di chiave esterna siano nulle; se sono tutti nulli, non è necessario che la riga abbia una corrispondenza nella tabella di riferimento. MATCH SIMPLEconsente a qualsiasi colonna di chiave esterna di essere nulla; se uno di essi è nullo, non è necessario che la riga abbia una corrispondenza nella tabella di riferimento. MATCH PARTIALnon è ancora implementato. (Naturalmente, i NOT NULLvincoli possono essere applicati alle colonne di riferimento per evitare l'insorgere di questi casi.)

Inoltre, nel capitolo sulle chiavi esterne :

Normalmente, una riga di riferimento non deve soddisfare il vincolo di chiave esterna se una delle sue colonne di riferimento è nulla. Se MATCH FULL viene aggiunto alla dichiarazione di chiave esterna, una riga di riferimento sfugge soddisfacendo il vincolo solo se tutte le sue colonne di riferimento sono nulle (pertanto si garantisce che un insieme di valori null e non null non MATCH FULL superi un vincolo). Se non si desidera che le righe di riferimento siano in grado di evitare di soddisfare il vincolo di chiave esterna, dichiarare le colonne di riferimento come NOT NULL.

E assicurati di consultare il manuale corrente o la versione corrispondente alla tua installazione. Non cadere per i link Google obsoleti a versioni obsolete.


7

FULLvs SIMPLEvsPARTIAL

Mentre la risposta scelta è corretta, se questa è una novità per te, potresti volerla vedere con il codice - penso che sia più facile fare grok in quel modo.

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

Logicamente, con FULLe SIMPLE, possiamo inserire una corrispondenza completa.

-- works
INSERT INTO t_full (a,b) VALUES (1,1);
INSERT INTO t_simple (a,b) VALUES (1,1);

Il problema si presenta quando una delle colonne è NULL.

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

-- fails
INSERT INTO t_full (a,b) VALUES (1,NULL);

L'inserimento in t_fullgenera il seguente errore,

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, allora (42,NULL)? Questa è la parte che ho sempre trovato confuso MATCH SIMPLE,

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

Il comportamento sopra riportato NON funzionerebbe con quelli non implementati MATCH PARTIAL, il che probabilmente fa quello che vuoi per un indice composto in cui viene estratta la colonna più a destra NULL. Tuttavia, alcune persone lo vedono come un metodo per aprire una scatola di Pandora a un cattivo design.

Definizioni semplici e mnemoniche

  • MATCH FULLtutto deve corrispondere completamente o tutte le colonne devono essereNULL
  • MATCH SIMPLEse una cosa è NULLil vincolo viene semplicemente ignorato.
  • MATCH PARTIALse una cosa è NULLil fatto che non tutto è NULLè parzialmente recuperato facendo qualcosa di sensato per lo scopo del vincolo.

Note sulle specifiche SQL

Per i posteri, ecco le definizioni dalla specifica SQL su <match type>

  • MATCH SIMPLEse almeno una colonna di riferimento è nulla, la riga della tabella di riferimento supera il controllo del vincolo. Se tutte le colonne di riferimento non sono nulle, la riga passa il controllo del vincolo se e solo se esiste una riga della tabella di riferimento che corrisponde a tutte le colonne di riferimento.
  • MATCH PARTIAL: se tutte le colonne di riferimento sono nulle, la riga della tabella di riferimento supera il controllo del vincolo. Se almeno una colonna di riferimento non è nulla, la riga supera il controllo del vincolo se e solo se esiste una riga della tabella di riferimento che corrisponde a tutte le colonne di riferimento non nulle.
  • MATCH FULL: se tutte le colonne di riferimento sono nulle, la riga della tabella di riferimento supera il controllo del vincolo. Se tutte le colonne di riferimento non sono nulle, la riga passa il controllo del vincolo se e solo se esiste una riga della tabella di riferimento che corrisponde a tutte le colonne di riferimento. Se una colonna di riferimento è nulla e un'altra colonna di riferimento non è nulla, la riga della tabella di riferimento viola il controllo dei vincoli.

Sebbene questo non sia specifico di PostgreSQL, questi esempi sono dimostrati con PostgreSQL

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.