Can I have a foreign key to a parent table in PostgreSQL? - 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

Related

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

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

Foreign key constraint with no from column

In our database we happen to have a foreign key constraint that has an empty from column
It looks something like this
fk_1049376c154c25f8 FOREIGN KEY () REFERENCES table2 (id)
What does this denote and where is a documentation in the Postgres documentation for this
I see three possible meanings
use the same column name as referenced in the second table so meaning (id) references table2 (id) implicitly
use the primary key which would be id in this table so it might also be (id) references table (id)
or monitor all columns (*) references table2 (id) which actually seems to be the way this behaves but does not make any sense to me in using it
Can anyone point me to a correct explanation or some read that confirms any of my theories or gives me the real truth?
Trying to use this throws a syntax error in PostgreSQL 9.3 at least.
postgres=# alter table test add foreign key () references test(id);
ERROR: syntax error at or near ")"
LINE 1: alter table test add foreign key() references test(id);
I am guessing this comes from psql \d or something so it sounds like something wrong in your database, perhaps some sort of catalog corruption.
At any rate it is not a valid syntax and you should look into where this is coming from and fixing it.

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.