Что является причиной ОШИБКИ: не существует уникального ограничения, соответствующего данным ключам для ссылочной таблицы?


155

В приведенном ниже примере структуры таблицы выдается ОШИБКА: не существует уникального ограничения, соответствующего заданным ключам для ссылочной таблицы, и пока я не могу понять, почему эта ошибка возникает в этой ситуации, пока я на нее смотрю.

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

Ответы:


189

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

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


1
идеально короткое и точное и легко уловимое объяснение!
Алекс

79

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

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

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

Акцент мой.


21
почему объявленный PK не рассматривается как уникальное ограничение? это не значит, что у тебя может быть неуникальный ПК ...
амфибия

2
Он должен быть уникальным для таблицы, на которую он «указывает», потому что в противном случае ядро ​​базы данных не сможет узнать, на какую строку вы ссылаетесь.
Маттео Тассинари

Композитные ключи? @amphibient
Очаровательный робот

1
Я думаю, что наличие уникального ключа в столбце ссылки на родительской таблице не требуется только в postgresql, но также и в других СУБД, таких как oracle, sql server и т. Д.
Mufachir Hossain

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

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 немного
затруднительно

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

Вот и все.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.