Що викликає ПОМИЛУ: не існує єдиного відповідного обмеження для заданих клавіш для посилальної таблиці?


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;

Запуск вищевказаного коду дає таку помилку, яка для мене не має сенсу, чи може хтось пояснити, чому ця помилка виникає. Я використовую постгреси 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столі не має єдиного обмеження.

Так уявіть собі , у вас є 2 рядки на barстолі , які містять ім'я 'ams'і вставити рядок на bazз 'ams'на bar_fk, що рядок на barб це мати в виду , так як є два рядки , відповідні?


1
ідеальне коротке та точне та легко зрозуміле пояснення!
Олексій

79

У postgresql всі зовнішні ключі повинні посилатися на унікальний ключ у батьківській таблиці, тому у вашій barтаблиці ви повинні мати unique (name)індекс.

Дивіться також http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK та конкретно:

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

Наголос мій.


21
чому не оголошений ПК вважається унікальним обмеженням? це не так, як ти можеш мати
непримітний

2
Він повинен бути унікальним у таблиці, на яку він "вказує", тому що якщо це не так, двигун бази даних не зможе знати, на який рядок ви насправді маєте на увазі.
Маттео Тассінарі

Композитні ключі? @amphibient
Чарівний робот

1
Я думаю, що унікальний ключ у посилається на стовпчик на батьківській таблиці не потрібен лише у postgresql, але також і в інших RDBMS, таких як oracle, sql-сервер тощо.
Mufachir Hossain,

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

Це все.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.