Re: Constraint for two fields unique any order

From: MargaretGillon(at)chromalloy(dot)com
To: Reece Hart <reece(at)harts(dot)net>
Cc: pgsql-general <pgsql-general(at)postgresql(dot)org>
Subject: Re: Constraint for two fields unique any order
Date: 2006-07-19 23:26:42
Message-ID: OFAA3CE1BA.D2C1F627-ON882571B0.0080625E-882571B0.0080C5C4@CHROMALLOY.COM
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

> On Wed, 2006-07-19 at 09:01 -0700, MargaretGillon(at)chromalloy(dot)com wrote:
> > I have a junction table that is recording relationships between two
> > records in another table. Is there a way that I can create a
> > constraint so that the values are not repeated in any order? I want to
> > make sure that rows such as 2 and 4 in the example below cannot
> > happen. This is a very small table that is meta data for an
> > application. It is only 41 rows now and probably won't grow beyond 200
> > rows. I am on Postgresql ver 7.3.4 .
> >
> > id fkey1 fkey2
> > 1 3 4
> > 2 10 4
> > 3 2 7
> > 4 4 10
> > 5 15 8
>
>
> I can think of two solutions with slightly different semantics.
>
> 1) If the directionality of the association is immaterial, then the
> easiest approach is to impose the convention that rows always satisfy
> fkey1<fkey2 and then create a unique index on (fkey1,fkey2). At a
> minimum, you should have a check constraint verify this condition. You
> might consider writing a trigger for insert and update to swap fkey1 and
> fkey2 when necessary.
>
> For example:
> create table jx1 (
> id serial primary key,
> fkey1 integer not null,
> fkey2 integer not null,
> constraint jx1_invalid_key_order check (fkey1<fkey2),
> constraint jx1_unique_association unique (fkey1,fkey2)
> );
>
>
> 2) If you care about directionality and really seek to preclude
> symmetric relationships (as in a family tree), then create a unique
> index on the reordered pairs, like this:
>
> create table jx2 (
> id serial primary key,
> fkey1 integer not null,
> fkey2 integer not null
> );
> create or replace function jx_reorder(integer,integer) returns text
> strict immutable language sql as
> 'SELECT CASE WHEN $1<$2 THEN $1||''-''||$2 ELSE $2||''-''||$1 END';
> create unique index jx2_no_symmetric_reln on jx2
(jx_reorder(fkey1,fkey2));
>
>
> These should work fine on 7.3.4, but I didn't verify that. You should
> consider upgrading.
>
>
> -Reece
>
> --
> Reece Hart, http://harts.net/reece/, GPG:0x25EC91A0
>

Thanks for the suggestions Reece. Some of the pairs are aleady being used
in code so I don't know if I can reverse the order to create the
fkey1<fkey2 condition. I'm going to check my code tomorrow and see if I
can rearrange the keys without too much impact on the software. I also
need to verify that I'll never have a pair where fkey1 = fkey2.

Margaret Gillon

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Paul S 2006-07-20 00:22:38 Re: Difference between function and procedure?
Previous Message Eric Faulhaber 2006-07-19 22:06:08 Re: UTF8 conversion differences from v8.1.3 to v8.1.4