web-dev-qa-db-ja.com

MATCH FULL、MATCH SIMPLE、MATCH PARTIALの違いは?

MATCH SIMPLEMATCH FULLに気づきましたが、何をしているのかわかりません。デフォルトはMATCH SIMPLEです。しかし、FOREIGN KEY制約関数に対する他のMATCH句はどのように使用しますか?

32
user32234

マニュアルの CREATE TABLEページを確認してください

マッチタイプには、MATCH FULLMATCH PARTIALMATCH SIMPLE(デフォルト)の3つがあります。 MATCH FULLでは、すべての外部キー列がnullでない限り、複数列の外部キーの1つの列をnullにすることはできません。それらがすべてnullの場合、その行は参照先のテーブルで一致する必要はありません。 MATCH SIMPLEでは、任意の外部キー列をnullにすることができます。それらのいずれかがnullの場合、その行は参照されるテーブルで一致する必要はありません。 MATCH PARTIALはまだ実装されていません。 (もちろん、NOT NULL制約を参照列に適用して、これらのケースが発生しないようにすることができます。)

また、 外部キーの章

通常、その参照列のいずれかがnullの場合、参照行は外部キー制約を満たす必要はありません。 MATCH FULLが外部キー宣言に追加された場合、すべての参照列がnullである場合にのみ、参照行は制約を満たし、エスケープされます(したがって、null値とnull以外の値の混合がMATCH FULL制約)。参照する行が外部キー制約を満たさないようにしたくない場合は、参照する列をNOT NULLとして宣言します。

また、currentマニュアルまたはインストールに一致するバージョンを必ず参照してください。古いバージョンへの古いGoogleリンクに陥らないでください。

43

FULL vs SIMPLE vs PARTIAL

選択した答えは正しいですが、これが初めての場合は、コードで確認することをお勧めします。そのように考える方が簡単だと思います。

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

論理的には、FULLおよびSIMPLEを使用すると、完全一致を挿入できます。

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

列の1つがNULLであるときに問題が発生します。

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

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

t_fullに挿入すると、次のエラーが生成されます。

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

では、(42,NULL)についてはどうですか。これは、私がMATCH SIMPLEについて常に混乱している部分です。

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

上記の動作は[〜#〜] not [〜#〜]実装されていないMATCH PARTIALで機能します。これは、右端の列がNULLedである複合インデックスに必要なことを行う可能性がありますアウト。しかし、一部の人々は、それをパンドラの箱を悪いデザインに広げる方法として見ています。

単純な定義とニーモニック

  • MATCH FULLすべてが完全に一致する必要があります、またはすべての列がNULLである必要があります
  • MATCH SIMPLE 1つのものがNULLの場合、制約はsimply無視されます。
  • MATCH PARTIAL 1つがNULLである場合、すべてがNULLであるとは限らないという事実は、部分的に制約の目的のために賢明な何かを行うことによって救われます。

SQL仕様のメモ

後世のために、これが<match type>のSQL仕様の定義です。

  • MATCH SIMPLE少なくとも1つの参照列がnullの場合、参照テーブルの行は制約チェックに合格します。すべての参照列がnullでない場合、行はすべての参照列に一致する被参照テーブルの行がある場合に限り、制約チェックに合格します。
  • MATCH PARTIAL:すべての参照列がnullの場合、参照テーブルの行は制約チェックに合格します。少なくとも1つの参照列がnullでない場合、その行は、null以外のすべての参照列と一致する参照先テーブルの行がある場合に限り、制約チェックに合格します。
  • MATCH FULL:すべての参照列がnullの場合、参照テーブルの行は制約チェックに合格します。すべての参照列がnullでない場合、行はすべての参照列に一致する被参照テーブルの行がある場合に限り、制約チェックに合格します。一部の参照列がnullで別の参照列がnullでない場合、参照テーブルの行は制約チェックに違反しています。

これはPostgreSQL固有ではありませんが、これらの例はPostgreSQLで示されています

11
Evan Carroll