繁体   English   中英

嵌套一对多关系的唯一约束

[英]Unique constraint on nested one-to-many relationship

假设我试图代表三种类型的事物——祖父母、父母和孩子。 祖父母和父母之间是一对多的关系,父母和孩子之间是一对多的关系。 共享一个祖父母的父母必须有一个唯一的名字。 孩子也是如此,因为所有共享祖父母的孩子都必须有一个唯一的名字。

这是一个示例架构:

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)
);

我试图想出一些东西来消除child表中的grandparentid字段的需求,因为我不想陷入与parentid字段的内容不一致的情况。 但是,我不能只是删除它(据我所知),因为我仍然需要对grandparentidname对的唯一约束。

另外值得注意的是,每一代都有独特的信息。 这是一个人为的例子,因为实际用例是特定于域的,只会混淆问题。

您需要避免不是由数据库控制而是由您的应用程序控制的冗余。 应用程序中的单个错误可能会存储难以解决的数据差异。 如果控制得当,冗余是可以的。

您需要在child表中包含grandparentid列以确保子集中名称列的唯一性。 现在,要考虑的关键方面是parent表中需要一个可以从child表中引用的复合键 通过这种方式,您将能够在child表中强制执行唯一性,并确保数据库始终验证冗余。

例如:

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)
);

注意最后一行:

  foreign key (parentid, grandparentid) 
     references parent (parentid, grandparentid)

此外键引用parent表中的唯一约束。

使用此结构,您将无法插入错误的grandparentidparentid组合。 数据库就是没有它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM