エラーの原因は何ですか:参照されたテーブルの特定のキーに一致する一意の制約はありませんか?


154

以下のテーブル構造の例ではエラーが発生します。参照されたテーブルの特定のキーに一致する一意の制約はなく、それを見つめていたので、この状況でこのエラーが発生する理由を理解できません。

BEGIN;

CREATE TABLE foo (
    name                VARCHAR(256) PRIMARY KEY
);

CREATE TABLE bar(
    pkey        SERIAL PRIMARY KEY,
    foo_fk      VARCHAR(256) NOT NULL REFERENCES foo(name), 
    name        VARCHAR(256) NOT NULL, 
    UNIQUE (foo_fk,name)
);

CREATE TABLE baz(   
    pkey            SERIAL PRIMARY KEY,
    bar_fk          VARCHAR(256) NOT NULL REFERENCES bar(name),
    name            VARCHAR(256)
);

COMMIT;

上記のコードを実行すると次のエラーが発生しますが、これは私には意味がありません。このエラーが発生する理由を誰かが説明できます。私はpostgres 9.1を使用しています

NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
NOTICE:  CREATE TABLE will create implicit sequence "bar_pkey_seq" for serial column "bar.pkey"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "bar_pkey" for table "bar"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "bar_foo_fk_name_key" for table "bar"
NOTICE:  CREATE TABLE will create implicit sequence "baz_pkey_seq" for serial column "baz.pkey"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "baz_pkey" for table "baz"
ERROR:  there is no unique constraint matching given keys for referenced table "bar"


********** Error **********

ERROR: there is no unique constraint matching given keys for referenced table "bar"
SQL state: 42830

回答:


188

これnameは、barテーブルの列にUNIQUE制約がないためです。

ですから、上の2行持つ想像bar名前が含まれている表を'ams'、あなたは上の行を挿入bazして'ams'上のbar_fkどの行に、bar二列マッチングがあるので、それを参照することでしょうか?


1
完璧で短く正確でわかりやすい説明!
Alex

79

postgresqlでは、すべての外部キーが親テーブルの一意のキーを参照するbar必要があるため、テーブルにはunique (name)インデックスが必要です。

http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK参照してください。具体的には次のとおりです。

最後に、外部キーは主キーであるか、一意制約を形成する列を参照する必要があることを言及する必要があります。

鉱山を強調します。


21
宣言されたPKが一意の制約と見なされないのはなぜですか?ユニークでないPKを持つことができるようではありません...
両生類

2
それが「指す」テーブルで一意である必要があります。一意でない場合、データベースエンジンは実際に参照している行を知ることができないためです。
Matteo Tassinari、2016

複合キー?@amphibient
魅力的なロボット

1
私は、親テーブルで参照列に一意のキーを持つだけのPostgreSQLで必要とされていないと思いますが、あまりにもなどのOracle、SQL Serverのような、それは他のRDBMS
Mufachirホサイン

2
親テーブルで複合一意制約または主キーが必要な複合外部キーについても同様です。
Ninjakannon

8

あなたが行ったUNIQUEようにテーブルレベルの制約として行うとき、あなたの定義は複合主キーのようなものですddl制約を参照してください、これは抽出です

"This specifies that the *combination* of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique."

つまり、組み合わせが一意であり、これが外部キー制約と一致しない場合、どちらかのフィールドが一意でない値になる可能性があります。

ほとんどの場合、制約を列レベルにする必要があります。そのため、それらをテーブルレベルの制約として定義するのではなくUNIQUE、列定義の最後に「追加」するname VARCHAR(60) NOT NULL UNIQUEか、各フィールドに個別のテーブルレベルの制約を指定します。


私の状況では列レベルの制約が機能しません。実際に複合主キーを定義する必要がありますが、JPAにマッピングするのは少し面倒なので、私はそれから後退しました:)
ams

6

一意の制約として名前列が必要です。ここにあなたの問題を変更する3行のコードがあります

  1. 最初にこのコードを入力して主キー制約を見つけます

    \d table_name

    このように下部に表示されます "some_constraint" PRIMARY KEY, btree (column)

  2. 制約を削除します。

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
  3. 既存のものと一緒に新しい主キー列を追加します。

    ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);

それで全部です。

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