After I posted my question, I thought of a possible solution.
For concreteness, let's say that this is the table definition for F
:
CREATE TABLE F (
X NUMBER(10) NOT NULL,
Y NUMBER(10) NOT NULL,
CONSTRAINT xy_unique UNIQUE (X, Y)
);
We could replace this F
with tables G
, H
, and I
, defined as follows
CREATE TABLE I (
ID NUMBER(10) PRIMARY KEY
);
CREATE TABLE G (
X NUMBER(10) NOT NULL,
YSET_ID NUMBER(10) NOT NULL,
CONSTRAINT fk_g_yset_id FOREIGN KEY (YSET_ID) REFERENCES I(ID),
CONSTRAINT x_unique UNIQUE (X)
);
CREATE TABLE H (
YSET_ID NUMBER(10) NOT NULL,
Y NUMBER(10) NOT NULL,
CONSTRAINT fk_h_yset_id FOREIGN KEY (yset_id) REFERENCES I(ID),
CONSTRAINT unique_y UNIQUE (Y)
);
The idea is that H
is now a table of "y-sets". Each y-set consists of all the [y]'s corresponding to a given value of H.YSET_ID
. The fundamental difference between F
and H
is that for H
we can define a uniqueness constraint on H.Y
, which ensures that these y-sets are disjoint.
Table I
's only function is to relate G
and H
. (It would be convenient if G.YSET_ID
could refer directly to H.YSET_ID
, rather than indirectly via I.ID
, but my understanding is that a foreign key must always refer to a primary key...)
(I don't know much about Oracle's version of SQL, so this solution is bound to be clumsy, or even syntactically incorrect.)
For example, if F
is
X Y
10 0
10 1
20 2
20 3
20 4
30 0
30 1
...then the corresponding tables G
, H
, and I
could be
G:
X YSET_ID
10 100
20 101
30 100
H:
YSET_ID Y
100 0
100 1
101 2
101 3
101 4
I:
ID
100
101
As pointed out by @ypercubeᵀᴹ, the original F
can be recovered from the new G
, H
, and I
tables with
SELECT G.X, H.Y FROM G JOIN H ON G.YSET_ID = H.YSET_ID;
EDIT: Yet another afterthought: it turns out the there is a surprisingly symmetrical variation of the solution above:
CREATE TABLE I (
ID NUMBER(10) PRIMARY KEY
);
CREATE TABLE G (
X NUMBER(10) PRIMARY KEY,
YSET_ID NUMBER(10) NOT NULL,
CONSTRAINT fk_g_yset_id FOREIGN KEY (YSET_ID) REFERENCES I(ID)
);
CREATE TABLE H (
Y NUMBER(10) PRIMARY KEY,
YSET_ID NUMBER(10) NOT NULL,
CONSTRAINT fk_h_yset_id FOREIGN KEY (yset_id) REFERENCES I(ID)
);
Even though it is not clear from my problem description, a table satisfying the desired constraint expresses a bijective function whose domain and codomain are both sets of disjoint sets. My second solution above makes this symmetry manifest.