update pg_constraint has no effect (postgres) - postgresql

I tried to change all foreign keys in PostgreSQL at once to cascade on delete:
UPDATE pg_catalog.pg_constraint
SET confupdtype='c', confdeltype='c', confmatchtype='u'
WHERE connamespace=2200;
There are no errors, and when I inspect the tables with pgadmin, it looks right, but when I try to delete a referenced table-line it comes to a constraint error. Just the SQL statement works:
ALTER TABLE tblname
DROP CONSTRAINT IF EXISTS fk3e2e4a8ff123848a;
ALTER TABLE tblname
ADD CONSTRAINT fk3e2e4a8ff123848a FOREIGN KEY (field)
REFERENCES othertable (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE;
Any idea why changing pg_catalog.pg_constraint is not working? even restarting the service after didn't help.

Really you shouldn't be updating pg_* tables.
Use a command like
ALTER TABLE YOURTABLE DISABLE TRIGGER;
Check this link out.
http://archives.postgresql.org/pgsql-general/2011-10/msg00802.php

Related

Drop cascade condition in PostgreSQL

I have a table with a foreign key reference and I had added a on_delete_cascade condition with that foreign key.
I don't need the rows to be deleted even if the foreign key object gets deleted.
How can I change the drop condition without have to drop the column?
Just drop the conatraint and then add it back without the ON DELETE CASCADE clause:
ALTER TABLE some_table DROP CONSTRAINT some_key,
ADD CONSTRAINT some_key FOREIGN KEY (id) REFERENCES tab(a_id);
Check what the real experts wrote by reading here:
https://www.postgresql.org/message-id/CABvLTWHdT0tTygV0-O_ZgLRRAGZAg0W4zvghfF2PshAzvkAaGg%40mail.gmail.com

Postgres - Cascade delete not working

I have a table called "Reviews" and it references a record in a table "ReviewSetups". When I delete a ReviewSetup I was to also delete all child Reviews (so cascade delete).
I have setup the foreign key like below on the Reviews table but nothing gets deleted when I delete a parent ReviewSetup.
I have other entities in by db as well which I migrated with a FK in exactly the same way and those work fine.
Does anyone have an idea what is going on here?
EDIT
Here's the code:
-- Foreign Key: "FK_Reviews_ReviewSetup_Id_ReviewSetups_Id"
-- ALTER TABLE "Reviews" DROP CONSTRAINT "FK_Reviews_ReviewSetup_Id_ReviewSetups_Id";
ALTER TABLE "Reviews"
ADD CONSTRAINT "FK_Reviews_ReviewSetup_Id_ReviewSetups_Id" FOREIGN KEY ("ReviewSetup_Id")
REFERENCES "ReviewSetups" ("Id") MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE;
If you had to drop database again and again, it's better to disable constraints till you find the right culprit or re-design the schema.
Disable constraints and delete data, then re-enable again.
Disable constraints :
Alter table tablename NOCHECK CONSTRAINT constraintname
Enable again:
Alter table tablename CHECK CONSTRAINT constraintname
Ended up dropping the entire db and re-running the migration from scratch. Somehow that solved it. Somewhere, somehow the config was off a bit. Really curious what was the culprit though...

PostgreSQL constraints - ON DELETE CASCADE not being restored

I have run into problems when restoring a PostgreSQL database schema in another server. More precisely, some of the tables don't seem to have the same foreign key constraints associated with them that they used to in the original database. For example, the ON DELETE CASCADE clause seems to have completely evaporated from all of the constraint definitions.
That's probably because the dumping procedure didn't backup the ON DELETE CASCADE clauses in your table definitions.
Firstly you should delete the foreign key constraints on your tables and then go on to altering them:
Something like the following:
ALTER TABLE ONLY *your_table* DROP CONSTRAINT your_constraint;
After that, recreate the constraints with something like:
ALTER TABLE ONLY your_table ADD CONSTRAINT your_constraint (...ON DELETE CASCADE, etc..);

How can use the cascade in Postgresql query while deleting record from parent table

How can we use the cascade in PostgreSQL while deleting the one record from the parent table that is being referred in other child tables. Currently it is giving the syntax error.
ERROR: syntax error at or near "cascade"
LINE 1: DELETE FROM fs_item where itemid = 700001803 cascade;
You have to add ON DELETE CASCADE constraint in following way:
ALTER TABLE table1 ADD CONSTRAINT "tbl1_tbl2_fkey" FOREIGN KEY(reference_key) REFERENCES table2 ON DELETE CASCADE;
Then, you can simply execute the DELETE query
DELETE FROM fs_item where itemid = 700001803
There is no CASCADE for delete statements. You set the foreign key to CASCADE deletes and then it happens for you automatically.

Foreign keys in postgresql can be violated by trigger

I've created some tables in postgres, added a foreign key from one table to another and set ON DELETE to CASCADE. Strangely enough, I have some fields that appear to be violating this constraint.
Is this normal behaviour? And if so, is there a way to get the behaviour I want (no violations possible)?
Edit:
I orginaly created the foreign key as part of CREATE TABLE, just using
... REFERENCES product (id) ON UPDATE CASCADE ON DELETE CASCADE
The current code pgAdmin3 gives is
ALTER TABLE cultivar
ADD CONSTRAINT cultivar_id_fkey FOREIGN KEY (id)
REFERENCES product (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE;
Edit 2:
To Clarify, I have a sneaking suspicion that the constraints are only checked when updates/inserts happen but are then never looked at again. Unfortunately I don't know enough about postgres to find out if this is true or how fields could end up in the database without those checks being run.
If this is the case, is there some way to check all the foreign keys and fix those problems?
Edit 3:
A constraint violation can be caused by a faulty trigger, see below
I tried to create a simple example that shows foreign key constraint being enforced. With this example I prove I'm not allowed to enter data that violates the fk and I prove that if the fk is not in place during insert, and I enable the fk, the fk constraint throws an error telling me data violates the fk. So I'm not seeing how you have data in the table that violates a fk that is in place. I'm on 9.0, but this should not be different on 8.3. If you can show a working example that proves your issue that might help.
--CREATE TABLES--
CREATE TABLE parent
(
parent_id integer NOT NULL,
first_name character varying(50) NOT NULL,
CONSTRAINT pk_parent PRIMARY KEY (parent_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE parent OWNER TO postgres;
CREATE TABLE child
(
child_id integer NOT NULL,
parent_id integer NOT NULL,
first_name character varying(50) NOT NULL,
CONSTRAINT pk_child PRIMARY KEY (child_id),
CONSTRAINT fk1_child FOREIGN KEY (parent_id)
REFERENCES parent (parent_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
)
WITH (
OIDS=FALSE
);
ALTER TABLE child OWNER TO postgres;
--CREATE TABLES--
--INSERT TEST DATA--
INSERT INTO parent(parent_id,first_name)
SELECT 1,'Daddy'
UNION
SELECT 2,'Mommy';
INSERT INTO child(child_id,parent_id,first_name)
SELECT 1,1,'Billy'
UNION
SELECT 2,1,'Jenny'
UNION
SELECT 3,1,'Kimmy'
UNION
SELECT 4,2,'Billy'
UNION
SELECT 5,2,'Jenny'
UNION
SELECT 6,2,'Kimmy';
--INSERT TEST DATA--
--SHOW THE DATA WE HAVE--
select parent.first_name,
child.first_name
from parent
inner join child
on child.parent_id = parent.parent_id
order by parent.first_name, child.first_name asc;
--SHOW THE DATA WE HAVE--
--DELETE PARENT WHO HAS CHILDREN--
BEGIN TRANSACTION;
delete from parent
where parent_id = 1;
--Check to see if any children that were linked to Daddy are still there?
--None there so the cascade delete worked.
select parent.first_name,
child.first_name
from parent
right outer join child
on child.parent_id = parent.parent_id
order by parent.first_name, child.first_name asc;
ROLLBACK TRANSACTION;
--TRY ALLOW NO REFERENTIAL DATA IN--
BEGIN TRANSACTION;
--Get rid of fk constraint so we can insert red headed step child
ALTER TABLE child DROP CONSTRAINT fk1_child;
INSERT INTO child(child_id,parent_id,first_name)
SELECT 7,99999,'Red Headed Step Child';
select parent.first_name,
child.first_name
from parent
right outer join child
on child.parent_id = parent.parent_id
order by parent.first_name, child.first_name asc;
--Will throw FK check violation because parent 99999 doesn't exist in parent table
ALTER TABLE child
ADD CONSTRAINT fk1_child FOREIGN KEY (parent_id)
REFERENCES parent (parent_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE;
ROLLBACK TRANSACTION;
--TRY ALLOW NO REFERENTIAL DATA IN--
--DROP TABLE parent;
--DROP TABLE child;
Everything I've read so far seems to suggest that constraints are only checked when the data is inserted. (Or when the constraint is created) For example the manual on set constraints.
This makes sense and - if the database works properly - should be good enough. I'm still curious how I managed to circumvent this or if I just read the situation wrong and there was never a real constraint violation to begin with.
Either way, case closed :-/
------- UPDATE --------
There was definitely a constraint violation, caused by a faulty trigger. Here's a script to replicate:
-- Create master table
CREATE TABLE product
(
id INT NOT NULL PRIMARY KEY
);
-- Create second table, referencing the first
CREATE TABLE example
(
id int PRIMARY KEY REFERENCES product (id) ON DELETE CASCADE
);
-- Create a (broken) trigger function
--CREATE LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION delete_product()
RETURNS trigger AS
$BODY$
BEGIN
DELETE FROM product WHERE product.id = OLD.id;
-- This is an error!
RETURN null;
END;
$BODY$
LANGUAGE plpgsql;
-- Add it to the second table
CREATE TRIGGER example_delete
BEFORE DELETE
ON example
FOR EACH ROW
EXECUTE PROCEDURE delete_product();
-- Now lets add a row
INSERT INTO product (id) VALUES (1);
INSERT INTO example (id) VALUES (1);
-- And now lets delete the row
DELETE FROM example WHERE id = 1;
/*
Now if everything is working, this should return two columns:
(pid,eid)=(1,1). However, it returns only the example id, so
(pid,eid)=(0,1). This means the foreign key constraint on the
example table is violated.
*/
SELECT product.id AS pid, example.id AS eid FROM product FULL JOIN example ON product.id = example.id;