Подтвердить что ты не робот

Что вызывает ERROR: нет уникального ограничения, связанного с заданными ключами для таблицы ссылок?

Ниже примерная структура таблицы дает ERROR: нет уникального ограничения, сопоставляющего заданные ключи для таблицы, на которую ссылается, и глядя на него, пока я не могу понять, почему эта ошибка возникает в этой ситуации.

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
4b9b3361

Ответ 1

Это потому, что столбец name в таблице bar не имеет ограничения UNIQUE.

Итак, представьте, что у вас есть 2 строки в таблице bar, которые содержат имя 'ams', и вы вставляете строку на baz с 'ams' на bar_fk, какая строка на bar будет ссылаться так как есть две строки, соответствующие?

Ответ 2

В postgresql все внешние ключи должны ссылаться на уникальный ключ в родительской таблице, поэтому в вашей таблице bar у вас должен быть индекс unique (name).

См. также http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK и, в частности:

Наконец, следует отметить, что внешний ключ должен ссылаться на столбцы которые либо являются первичным ключом, либо образуют уникальное ограничение.

Акцент на мой.

Ответ 3

когда вы выполняете 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, или укажите отдельные ограничения уровня таблицы для каждого поля.

Ответ 4

Вы должны иметь имя столбца в качестве уникального ограничения. вот 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);
    

Все это.