Each foo must have a bar

From: David Fetter <david(at)fetter(dot)org>
To: PostgreSQL General <pgsql-general(at)postgresql(dot)org>
Subject: Each foo must have a bar
Date: 2006-02-11 20:56:36
Message-ID: 20060211205636.GA6106@fetter.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Folks,

I'm trying to figure out how to enforce the following. Table foo has
a primary key. Table bar has a foreign key to foo. So far so good.
I'd also like to say, "for each row in foo, there must be at least one
row in bar."

I've tried the following, but the check fails too soon. I also tried
an INITIALLY DEFERRED foreign key on bar to foo, trying the INSERT on
bar first, but that didn't work in transaction_isolation LEVEL
SERIALIZABLE.

Any clues?

Cheers,
D

CREATE TABLE foo (
id SERIAL PRIMARY KEY
);

CREATE TABLE bar (
foo_id INTEGER NOT NULL REFERENCES foo(id)
ON DELETE CASCADE
INITIALLY DEFERRED
);

CREATE FUNCTION foo_trg ()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
DECLARE
childless_foo_count INTEGER;
BEGIN
SELECT INTO
childless_foo_count
COUNT(*)
FROM
foo
LEFT JOIN
bar
ON (foo.id = bar.foo_id)
WHERE bar.foo_id IS NULL;
IF childless_foo_count > 0 THEN
RAISE EXCEPTION 'Each foo must have at least one bar.';
END IF;
RETURN NULL;
END;
$$;

CREATE TRIGGER foo_after
AFTER INSERT OR UPDATE ON foo
FOR EACH STATEMENT
EXECUTE PROCEDURE foo_trg();

--
David Fetter david(at)fetter(dot)org http://fetter.org/
phone: +1 415 235 3778

Remember to vote!

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Michael Fuhr 2006-02-11 21:59:48 Re: Each foo must have a bar
Previous Message Johan Vromans 2006-02-11 20:26:57 Re: Last modification time