Was verursacht FEHLER: Es gibt keine eindeutige Einschränkung, die den angegebenen Schlüsseln für die referenzierte Tabelle entspricht.

154

Die folgende Beispieltabellenstruktur gibt einen FEHLER an: Es gibt keine eindeutige Einschränkung, die den angegebenen Schlüsseln für die referenzierte Tabelle entspricht, und nachdem ich sie eine Weile angestarrt habe, kann ich nicht herausfinden, warum dieser Fehler in dieser Situation auftritt.

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;

Das Ausführen des obigen Codes führt zu dem folgenden Fehler, der für mich keinen Sinn ergibt. Kann jemand erklären, warum dieser Fehler auftritt? Ich benutze 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
ams
quelle

Antworten:

188

Dies liegt daran, dass die nameSpalte in der barTabelle nicht die UNIQUE- Einschränkung enthält.

Stellen Sie sich also vor, Sie haben 2 Zeilen in der barTabelle, die den Namen enthalten, 'ams'und Sie fügen eine Zeile bazmit 'ams'on ein bar_fk. Auf welche Zeile barwürde sich das beziehen, da zwei Zeilen übereinstimmen?

Diego
quelle
1
perfekt kurz und präzise und leicht zu fassende Erklärung!
Alex
79

In postgresql müssen alle Fremdschlüssel auf einen eindeutigen Schlüssel in der übergeordneten Tabelle verweisen. In Ihrer barTabelle müssen Sie also einen unique (name)Index haben.

Siehe auch http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK und speziell:

Schließlich sollten wir erwähnen, dass ein Fremdschlüssel auf Spalten verweisen muss, die entweder ein Primärschlüssel sind oder eine eindeutige Einschränkung bilden.

Hervorhebung von mir.

Matteo Tassinari
quelle
21
Warum wird die deklarierte PK nicht als eindeutige Einschränkung betrachtet? Es ist nicht so, dass Sie eine nicht einzigartige PK haben können ...
Amphibient
2
Es muss in der Tabelle, auf die es "zeigt", eindeutig sein, da das Datenbankmodul sonst nicht wissen kann, auf welche Zeile Sie sich tatsächlich beziehen.
Matteo Tassinari
Zusammengesetzte Schlüssel? @amphibient
Charming Robot
1
Ich denke, ein eindeutiger Schlüssel in der Spalte, auf die verwiesen wird, in der übergeordneten Tabelle ist nicht nur in postgresql erforderlich, sondern auch in anderen RDBMS wie Oracle, SQL Server usw.
Mufachir Hossain
2
Beachten Sie, dass die Antwort auch für zusammengesetzte Fremdschlüssel gilt, bei denen eine zusammengesetzte eindeutige Einschränkung oder ein Primärschlüssel für die übergeordnete Tabelle erforderlich ist.
Ninjakannon
8

Wenn Sie UNIQUEeine Einschränkung auf Tabellenebene ausführen, wie Sie es getan haben, ist Ihre Definition ein bisschen wie ein zusammengesetzter Primärschlüssel. Siehe ddl-Einschränkungen . Hier ist ein Auszug

"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."

Dies bedeutet, dass jedes Feld möglicherweise einen nicht eindeutigen Wert haben kann, vorausgesetzt, die Kombination ist eindeutig und entspricht nicht Ihrer Fremdschlüsseleinschränkung.

Höchstwahrscheinlich möchten Sie, dass sich die Einschränkung auf Spaltenebene befindet. Definieren Sie sie also lieber als Einschränkungen auf Tabellenebene, hängen Sie sie UNIQUEan das Ende der name VARCHAR(60) NOT NULL UNIQUESpaltendefinition an oder geben Sie für jedes Feld einzelne Einschränkungen auf Tabellenebene an.

TI
quelle
Die Einschränkung auf Spaltenebene in meiner Situation wird nicht funktionieren. Ich sollte eigentlich einen zusammengesetzten Primärschlüssel definieren, aber ich habe mich zurückgezogen, weil das Zuordnen zu JPA ein bisschen schmerzhaft ist :)
ams
6

Sie sollten eine Namensspalte als eindeutige Einschränkung haben. Hier sind 3 Codezeilen, um Ihre Probleme zu ändern

  1. Ermitteln Sie zunächst die Einschränkungen des Primärschlüssels, indem Sie diesen Code eingeben

    \d table_name

    Sie werden unten so angezeigt "some_constraint" PRIMARY KEY, btree (column)

  2. Löschen Sie die Einschränkung:

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
  3. Fügen Sie eine neue Primärschlüsselspalte mit der vorhandenen hinzu:

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

Das ist alles.

Hari Bharathi
quelle