There is no unique constraint matching given keys for referenced - postgresql

Table: A
columns names
--------------------------
PK varchar |datasource
PK int |programid
int |workspaceid
composite pk key of: datasource and programid
Table: B
columns names
---------------------------------------
PK varchar | datasource
PK int | quantitycontractid
int | workspaceid
composite pk key of: datasource and quantitycontractid
I need to make relationship between those tables but using workspaceid and datasource. So i try as usual:
ALTER TABLE A
ADD CONSTRAINT fk_relation
FOREIGN KEY (workspaceid, datasource)
REFERENCES B(workspaceid, datasource)
I am getting following error:
there is no unique constraint matching given keys for referenced table
"B"

You need to add UNIQUE key to B(workspaceid, datasource) before you consider that as a foreign key in table A. This is to ensure a correct one to one or one to many relationships between the two tables.
ALTER TABLE B
ADD CONSTRAINT unq_contraint
UNIQUE KEY (workspaceid, datasource)

The error makes perfect sense to me, your table B doesn't have any unique index or primary key linked to workspaceid. Having said that, your table structure for B looks kinda weird to me. Most databases have a primary key that is an autoincrement and one or more foreign keys linking to other tables. You seem to have made your primary key a combination of multiple foreign keys. While this works, you're gonna have issues like you described and have complicated joins when your query your tables.
Vishal R already answered on how to fix your problem.

Related

Postgres - PK with two columns, FK references one of the columns

I am adding declarative partitioning to an existing table TEST which already has a PK on ID column.
Another table FOREIGN has a FK on TEST (ID).
I am going to partition TEST by range on TIME_STAMP column, and Postgres is telling me the partitioned column must be part of the PK.
If I update the PK to (ID, TIME_STAMP) that breaks the FK in FOREIGN table.
FOREIGN does not have a TIME_STAMP table so I can't extend the FK to include it.
I have tried adding a unique constaint for ID, but again, postgres tell me the unique constraint must include all columns in the PK.
Any solution to this? Inheritance partitioning is beginning to look much more straight forward.

PostgreSQL declarative partition - unique constraint on partitioned table must include all partitioning columns [duplicate]

This question already has an answer here:
ERROR: unique constraint on partitioned table must include all partitioning columns
(1 answer)
Closed last month.
I'm trying to create a partitioned table which refers to itself, creating a doubly-linked list.
CREATE TABLE test2 (
id serial NOT NULL,
category integer NOT NULL,
time timestamp(6) NOT NULL,
prev_event integer,
next_event integer
) PARTITION BY HASH (category);
Once I add primary key I get the following error.
alter table test2 add primary key (id);
ERROR: unique constraint on partitioned table must include all partitioning columns
DETAIL: PRIMARY KEY constraint on table "test2" lacks column "category" which is part of the partition key.
Why does the unique constrain require all partitioned columns to be included?
EDIT: Now I understand why this is needed: https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITIONING-DECLARATIVE-LIMITATIONS
Once I add PK with both columns it works.
alter table test2 add primary key (id, category);
But then adding the FK to itself doesn't work.
alter table test2 add foreign key (prev_event) references test2 (id) on update cascade on delete cascade;
ERROR: there is no unique constraint matching given keys for referenced table "test2"
Since PK is not just id but id-category I can't create FK pointing to id.
Is there any way to deal with this or am I missing something?
I would like to avoid using inheritance partitioning if possible.
EDIT2: It seems this is a known problem. https://www.reddit.com/r/PostgreSQL/comments/di5mbr/postgresql_12_foreign_keys_and_partitioned_tables/f3tsoop/
Seems that there is no straightforward solution. PostgreSQL simply doesn't support this as of v14. One solution is to use triggers to enforce 'foreign key' behavior. Other is to use multi-column foreign keys. Both are far from optimal.

PostgreSQL oximoron

Hi all,
Can any understand what's going on here?
The case is:
There are 2 tables, called "matricula" and "pagament" with a 1:1 relationship cardinality.
Table matricula primary key composed by 3 fields "edicio","curs" and "estudiant".
Table pagament primary key, the same as above. Furthermore, it references matricula.
As shown, trying to insert a row in pagament table is rejected because it does not exists a row in table matricula. However, asking for this row returns one result.
What am I missing?
Thanks you all
Carles
The problem is that the order of the fields in both tables is not the same, and, moreover, the restriction of the foreign key in table pagament, said that
foreign key (estudiant,curs,edicio) references matricula
without specifying the matricula fields.
It's been solved by setting this restriction as
foreign key (estudiant,curs,edicio) references matricula(estudiant,curs,edicio)

Create relationship for association table

Normally when creating constraint between two tables i used to use following script:
ALTER TABLE userVendor
ADD CONSTRAINT myrelation
FOREIGN KEY (DataSource, userId)
REFERENCES user(DataSource, userId)
so userVendor table references user table
Now let's say userVendor becomes association table between two tables. Therefore we have additionally third table called Vendor which has datasource and vendor id as composite key. All of them by the way having composite keys.
How to modify my script to say like (wrong script so far):
ALTER TABLE userVendor
ADD CONSTRAINT myrelation
FOREIGN KEY (DataSource, userId, vendorid)
REFERENCES user(DataSource, userId)
REFERENCES user(DataSource, vendorid)
You'll have to add two foreign key constraints, each referencing one table. It is no problem if a column appears in both constraints.
You will need two ADD CONSTRAINT clauses in your ALTER TABLE statement.

Dropping Unique Constraint - PostgreSQL

TL;DR
I am seeking clarity on this: does a FOREIGN KEY require a UNIQUE CONSTRAINT on the other side, specifically, in Postgres and, generally, in relational database systems?
Perhaps, I can test this, but I'll ask, if the UNIQUE CONSTRAINT is required by the FOREIGN KEY what would happen if I don't create it? Will the Database create one or will it throw an error?
How I got there
I had earlier on created a table with a column username on which I imposed a unique constraint. I then created another table with a column bearer_name having a FOREIGN KEY referencing the previous table's column username; the one which had a UNIQUE CONSTRAINT.
Now, I want to drop the UNIQUE CONSTRAINT on the username column from the database because I have later on created a UNIQUE INDEX on the same column and intuitively I feel that they serve the same purpose, or don't they? But the database is complaining that the UNIQUE INDEX has some dependent objects and so it can't be dropped unless I provide CASCADE as an option in order to drop even the dependent object. It's identifying the FOREIGN KEY on bearer_name column in the second table as the dependent object.
And is it possible for the FOREIGN KEY to be a point to the UNIQUE INDEX instead of the UNIQUE CONSTRAINT?
I am seeking clarity on this: does a FOREIGN KEY require a UNIQUE CONSTRAINT on the other side
No it does not require only UNIQUE CONSTRAINT. It could be PRIMARY KEY or UNIQUE INDEX.
Perhaps, I can test this, but I'll ask, if the UNIQUE CONSTRAINT is required by the FOREIGN KEY what would happen if I don't create it? Will the Database create one or will it throw an error?
CREATE TABLE tab_a(a_id INT, b_id INT);
CREATE TABLE tab_b(b_id INT);
ALTER TABLE tab_a ADD CONSTRAINT fk_tab_a_tab_b FOREIGN KEY (b_id)
REFERENCES tab_b(b_id);
ERROR: there is no unique constraint matching given keys
for referenced table "tab_b"
DBFiddle Demo
And is it possible for the FOREIGN KEY to be a point to the UNIQUE INDEX instead of the UNIQUE CONSTRAINT?
Yes, it is possible.
CREATE UNIQUE INDEX tab_b_i ON tab_b(b_id);
DBFiddle Demo2