Postgres foreign keys / schema issue - postgresql

If I create a new schema on the current database (management), why does it complain about cross-database references?
management=# create schema mgschema;
CREATE SCHEMA
management=# alter table clients add column task_id int null references mgschema.tasks.id;
ERROR: cross-database references are not implemented: "mgschema.tasks.id"

alter table clients add column task_id int null references mgschema.tasks.id;
The REFERENCES syntax in not correct, you should use:
REFERENCES reftable [ ( refcolumn ) ]

A simple references only expects a table name. The foreign key will then automatically point to the primary key of that table, e.g.
alter table clients add column task_id int null references mgschema.tasks;
Another alternative is to to specify the table and columns, but not with a single identifier:
alter table clients add column task_id int null references mgschema.tasks (id);
The second format is needed if the target table has multiple unique constraints.

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.

there is no unique constraint matching given keys for referenced table "employees" [duplicate]

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?
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?
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.
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.
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.

ERROR: there is no unique constraint matching given keys for referenced table "mail_message" Odoo Postgres [duplicate]

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?
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?
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.
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.
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.

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

postgres key is not present in table constraint

When trying to ALTER TABLE in Postgres 9.5 to create foreign key constraint: from product_template.product_brand_id to product_brand.id
ALTER TABLE public.product_template
ADD CONSTRAINT product_template_product_brand_id_fkey
FOREIGN KEY (product_brand_id)
REFERENCES public.product_brand (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE SET NULL;
Returns error
ERROR: insert or update on table "product_template" violates foreign key constraint "product_template_product_brand_id_fkey"
DETAIL: Key (product_brand_id)=(12) is not present in table "product_brand".
STATEMENT: ALTER TABLE "product_template" ADD FOREIGN KEY ("product_brand_id") REFERENCES "product_brand" ON DELETE set null
Im confused why postgres is trying to find product_brand.product_brand_id, when the fkey is from product_template.product_brand_id to product_brand.id
Any ideas?
The error message simply states that there is at least one row in the table product_template that contains the value 12 in the column product_brand_id
But there is no corresponding row in the table product_brand where the column id contains the value 12
Key (product_brand_id)=(12) relates the source column of the foreign key, not the target column.
In simple terms, the value of FOREIGN KEY(product_brand_id) provided in your ALTER statement is not present in the source (product_brand) table.