Reputation: 62632
Trying to create this example table structure in Postgres 9.1:
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)
);
Running the above code produces an error, which does not make sense to me:
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
Can anyone explain why this error arises?
Upvotes: 280
Views: 409912
Reputation: 9933
when you do UNIQUE
as a table level constraint as you have done then what your defining is a bit like a composite primary key see ddl constraints, here is an extract
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.
this means that either field could possibly have a non unique value provided the combination is unique and this does not match your foreign key constraint.
most likely you want the constraint to be at column level. so rather then define them as table level constraints, 'append' UNIQUE
to the end of the column definition like name VARCHAR(60) NOT NULL UNIQUE
or specify indivdual table level constraints for each field.
Upvotes: 14
Reputation: 441
You should have name column as a unique constraint. here is a 3 lines of code to change your issues
First find out the primary key constraints by typing this code
\d table_name
you are shown like this at bottom "some_constraint" PRIMARY KEY, btree (column)
Drop the constraint:
ALTER TABLE table_name DROP CONSTRAINT some_constraint
Add a new primary key column with existing one:
ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);
That's All.
Upvotes: 16
Reputation: 18584
In postgresql all foreign keys must reference a unique key in the parent table, so in your bar
table you must have a unique (name)
index.
See also http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK and specifically:
Finally, we should mention that a foreign key must reference columns that either are a primary key or form a unique constraint.
Emphasis mine.
Upvotes: 144
Reputation: 36126
It's because the name
column on the bar
table does not have the UNIQUE constraint.
So imagine you have 2 rows on the bar
table that contain the name 'ams'
and you insert a row on baz
with 'ams'
on bar_fk
, which row on bar
would it be referring since there are two rows matching?
Upvotes: 343