Ho notato un MATCH SIMPLE
e MATCH FULL
, ma non capisco cosa fanno. Vedo che il valore predefinito è MATCH SIMPLE
; ma come funzionano le altre MATCH
clausole della FOREIGN KEY
restrizione?
Ho notato un MATCH SIMPLE
e MATCH FULL
, ma non capisco cosa fanno. Vedo che il valore predefinito è MATCH SIMPLE
; ma come funzionano le altre MATCH
clausole della FOREIGN KEY
restrizione?
Risposte:
Controlla la CREATE TABLE
pagina del manuale :
Ci sono tre tipi di corrispondenza:
MATCH FULL
,MATCH PARTIAL
, eMATCH SIMPLE
(che è l'impostazione predefinita).MATCH FULL
non 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 SIMPLE
consente 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 PARTIAL
non è ancora implementato. (Naturalmente, iNOT NULL
vincoli 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 nonMATCH 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 comeNOT 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.
FULL
vs SIMPLE
vsPARTIAL
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 FULL
e 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_full
genera 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.
MATCH FULL
tutto deve corrispondere completamente o tutte le colonne devono essereNULL
MATCH SIMPLE
se una cosa è NULL
il vincolo viene semplicemente ignorato.MATCH PARTIAL
se una cosa è NULL
il fatto che non tutto è NULL
è parzialmente recuperato facendo qualcosa di sensato per lo scopo del vincolo.Per i posteri, ecco le definizioni dalla specifica SQL su <match type>
MATCH SIMPLE
se 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