Необходимость использования отложенных ограничений часто указывает на проблемы проектирования. Конечно, эта модель данных не очень хорошая: она не нормализована должным образом. Нормализованное решение будет выглядеть так:
PERSON
------
ID number
NAME varchar2(30)
PRIMARY KEY (ID)
MARRIED_COUPLE
--------------
PARTNER_1 number
PARTNER_2 number
PRIMARY KEY (PARTNER_1, PARTNER_2)
FOREIGN KEY (PARTNER_1) REFERENCES (PERSON.ID)
FOREIGN KEY (PARTNER_2) REFERENCES (PERSON.ID)
Это дает дополнительное преимущество поддержки гражданских партнерств :) Если вы хотите препятствовать двоеженству, вы можете добавить уникальные ключи на PARTNER_1 или PARTNER_2.
Сложнее моделировать культуры, где допускается многоженство или полиандрия.
редактировать
На что Дэвид возражает (в комментариях):
SQL> create table married_couple (partner_1 number, partner_2 number)
2 /
Table created.
SQL> alter table married_couple add primary key (partner_1, partner_2)
2 /
Table altered.
SQL> insert into married_couple values (1, 2)
2 /
1 row created.
SQL> insert into married_couple values (2,1)
2 /
1 row created.
SQL>
Это верная точка, но она разрешима. Например, с Oracle я могу создать уникальную функцию на основе, чтобы обеспечить уникальность перестановок.
SQL> delete from married_couple
2 /
2 rows deleted.
SQL> create unique index mc_uidx on married_couple
2 (greatest(partner_1, partner_2),least(partner_1, partner_2))
3 /
Index created.
SQL> insert into married_couple values (1, 2)
2 /
1 row created.
SQL> insert into married_couple values (2,1)
2 /
insert into married_couple values (2,1)
*
ERROR at line 1:
ORA-00001: unique constraint (APC.MC_UIDX) violated
SQL>
Чтобы избежать многоженства, мы можем использовать аналогичный прием. Мы не хотим этого:
SQL> insert into married_couple values (1,3)
2 /
1 row created.
Итак, нам нужны два индекса:
SQL> delete from married_couple where partner_2 = 3;
1 row deleted.
SQL> create unique index mc1_uidx
2 on married_couple (greatest(partner_1, partner_2))
3 /
Index created.
SQL> create unique index mc2_uidx
2 on married_couple (least(partner_1, partner_2))
3 /
Index created.
SQL> insert into married_couple values (3, 1)
2 /
insert into married_couple values (3, 1)
*
ERROR at line 1:
ORA-00001: unique constraint (APC.MC2_UIDX) violated
SQL>
Для тех, кто думает, что это обман для решения проблемы моделирования данных с помощью хитрости реализации, я умоляю «Виновен как обвиненный», но у меня был долгий и трудный день.