Getting an error while assigning FK's to tables in postGIS? - postgresql

I have created 5 tables, with four of them having a Primary Key. I then try to assign Foreign Keys using the following alter statement:
ALTER TABLE SensorLocation
ADD CONSTRAINT constraint_name
FOREIGN KEY (sensor_id)
REFERENCES Sensor (sensor_id)
;
ALTER TABLE DataStream
ADD CONSTRAINT constraint_name
FOREIGN KEY (sensorlocation_id)
REFERENCES SensorLocation (sensorlocation_id)
;
ALTER TABLE DataStream
ADD CONSTRAINT constraint_name
FOREIGN KEY (property_id)
REFERENCES ObservedProperty (property_id)
;
ALTER TABLE Observation
ADD CONSTRAINT constraint_name
FOREIGN KEY (observation_id)
REFERENCES DataStream (observation_id)
;
The thing is, when I only use one constraint per table, it works. But when I want to assign multiple to the table DataStream it doesn't work.
The error message I receive is as follows:
constraint "constraint_name" for relation "datastream" already exists
Does anyone have any idea on how to solve this? All help is welcome!
This is our data-structure:

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

Alter a unique index to set it deferrable in postgresq

I need to alter a unique index which has already been created to set it deferrable. In postgres 9.6. Basically, i do something like:
DROP TABLE IF EXISTS test;
CREATE TABLE test (id integer);
ALTER TABLE test ADD CONSTRAINT unique_id unique(id);
ALTER TABLE test ALTER CONSTRAINT unique_id DEFERRABLE INITIALLY DEFERRED;
But i get
ERROR: constraint "unique_id" of relation "test" is not a foreign key constraint
Documentation does not seem to mention that such action cannot be performed. What am i missing?
Per the documentation:
ALTER CONSTRAINT
This form alters the attributes of a constraint that was previously created. Currently only foreign key constraints may be altered.
Instead you can:
ALTER TABLE test DROP CONSTRAINT unique_id;
ALTER TABLE test ADD CONSTRAINT unique_id unique(id) DEFERRABLE INITIALLY DEFERRED;

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.

Is it possible to set a primary key to DEFERRABLE?

my question is related to this question.
I want to switch two id of a table which are defined as primary keys.
But unfortunately the table where I want to switch the ids was already created and the primary key constraint was not set do deferrable.
I tried to set it to deferrable with the following statement:
alter table table_name alter constraint primary_key_name_pkey deferrable;
And got an error:
constraint "primary_key_name_pkey" of relation "table_name" is not a foreign key constraint
Is there any way to set a primary key constraint to deferrable after creation?
Thanks for your help.
As written in the source code of PostgreSQL:
/*
* ALTER TABLE ALTER CONSTRAINT
*
* Update the attributes of a constraint.
*
* Currently only works for Foreign Key constraints.
* Foreign keys do not inherit, so we purposely ignore the
* recursion bit here, but we keep the API the same for when
* other constraint types are supported.
Source: https://github.com/postgres/postgres/blob/master/src/backend/commands/tablecmds.c#L9557
So, it's not possible, even with Pg12.

Adding primary key changes column type

Our database currently doesn't define primary keys on any tables. All of the id columns are simply unique indexes. I'm dropping those indexes and replacing them with proper primary keys.
My problem: In Postgres 8.4.7, one table in particular changes the data type from bigint to integer when I add the primary key to the table.
I've got the following table definition:
psql=# \d events
Table "public.events"
Column | Type | Modifiers
-----------------------+--------------------------+-----------------------------------------------------
id | bigint | not null default nextval('events_id_seq'::regclass)
[more columns omitted]
Indexes:
"events_id_unique_pk" UNIQUE, btree (id)
Foreign-key constraints:
"events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
"events_event_configs_id_fk" FOREIGN KEY (event_config_id) REFERENCES event_configs(id)
"events_pdu_circuitbreaker_id_fk" FOREIGN KEY (pdu_circuitbreaker_id) REFERENCES pdu_circuitbreaker(id)
"events_pdu_id_fk" FOREIGN KEY (pdu_id) REFERENCES pdus(id) ON DELETE CASCADE
"events_pdu_outlet_id_fk" FOREIGN KEY (pdu_outlet_id) REFERENCES pdu_outlet(id)
"events_sensor_id_fk" FOREIGN KEY (sensor_id) REFERENCES sensors(id)
"events_user_id_fk" FOREIGN KEY (clearing_user_id) REFERENCES users(id)
Referenced by:
TABLE "events" CONSTRAINT "events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
TABLE "event_params" CONSTRAINT "events_params_event_id_fk" FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE
Triggers:
event_validate BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE event_validate()
This is what happens:
psql=# ALTER TABLE events ADD PRIMARY KEY (id);
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "events_pkey" for table "events"
ALTER TABLE
psql=# \d events
Table "public.events"
Column | Type | Modifiers
-----------------------+--------------------------+-----------------------------------------------------
id | integer | not null default nextval('events_id_seq'::regclass)
[more columns omitted]
Indexes:
"events_pkey" PRIMARY KEY, btree (id)
"events_id_unique_pk" UNIQUE, btree (id)
Foreign-key constraints:
"events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
"events_event_configs_id_fk" FOREIGN KEY (event_config_id) REFERENCES event_configs(id)
"events_pdu_circuitbreaker_id_fk" FOREIGN KEY (pdu_circuitbreaker_id) REFERENCES pdu_circuitbreaker(id)
"events_pdu_id_fk" FOREIGN KEY (pdu_id) REFERENCES pdus(id) ON DELETE CASCADE
"events_pdu_outlet_id_fk" FOREIGN KEY (pdu_outlet_id) REFERENCES pdu_outlet(id)
"events_sensor_id_fk" FOREIGN KEY (sensor_id) REFERENCES sensors(id)
"events_user_id_fk" FOREIGN KEY (clearing_user_id) REFERENCES users(id)
Referenced by:
TABLE "events" CONSTRAINT "events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
TABLE "event_params" CONSTRAINT "events_params_event_id_fk" FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE
Triggers:
event_validate BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE event_validate()
I considered a few workarounds, but I'd really rather know why it's happening. There are a few other tables that also use bigint, so I don't want to just hack a solution in place.
This is scripted with Liquibase, but it happens directly in the Postgres console too.
Update
Two other points:
I can create a simple table with a bigint id and a unique index on id, add the primary key, and the column type stays the same.
All tables are empty at the time execution.
Could it have something to do with the constraints?
That's pretty interesting. I can't reproduce it with version 9.1.0 (yes, I should upgrade too!). But then I don't know precisely how the original table and sequence were created.
This page seems to allude to a similar automatic change of types between SERIAL and INTEGER: http://grover.open2space.com/content/migrate-data-postgresql-and-maintain-existing-primary-key
Could it be something like creating the table using SERIAL instead of BIGSERIAL, and then forcing the type to BIGINT? Something in between the sequence and primary key manipulations might have reset it.
I wasn't able to reproduce this the next day, even after reproducing it multiple times with witnesses the first time it occurred. I'm chalking it up to gremlins.