Only enforce constraint for new entries in fields_new
CHECK
constraints are supposed to be immutable, which generally rules out any kind of reference to other tables, which are not immutable by nature.
To allow some leeway (especially with temporal functions) STABLE
functions are tolerated. Obviously, this cannot be completely reliable in a database with concurrent write access. If rows in the referenced table change, they may be in violation of the constraint.
Declare the invalid nature of your constraint by making it NOT VALID
(Postgres 9.1+). This way Postgres also won't try to enforce it during a restore (which might be bound to fail). Details here:
The constraint is only enforced for new rows.
CREATE OR REPLACE FUNCTION f_fields_name_free(_name text)
RETURNS bool AS
$func$
SELECT NOT EXISTS (SELECT 1 FROM fields WHERE name = $1);
$func$ LANGUAGE sql STABLE;
ALTER TABLE fields_new ADD CONSTRAINT fields_new_name_not_in_fields
CHECK (f_fields_name_free(name)) NOT VALID;
Plus, of course, a UNIQUE
or PRIMARY KEY
constraint on fields_new(name)
as well as on fields(name)
.
Related:
Enforce both ways
You could go one step further and mirror the above CHECK
constraint on the 2nd table. Still no guarantees against nasty race conditions when two transactions write to both tables at the same time.
Or you could maintain a "materialized view" manually with triggers: a union of both name
columns. Add a UNIQUE
constraint there. Not as rock solid as the same constraint on a single table: there might be race conditions for writes to both tables at the same time. But the worst that can happen is a deadlock forcing transactions to be rolled back. No permanent violation can creep in if all write operations are cascaded to the "materialized view".
Similar to the "dark side" in this related answer:
Just that you need triggers for INSERT
/ UPDATE
/ DELETE
on both tables.