How to set FOREIGN KEY (packet_id) REFERENCES girvi_packet(id) DEFERRABLE INITIALLY DEFERRED to NULL ?
If parent get deleted postgreSQL raises error that parent is missing I want to suppress this behavior. This constraint is added by default by some 3rd part tool. But my use case demands otherwise.
The purpose of the foreign key is to prevent orphan children. The only way you can do is to delete the constrain
ALTER TABLE ... DROP CONSTRAINT ...
Related
I have a table named base_types that contains this constraint:
ALTER TABLE public.base_types
ADD CONSTRAINT base_type_gas_type_fk FOREIGN KEY (gas_type)
REFERENCES public.gas_types (gas_type) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED;
And I have a table named alarm_history that contains five constraints, including this one:
ALTER TABLE public.alarm_history
ADD CONSTRAINT alarm_history_device_fk FOREIGN KEY (device)
REFERENCES public.bases (alarm_device) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED;
I am trying to convert a database from one that didn't bother with anything weird and useless like constraints into one that uses them. I am beginning with this script:
delete from gas_types;
select conversion.convert_base_types();
alter table base_types validate constraint base_type_gas_type_fk;
select conversion.convert_alarm_history();
alter table alarm_history validate constraint alarm_history_base_fk;
alter table alarm_history validate constraint alarm_history_charge_fk;
alter table alarm_history validate constraint alarm_history_cooler_fk;
alter table alarm_history validate constraint alarm_history_device_fk;
alter table alarm_history validate constraint alarm_history_furnace_fk;
I duly get an error message telling me that the gas_type field in my new base_types record doesn't match anything in the gas_types table, since the gas_types table is empty. But if I comment out the base_types commands, I get 18,000 nice, shiny new records in the alarm_history table, despite the fact that every single one of them violates at least one of that table's five foreign key constraints, since all of the tables those keys are referring to are empty. I need to ensure that my converted data is consistent, and therefore I need to validate my constraints, but that's obviously not happening. Why not?
Since the constraints above are created as DEFERRABLE INITIALLY DEFERRED, they are not checked until the DML statements (your delete statement) are committed or in your case you until you explicitly validate the constraint.
This is the normal and expected operation of an initially deferred deferrable constraint.
To change this functionality within your current transaction you can issue a SET CONSTRAINTS command to alter this:
SET CONSTRAINTS alarm_history_device_fk IMMEDIATE;
delete from gas_types;
Which should raise a foreign key violation alerting you earlier that you have data dependent on the records you are tying to delete.
When dropping constraints from a postgres table , How to know the safest order to drop the constraints. Like ,
1) The foreign key constraints can be dropped first [as they have to be droppped before primary key constraint]
Then the order of removing the constraints can be in any order . like check constraint, unique constraint, not nulls, default , primary key constraints . Am I correct
No constraint on a PostgreSQL table depends on another constraint on the same table, so the order does not matter here.
The only dependency between constraints is the dependency of a foreign key on the primary or unique key on the target table.
So you can either remove all foreign key constraints first and then all other constraints, or you can use ALTER TABLE ... DROP CONSTRAINT ... CASCADE which will automatically drop all dependent constraints, then you don't have to care about the order at all.
In order to delete some rows referenced by a foreign key constraint without cascading on delete, I created a temporary foreign key constraint, deleted the row, and then deleted the temporary constraint:
ALTER TABLE rel_user_right
ADD CONSTRAINT temp_fk_rel_user_right_user_right_02
FOREIGN KEY (right_id) REFERENCES user_right (id)
ON DELETE CASCADE;
DELETE FROM user_right WHERE "name" LIKE '%.statusLight.%';
ALTER TABLE rel_user_right
DROP CONSTRAINT temp_fk_rel_user_right_user_right_02;
where this table already had the following constraint defined on it:
ALTER TABLE rel_user_right
ADD CONSTRAINT fk_rel_user_right_user_right_02
FOREIGN KEY (right_id) REFERENCES user_right (id);
This worked fine for me, but seems to have failed on my colleague's computer. As you can see, the two FK constraints define conflicting ON DELETE behaviour. Is precedence defined in this situation, or is it non-deterministic?
Postgres allows to create two references differing only in ON DELETE clause.
I could find no information on the impact of such a case.
In my tests I was unable to cover the existing constraint with new one (i.e. DELETE was always restricted despite of the existence of the second cascading constraint).
However this behaviour is undocumented and one should not rely on it.
The normal way to proceed should be replacing the old constraint with new one:
ALTER TABLE rel_user_right
ADD CONSTRAINT fk_rel_user_right_user_right_temp
FOREIGN KEY (right_id) REFERENCES user_right (id)
ON DELETE CASCADE,
DROP CONSTRAINT fk_rel_user_right_user_right;
DELETE FROM user_right WHERE "name" LIKE '%.statusLight.%';
ALTER TABLE rel_user_right
ADD CONSTRAINT fk_rel_user_right_user_right
FOREIGN KEY (right_id) REFERENCES user_right (id),
DROP CONSTRAINT fk_rel_user_right_user_right_temp;
DISABLE CONSTRAINT would be useful here, but there is no such feature in Postgres (there have been attempts to implement it, but they did not end in success). You can use DISABLE TRIGGER for it, but the above solution is simpler and more natural.
As I understand, if I delete a parent row, its children should be deleted if I turn on cascade on delete. However, from my testing, it doesn't seem to work at all. No matter if I set WillCascaseOnDelete to true or false, it simply sets the foreign key of its children to null. This is causing another problem that I have to set the foreign key nullable, otherwise, SaveChange will throw exception. Is this a defect or desired behavior?
This is because your foreign keys (child) are nullable. By default, when deleting parent, if the foreign key on the relationship is nullable EF will delete the parent and set the foreign key to null. If the foreign key is NOT NULL it will delete the child (the behaviour you're looking for?).
You can alter this default behaviour here
Make sure on the Foreign Key Relationship window in SQL Server, you have selected Cascade as Delete rule.
I'm inserting a value in table A, that has a serial type as primary key. I wanna use the returned value of the query as a foreign key of table B... but I get this message:
ERROR: insert or update on table "tb_midia_pessoa" violates foreign key constraint "tb_midia_pessoa_id_pessoa_fkey" DETAIL: Key (id_pessoa)=(30) is not present in table "tb_pessoa". )
How can I make this possible without:
starting a new Transaction
droping my foreign keys constraints =O
?
Regards!
Pedro
You can make a deferrable FK, just use DEFERRABLE and maybe INITIALLY DEFERRED, that's up to you.
http://www.postgresql.org/docs/current/static/sql-createtable.html
The statement below allows non-deferrable constraints to be deferred until transaction committed. If you don't want to change FK definitions.
SET CONSTRAINTS ALL DEFERRED;