Suppose I'm trying to represent three types of things -- grandparent, parents, and children. There's a one-to-many relationship between grandparents and parents, and a one-to-many relationship between parents and children. Parents that share a grandparent must have a unique name. The same goes for children, as all children that share a grandparent must have a unique name.
Here's an example schema:
CREATE TABLE grandparent (
grandparentid TEXT PRIMARY KEY,
uniquefield1 TEXT NOT NULL
);
CREATE TABLE parent (
parentid TEXT PRIMARY KEY,
grandparentid TEXT REFERENCES grandparent,
name TEXT NOT NULL,
uniquefield2 TEXT NOT NULL,
UNIQUE (grandparentid, name)
);
CREATE TABLE child (
childid TEXT PRIMARY KEY,
grandparentid TEXT REFERENCES grandparent,
parentid TEXT REFERENCES parent,
name TEXT NOT NULL,
uniquefield3 TEXT NOT NULL,
UNIQUE (grandparentid, name)
);
I'm trying to come up with something that removes the need for the grandparentid
field in the child
table, because I don't want to get into a situation where it disagrees with the contents of the parentid
field. However, I can't just remove it (to the best of my knowledge) because I still need a unique constraint on the pair of grandparentid
and name
.
Also worth noting is that each generation has unique information. It's a bit of a contrived example, because the actual use case is domain-specific and would just obfuscate the problem.
You need to avoid the redundancy that is not controlled by the database but by your app. A single bug in your app can store discrepancies in the data that it would be hard to resolve. Redundancy is OK if it's properly controlled.
You need to include the grandparentid
column in the child
table to ensure uniqueness of the name column in the subset. Now, the key aspect to consider is that you need a composite key in the parent
table that can be referenced from the child
table. This way you will be able to enforce the uniqueness in the child
table and make sure the redundancy is always validated by the database.
For example:
create table grandparent (
grandparentid text primary key,
uniquefield1 text not null
);
create table parent (
parentid text not null,
grandparentid text not null references grandparent (grandparentid),
name text not null,
uniquefield2 text not null,
unique (parentid, grandparentid), -- added this key
unique (grandparentid, name)
);
create table child (
childid text primary key,
grandparentid text not null,
parentid text not null,
name text not null,
uniquefield3 text not null,
unique (grandparentid, name),
foreign key (parentid, grandparentid)
references parent (parentid, grandparentid)
);
Pay attention to the last line:
foreign key (parentid, grandparentid)
references parent (parentid, grandparentid)
This foreign key references a unique constraint in the parent
table.
Using this structure you won't be able to insert a wrong combination of grandparentid
and parentid
. The database just won't have it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.