Cannot create foreign key constraint on table w/ inheritance - postgresql

I'm trying to add a foreign key constraint to an existing table:
ALTER TABLE address
ADD FOREIGN KEY(company_id)
REFERENCES company(company_id) ON DELETE CASCADE DEFERRABLE;
That fails with:
ERROR: insert or update on table "address" violates \
foreign key constraint "address_company_id_fkey"
DETAIL: Key (company_id)=(83376) is not present in table "company".
Yet the company table does have that key:
DB=> SELECT company_id FROM company WHERE company_id = 83376;
company_id
------------
83376
(1 row)
I suspect that this is due to table inheritance (old database, very historic reasons), company is a base table and one derived table is the person table. Which is the one containing the actual key:
DB=> SELECT company_id FROM person WHERE company_id = 83376;
company_id
------------
83376
(1 row)
I'm specifically targeting the base table (assuming it contains the data of all derived tables) because the address rows refer to different derived tables.
Is there a way to make that work?
Or as an alternative, kinda even better, is there a way to have foreign keys targeting specific derived tables?

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.

How to alter a foreign key in postgresql

I created a table in PostgreSQL with a foreign key constraint.
I dropped the table to which the foreign key belongs. Now how to alter the table or how to defer the foreign key present in the table?
To clarify:
I have a table named test. It has a column called subjectName, which is a foreign key of subject Table. Now I dropped subject table. How to remove the FK constaint on table test
Assuming the following tables:
create table subject
(
name varchar(10) primary key
);
create table test
(
some_column integer,
subject_name varchar(10) not null references subject
);
there are two scenarios what could have happened when you dropped the table subject:
1. you didn't actually drop it:
drop table subject;
ERROR: cannot drop table subject because other objects depend on it
Detail: constraint test_subject_name_fkey on table test depends on table subject
Hint: Use DROP ... CASCADE to drop the dependent objects too.
2. you did drop it, then the foreign key is gone as well.
drop table subject cascade;
NOTICE: drop cascades to constraint test_subject_name_fkey on table test
which tells you that the foreign key constraint was automatically dropped.
Perhaps your question in not exactly what you mean. Are you wanting to remove the which was a foreign key from the table. As amply indicated if you dropped the parent table then the FK is also dropped. However the column itself is not dropped from the child table. To remove that you need to alter the table.
alter table test drop column subject_name;
See demo here

Query which will delete other table reference as well as from main table

I have a requirement of deleting records from the Postgres database tables.
We have a Customer table which is the main table, this table contains a primary key which is used in so many other tables as a FOREIGN KEY, I want to delete one of the customers as well as its reference used in other tables. Is there any way to delete the customer from main table as well as from other tables which contains foreign key.
Thanks in Advance.
In the other tables, you want a cascading delete foreign key reference. You can create one in the database using:
alter table othertable add constraint fk_othertable_customerid
foreign key (customerid) references customers(customerid)
on delete cascade;
Note: This assumes that customerid is the name of the column in both tables and that it is already defined in the other tables.
A cascading foreign key constraint does exactly what you specify. When a row is deleted in the reference table, then all related rows are deleted.
If you already have foreign key constraints on customerid, then drop the existing constraint and add the cascading version.

It is possible :Two references to one column in PostgreSQL?

Is it possible to allow two optional foreign key?
For example:
table a (id, nameA)
table b(id nameB)
table c(id ,name)
that the name in table c is a foreign key
and it can contracts or the id from table a or the id from table b.
If its possible, what the way to create it?