Why is this compound primary key not working as expected? - mysql-error-1062

I have a table "tbl_project_user_assignment" with a compound primary key.
It is made up of project_id and user_id
Each of these are also a foreign key to the project and user tables respectively.
At the moment, I have 2 entries in this table as below...
project_id | user_id
--------------------
1 | 1
1 | 2
When I run this sql query...
INSERT INTO
tbl_project_user_assignment
(project_id, user_id) VALUES (2, 1);
...I get the following error message:
Integrity constraint violation: 1062
Duplicate entry '1' for key
'FK_project_user'
The FK_project_user key is the one linking the project_id to the tbl_project id.
This doesn't make sense to me because the values I'm inserting are unique...
Any ideas?

It looks like FK_project_user is a unique key. Try dropping temporarily that constraint and perform the insert again.
If insert works, recreate the constraint making sure it's not flagged as unique anymore.

I think you should have:
a foreign key relation to project
a foreign key relation to user
a unique constraint on (project, user)
possibly a primary key on the combination of (project, user) OR a separate key field
If you choose a combined PK you wouldn't need an extra constraint of course.
And it seems you have a unique constraint on user (by itself).
Posting the show create table statement would help even more.

Related

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.

Composite FK referencing atomic PK + non unique attribute

I am trying to create the following tables in Postgres 13.3:
CREATE TABLE IF NOT EXISTS accounts (
account_id Integer PRIMARY KEY NOT NULL
);
CREATE TABLE IF NOT EXISTS users (
user_id Integer PRIMARY KEY NOT NULL,
account_id Integer NOT NULL REFERENCES accounts(account_id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS calendars (
calendar_id Integer PRIMARY KEY NOT NULL,
user_id Integer NOT NULL,
account_id Integer NOT NULL,
FOREIGN KEY (user_id, account_id) REFERENCES users(user_id, account_id) ON DELETE CASCADE
);
But I get the following error when creating the calendars table:
ERROR: there is no unique constraint matching given keys for referenced table "users"
Which does not make much sense to me since the foreign key contains the user_id which is the PK of the users table and therefore also has a uniqueness constraint. If I add an explicit uniqueness constraint on the combined user_id and account_id like so:
ALTER TABLE users ADD UNIQUE (user_id, account_id);
Then I am able to create the calendars table. This unique constraint seems unnecessary to me as user_id is already unique. Can someone please explain to me what I am missing here?
Postgres is so smart/dumb that it doesn't assume the designer to do stupid things.
The Postgres designers could have taken different strategies:
Detect the transitivity, and make the FK not only depend on users.id, but also on users.account_id -> accounts.id. This is doable but costly. It also involves adding multiple dependency-records in the catalogs for a single FK-constraint. When imposing the constraint(UPDATE or DELETE in any of the two referred tables), it could get very complex.
Detect the transitivity, and silently ignore the redundant column reference. This implies: lying to the programmer. It would also need to be represented in the catalogs.
cascading DDL operations would get more complex, too. (remember: DDL is already very hard w.r.t. concurrency/versioning)
From the execution/performance point of view: imposing the constraints currently involves "pseudo triggers" on the referred table's indexes. (except DEFERRED, which has to be handled specially)
So, IMHO the Postgres developers made the sane choice of refusing to do stupid complex things.

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

Can I have a foreign key to a parent table in PostgreSQL?

I'm using inheritance and I ended up having a problem.
If I run:
select count(*) from estate_properties where id = 86820;
I get 1.
But when I try to run this:
insert into property_images (binary_image, name, property_id) values (16779, 'IMG_0096.jpg', 86820)
I get:
********** Error **********
ERROR: insert or update on table "property_images" violates foreign
key constraint "property_images_property_id_fkey" SQL state: 23503
Detail: Key (property_id)=(86820) is not present in table
"estate_properties".
Also ID on estate_properties is SERIAL.
Note: Another table apartments inherits from estate_properties, and 86820 was added to it. Would that make a difference? Also why would it I still have the ID in the parent table and I can select if from there.
Edit:
Looking more closely at the documentation:
http://www.postgresql.org/docs/9.5/static/ddl-inherit.html
I want to achieve this:
5.9.1. Caveats
Specifying that another table's column REFERENCES cities(name) would
allow the other table to contain city names, but not capital names.
There is no good workaround for this case.
EDIT2:
Here is the declaration of the foreign key:
CONSTRAINT property_images_property_id_fkey FOREIGN KEY (property_id)
REFERENCES estate_properties (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
Apparently the answer is here:
Foreign keys + table inheritance in PostgreSQL?
A foreign key can point to a table that is part of an inheritance hierarchy, but it'll only find rows in that table exactly. Not in any parent or child tables. To see which rows the foreign key sees, do a SELECT * FROM ONLY thetable. The ONLY keyword means "ignoring inheritance" and that's what the foreign key lookup will do

Why does this foreign key using inheritance not work? [duplicate]

This question already has answers here:
PostgreSQL foreign key not existing, issue of inheritance?
(2 answers)
Closed 8 years ago.
create table abstract_addresses (
address_id int primary key
);
create table phone_numbers (
phone_number text not null unique
) inherits (abstract_addresses) ;
create table contacts (
name text primary key,
address_id int not null references abstract_addresses(address_id)
);
insert into phone_numbers values (1, '18005551212'); --works
select * from abstract_addresses;
address_id
1
select * from phone_numbers;
address_id phone_number
1 18005551212
insert into contacts values ('Neil', 1); --error
I get this error message:
ERROR: insert or update on table "contacts" violates foreign key constraint "contacts_address_id_fkey"
SQL state: 23503
Detail: Key (address_id)=(1) is not present in table "abstract_addresses".
Just a bad use-case for postgresql table inheritance?
Per the caveats in the docs:
A serious limitation of the inheritance feature is that indexes (including unique constraints) and foreign key constraints only apply to single tables, not to their inheritance children. This is true on both the referencing and referenced sides of a foreign key constraint.
http://www.postgresql.org/docs/current/static/ddl-inherit.html
To do what you want:
Create a table with only an id — like you did.
Don't use inheritance. Really don't. It's useful to partition log tables; not for what you're doing.
Make phone number ids default to nextval('abstract_addresses_address_id_seq'), or whatever the sequence name is.
Add a foreign key in phone_numbers referencing abstract_addresses (address_id). Make it deferrable, initially deferred.
Add an after insert trigger on phone_numbers that inserts a new row in abstract_addresses when needed.
If appropriate, add an after delete trigger on phone_numbers that cascade deletes abstract_addresses — make sure it occurs after the delete, else affected rows will report incorrect values when you delete from phone_numbers.
That way, you'll have an abstract_address for use in occasional tables that need such a thing, while still being able to have a hard reference to phone_numbers where the latter is what you actually want.
One caveat to be aware of: it doesn't play well with ORMs.