web-dev-qa-db-fra.com

Quelle est la cause de ERROR: aucune contrainte unique ne correspond aux clés données pour la table référencée?

L'exemple de structure de table ci-dessous donne une ERREUR: il n'y a pas de contrainte unique qui correspond aux clés données pour la table référencée, et l'ayant regardée pendant un moment, je ne peux pas comprendre pourquoi cette erreur se produit dans cette situation.

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;

L'exécution du code ci-dessus donne l'erreur suivante, ce qui n'a pas de sens pour moi, quelqu'un peut-il expliquer pourquoi cette erreur se produit. J'utilise 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
113
ams

C'est parce que la colonne name de la table bar n'a pas la contrainte UNIQUE.

Alors imaginez que vous avez 2 lignes sur la table bar qui contiennent le nom 'ams' et que vous insérez une ligne sur baz avec 'ams' sur bar_fk, quelle ligne bar serait-il en référence puisqu'il y a deux lignes correspondant?

122
Diego

Dans postgresql, toutes les clés étrangères doivent faire référence à clé unique dans la table parente. Par conséquent, dans votre table bar, vous devez avoir un index unique (name).

Voir aussi http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK et plus précisément:

Enfin, nous devrions mentionner que ne clé étrangère doit référencer des colonnes qui sont soit une clé primaire, soit une contrainte unique.

L'accent est à moi.

64
Matteo Tassinari

quand vous faites UNIQUE comme une contrainte au niveau de la table, comme vous l'avez fait alors ce que vous définissez est un peu comme une clé primaire composite, voyez contraintes de ddl , voici un extrait

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

cela signifie que l'un ou l'autre champ pourrait éventuellement avoir une valeur non unique à condition que la combinaison soit unique et qu'elle ne corresponde pas à votre contrainte de clé étrangère.

très probablement, vous voulez que la contrainte soit au niveau de la colonne. donc plutôt que de les définir en tant que contraintes de niveau de table, 'ajoutez' UNIQUE à la fin de la définition de colonne, comme name VARCHAR(60) NOT NULL UNIQUE, ou spécifiez des contraintes de niveau de table individuelles pour chaque champ.

5
T I

Vous devriez avoir la colonne name comme contrainte unique. voici 3 lignes de code pour changer vos problèmes

  1. Commencez par connaître les contraintes de la clé primaire en tapant ce code

    \d table_name
    

    vous êtes comme ceci en bas "some_constraint" PRIMARY KEY, btree (column)

  2. Supprimez la contrainte:

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
    
  3. Ajoutez une nouvelle colonne de clé primaire avec une existante:

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

C'est tout.

4
Hari Bharathi