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
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?
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.
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.
Vous devriez avoir la colonne name comme contrainte unique. voici 3 lignes de code pour changer vos problèmes
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)
Supprimez la contrainte:
ALTER TABLE table_name DROP CONSTRAINT some_constraint
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.