How would you create a unique index on a foreign table? - postgresql

Database 1 has foreign tables a and b on database 2.
How can we create indexes on these foreign tables a and b. These foreign tables are wrappers over database2.c and database2.d tables respectively, which do have the necessary indexes in place.
How would you create indexes on foreign tables a and b? Is that even possible?
I get a cannot create index on foreign table a - when I try a simple Create Index command in postgres

You cannot create index on a foreign table, instead write a trigger on foreign table and create a local table in postgres such that whenever an insert, update or delete is happening in your foreign table it will be reflected in your local table and index it.

Joining with a foreign table can result to slow query's.
Since indexes are not a option with foreign table, consider making a materialized view on a foreign table . Materialized views do allow indexing
CREATE FOREIGN TABLE members_fdw(...)
CREATE MATERIALIZED VIEW members AS
select * from members_fdw
WITH DATA
CREATE UNIQUE INDEX "member_id" ON members USING btree ("id");

Related

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.

PostgreSQL create partitions of table with existing rows and with referential integrity

I'm trying to partitioning a table with existing rows in Postgresql 10.8.
The structure is like this :
I'm trying to create partitions of table Item, it has around 5mill of rows.
I create the partitions with those commands:
CREATE TABLE item_1 (CHECK (id >0 AND id <1000001)) INHERITS (item);
CREATE TABLE item_2 (CHECK (id >1000000 AND id <2000001)) INHERITS (item);
...
Then the rules:
CREATE RULE item_1_rule AS ON INSERT TO item WHERE (id >0 AND id <1000001) DO INSTEAD INSERT INTO item_1 VALUES (NEW.*);
CREATE RULE item_2_rule AS ON INSERT TO item WHERE (id >1000000 AND id <2000001) DO INSTEAD INSERT INTO item_2 VALUES (NEW.*);
...
Then the migration to the partitioned tables:
INSERT INTO item_1 SELECT * FROM item WHERE (id >0 AND id <1000001);
INSERT INTO item_2 SELECT * FROM item WHERE (id >1000000 AND id <2000001);
...
And finally I try to Delete all the rows from the Item table:
DELETE FROM ONLY item;
But I get this error:
ERROR: update or delete on table "item" violates foreign key constraint >"item_audit_item_id_fkey" on table "item_audit"
SQL state: 23503
Detail: Key (id)=(1) is still referenced from table "item_audit".
So is it possible to drop the data from the main table Item to have only the rows on the partitions tables?
There are other alternatives to make a partition in a different way?
If you use inheritance partitioning, you won't be able to have foreign keys pointing to the partitioned table. You have to drop the constraint before you can delete the rows.
I recommend to use declarative partitioning. If you upgrade to v11 or later, you can have a foreign key pointing to a partitioned table, but since the primary key on a partitioned table has to contain the partitioning key, you'd have to add that column to the foreign key as well.
Since partitioning is mostly useful for mass data deletion, it might make sense to partition item_audit the same way.

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.

updating table with Postgresql Foreign data wrapper

I created a foreign data wrapper table named t_user into mySchema.
IMPORT FOREIGN SCHEMA public LIMIT TO (t_user)
FROM SERVER myServer INTO mySchema;
The myServer side t_user added some column, but the foreign table didn't update accordingly.
I tried to delete the foreign table t_user, but it was used by my view and materialized view t_user, so the deletion failed.
Any ideas on how to update this table?
As you have seen, the foreign table definition does not change when the underlying table changes.
If all you did is add a column, you can use ALTER FOREIGN TABLE to add a corresponding column to the foreign table. That should work even if views depend on the foreign table.
For example, if the column is of type text, you can do:
ALTER FOREIGN TABLE t_user ADD COLUMN my_column text;

Altering table for adding foreign key constraint take very long time

I have one table manual_errors_archive. I need to add foreign key to this table keeping reference to values table, values table having 800,000 records and manual_errors_archive table does not have any records.
ALTER TABLE manual_errors_archive
ADD CONSTRAINT fk_manua_reference_value
FOREIGN KEY (value_id)
REFERENCES values;
Postgres version i am using 9.1
But this is running for more than 1 hr after that I canceled the process. Any idea how to optimize this process?