(Sorry for my bad english comments) Demo sql: BEGIN; -- Begins the magic CREATE TABLE pk ( -- pk table id BIGINT, CONSTRAINT pk2_id PRIMARY KEY (id) );
CREATE TABLE fk ( -- fk table fk_ids BIGINT[] ); CREATE FUNCTION bia2bi(bigint[]) RETURNS bigint -- temp type cast AS $$ SELECT $1[array_lower($1, 1)]; $$ LANGUAGE sql; CREATE FUNCTION bi_fk(bigint, bigint[]) RETURNS boolean --FK FUNCTION FOR TABLE pk AS $$ BEGIN IF (SELECT count(*) FROM pk WHERE id = ANY($2)) = (array_upper($2, 1) - array_lower($2, 1) + 1) THEN RETURN TRUE; END IF; RAISE EXCEPTION 'NO FK![%, %]', $1, $2; -- RAISE ERROR MSG, and dont scan other million records END; $$ LANGUAGE 'plpgsql'; CREATE OPERATOR ==> ( -- Cutsom operator for calling bi_fk PROCEDURE = bi_fk, LEFTARG = bigint, RIGHTARG = bigint[]); CREATE CAST (bigint[] AS bigint) -- TEMP CAST FOR INDEX CREATION WITH FUNCTION bia2bi(bigint[]) AS IMPLICIT; ALTER TABLE "fk" -- CREATE FK ADD CONSTRAINT "fk_id" FOREIGN KEY ("fk_ids") REFERENCES "pk"("id") ON DELETE NO ACTION ON UPDATE NO ACTION NOT DEFERRABLE; DROP CAST(bigint[] AS bigint); -- REMOVE CAST(recomended, but not needed) UPDATE pg_constraint SET conpfeqop = ARRAY(SELECT OID FROM pg_operator WHERE oprname = '==>') WHERE conname = 'fk_id'; -- CHANGING COMPARE FUNCTION INSERT INTO pk SELECT k FROM GENERATE_series(1, 100000) as k; -- MAKE DATA INSERT INTO fk VALUES(ARRAY[1,2, 3]); -- TESTING INSERT INTO fk VALUES(ARRAY[6,3,5]); -- TESTING INSERT INTO fk VALUES(ARRAY[6,3,444444444444444445]); -- FK BREAK. ROLLBACK; -- Magic rollback =)