213

Postgres 9.1 でこの例のテーブル構造を作成しようとしています:

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

上記のコードを実行するとエラーが発生しますが、これは私には意味がありません。

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

このエラーが発生する理由を説明できる人はいますか?

4

4 に答える 4

269

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

bar名前を含むテーブルに2 つの行があり、 onで'ams'行を挿入すると、2 つの行が一致するため、どの行を参照するのでしょうか?baz'ams'bar_fkbar

于 2012-08-15T09:00:22.520 に答える
110

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

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

最後に、外部キーは、主キーであるか、一意の制約を形成する列を参照する必要があることに注意してください。

強調鉱山。

于 2012-08-15T08:54:32.017 に答える
9

行ったようUNIQUEにテーブルレベルの制約として行う場合、定義は複合主キーに少し似ています。ddl制約を参照してください。ここに抜粋があります

これは、指定された列の値の組み合わせがテーブル全体で一意であることを指定しますが、列のいずれかが一意である必要はありません (通常は一意ではありません)。

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

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

于 2012-08-15T09:09:34.590 に答える