簡體   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