Let's say we have these tables:
CREATE TABLE A (
id SERIAL NOT NULL PRIMARY KEY
);
CREATE TABLE B (
id SERIAL NOT NULL PRIMARY KEY
);
CREATE TABLE Parent (
id SERIAL NOT NULL PRIMARY KEY,
aId INTEGER NOT NULL REFERENCES A (id),
bId INTEGER NOT NULL REFERENCES B (id),
UNIQUE(aId, bId)
);
CREATE TABLE Child (
parentId INTEGER NOT NULL REFERENCES Parent (id),
createdOn TIMESTAMP NOT NULL
);
Is it possible to create a unique constraint on Child
such that for all rows in Child
at most one references a Parent
having some value of aId
? Stated another way can I created a unique constraint so that the join of the above tables will have no duplicate aId
? I'm thinking not--the grammars of every database I could find seem tied to one table per constraint--but that might be a lack of imagination on my part. (De-normalizing to include aId
on Child
is one solution, of course.)
A PRIMARY KEY constraint automatically has a UNIQUE constraint. However, you can have many UNIQUE constraints per table, but only one PRIMARY KEY constraint per table.
To define a UNIQUE constraint, you use the UNIQUE keyword followed by one or more columns. You can define a UNIQUE constraint at the column or the table level. Only at the table level, you can define a UNIQUE constraint across multiple columns.
You can add the same constraint, but not with the same name.
If you create a unique constraint then by default a non-clustered Index has been created. You can create a maximum of 999 (Non-Clustered Indexes) per table as per limitations. You can create 999 Unique constraints per table.
You could try the following. You have to create a redundant UNIQUE constraint on (id, aId)
in Parent (SQL is pretty dumb isn't it?!).
CREATE TABLE Child
(parentId INTEGER NOT NULL,
aId INTEGER NOT NULL UNIQUE,
FOREIGN KEY (parentId,aId) REFERENCES Parent (id,aId),
createdOn TIMESTAMP NOT NULL);
Possibly a much better solution would be to drop parentId from the Child table altogether, add bId
instead and just reference the Parent table based on (aId, bId)
:
CREATE TABLE Child
(aId INTEGER NOT NULL UNIQUE,
bId INTEGER NOT NULL,
FOREIGN KEY (aId,bId) REFERENCES Parent (aId,bId),
createdOn TIMESTAMP NOT NULL);
Is there any reason why you can't do that?
The proper way to do this would be to do away with the Child
table altogether and put the createdOn
column in the Parent
table, without the NOT NULL
constraint. All you are saying is that one Parent
entry can have zero or one (but not more) createdOn
values. You don't need a separate table for that. The fact that it is not easy or obvious to do otherwise partially proves my point. ;-) SQL usually works out that way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With