You can defer deferrable
constraints until the end of a transaction:
create table a (id serial primary key, b_id bigint);
create table b (id serial primary key, a_id bigint references a(id) deferrable);
alter table a
add constraint fk_b_id foreign key (b_id) references b(id) deferrable;
begin transaction;
SET CONSTRAINTS ALL DEFERRED;
--your `COPY...FROM...WITH` goes here
insert into b values (1,1);--without deferring constraints it fails here
insert into a values (1,1);
commit;
Problem is, you have to make sure your foreign key constraints are deferrable
in the first place - by default they are not, so set constraints all deferred;
won't affect them.
You can do this dynamically for the time of your import (online demo):
CREATE TEMP TABLE queries_to_make_constraints_deferrable AS
SELECT format('alter table %I.%I alter constraint %I deferrable',
v.schemaname, v.tablename, con.conname) as query
FROM pg_catalog.pg_constraint con
INNER JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid
INNER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace
INNER JOIN (VALUES
('public','table1'),--list your tables here
('public','some_other_table'),
('public','a'),
('public','b')) v(schemaname,tablename)
ON nsp.nspname = v.schemaname AND rel.relname=v.tablename
WHERE con.contype='f' --foreign keys
AND con.condeferrable is False; --non-deferrable
do $$
declare rec record;
begin
for rec in select query from queries_to_make_constraints_deferrable
loop execute rec.query;
end loop;
end $$ ;
Carry out your import in a transaction with deferred constraints, then undo your alterations by replacing deferrable
with not deferrable
:
begin transaction;
SET CONSTRAINTS ALL DEFERRED;
--your `COPY...FROM...WITH` goes here
insert into b values (1,1);--without deferring constraints it fails here
insert into a values (1,1);
commit;
do $$
declare rec record;
begin
for rec in select query from queries_to_make_constraints_deferrable
loop execute replace(rec.query,'deferrable','not deferrable');
end loop;
end $$ ;
As already stated, an alternative would be to set up your schema without these constraints and add them after importing the data. That might require you to find and separate them from their table definitions, which again calls for a similar dynamic sql.