複合外部キーに別の一意制約が必要なのはなぜですか?


10

以下は、レコードが同じテーブル内の親レコードを参照できる単純なテーブルです。

CREATE TABLE foo (
    id         SERIAL  PRIMARY KEY,
    parent_id  INT     NULL,
    num        INT     NOT NULL,
    txt        TEXT    NULL,
    FOREIGN KEY (parent_id) REFERENCES foo(id)
);

他のフィールド値(num)の1つが親レコードと子レコードの間で同一でなければならないという追加の要件により、複合外部キーでうまくいくと思いました。最後の行を

    FOREIGN KEY (parent_id, num) REFERENCES foo(id, num)

となったエラー:参照された表「foo」というのキーを与えられた一意の制約マッチングはありません

この制約は簡単に追加できますが、参照される列(id)の1つが既に一意であることが保証されているのに、なぜ必要なのかわかりません。私の見たところ、新しい制約は冗長になります。

回答:


11

これは、DBMSの制限事項です-私が知る限り、DBMSのすべてにおいて。列を追加するときだけでなく、列を再配置するときも同様です。にUNIQUE制約がある場合、本質的に冗長な一意の制約がない限り(a1, a2)FOREIGN KEYそれを追加することはできません。REFERENCES (a2, a1)(a2, a1)

これを機能として追加することは、それほど難しくありません。

UNIQUE制約がある場合(a)、いずれ(a, b, c, ..., z)かまたは(b,c, ...a, ...z)組み合わせも保証されUNIQUEます。

または一般化:

UNIQUE制約がある場合(a1, a2, ..., aN)、任意の(a1, a2, ..., aN, b1, b2, ..., bM)組み合わせまたは再配置も保証されUNIQUEます。

要求されていないか、実装するのに十分な優先度と見なされていないようです。

機能を実装するためのリクエストは、それぞれのチャネルでいつでも行うことができます。または、DBMSがPostgresのようなオープンソースの場合は、自分で実装することもできます。


私はそれがこれほど単純であるかどうかはわかりません。部分インデックス、またはNULL値はどうですか?等で満足している場合、NULLは引き続き正常に機能する可能性がありますNULL != NULL。とにかく.. :)
Joishi Bodio 2016年

@JoishiBodio Nullは問題ないと思います。UNIQUE制約を定義することも、null許容列を指定することもできます。デフォルトでは、いずれかの列にNULLがある場合、制約が渡され、行が受け入れられます。
ypercubeᵀᴹ

2番目に、a1、a2、... aNがnull可能ではなく、b1、b2、bMがnullである場合、問題が発生する可能性があります。ただし、この機能はnull不可の列に対して確実に実装できます。おそらく気になるのは、効率への影響です。
ypercubeᵀᴹ

UNIQUE INDEX列がどこにあるかはよく知っていますNULLABLE。:)しかし、私は同意します-NULL(および部分インデックス)がない場合、それはおそらくかなり簡単です。
Joishi Bodio

5

外部キーは、一般に(単なる複合ではなく)別のテーブル内のある種の一意キーを指す必要があります。そうでない場合、リレーショナルデータの整合性はありません。

(id)に一意のキーがある一方で、(id、num)に一意のキーがないため、これは不満です。したがって、DBに関する限り、(id、num)のペアは一意であることが保証されていません。私たち人間は、それが一意になることを理解できますが、Postgresが「ああ、IDは一意であることがわかるように十分にスマートにするために追加する必要がある多くの追加コードがあると確信しています。 、したがって、id、numも一意である必要があります。

問題を修正するために2つの列に別の一意のインデックスを作成する必要がある場合に、そのコードを追加したとしたら、私は非常に驚きます。

明確にするために、彼らが追加しなければならないコードは、この単純なケースではありません...外部キーが4つ以上の列にあるケースなど、すべてのケースを処理する必要があります。きっとロジックはかなり複雑になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.