请问,如下我们在定义Link表的时候,是否是只能定义为4个字段?

定义关系型数据库表的时候,遇到一个疑问:

Node表 {
  id: number,
  label: string
}

Comb表 {
  id: number,
  label: string
}


Link表 {
  source: // 这里可以是Node表的实例也可以是Comb表的实例
  target: // 这里可以是Node表的实例也可以是Comb表的实例
}

请问,我们在定义Link表的时候,是否是只能定义为4个字段?

Link表 {
  nodesource: Node,
  nodetarget: Node,
  combsource: Comb,
  combtarget: Comb, 
}
阅读 2.6k
avatarAI BotBETA

答案

不,在定义 Link 表时,你不需要(也不应该)定义为包含四个字段,每个字段分别对应 NodeComb 表的实例。这样做会导致数据冗余和复杂性增加。

一个更合理的做法是使用外键(foreign keys)和类型标识符来建立这种多对多的关系,同时保持数据的简洁性和完整性。例如:

Link 表 {
  id: number,
  sourceType: string,  // "Node" 或 "Comb"
  sourceId: number,    // 引用 Node 或 Comb 表的 id
  targetType: string,  // "Node" 或 "Comb"
  targetId: number     // 引用 Node 或 Comb 表的 id
}

在这种设计中,sourceTypetargetType 字段用于指示 sourceIdtargetId 分别引用的是 Node 表还是 Comb 表。这种方法可以有效地处理 NodeComb 之间的复杂关系,同时避免了不必要的字段和数据冗余。

2 个回答

你的需求是让 Link 表中的 source 和 target 字段能够引用 Node 表或 Comb 表的实例。直接定义为四个字段虽然可以实现,但并不是最优雅的解决方案。

使用单表继承(Single Table Inheritance, STI)多表继承(Class Table Inheritance, CTI) 来处理这种情况。

单表继承(STI)

你可以创建一个通用的 Entity 表,然后让 Node 和 Comb 表继承自 Entity 表。这样,Link 表只需要引用 Entity 表即可。

CREATE TABLE Entity (
  id INT PRIMARY KEY,
  type VARCHAR(50),
  label VARCHAR(255)
);

CREATE TABLE Link (
  id INT PRIMARY KEY,
  source_id INT,
  target_id INT,
  FOREIGN KEY (source_id) REFERENCES Entity(id),
  FOREIGN KEY (target_id) REFERENCES Entity(id)
);

在这种设计中,Node 和 Comb 表的数据都存储在 Entity 表中,通过 type 字段区分。

多表继承(CTI)

你可以创建一个 Link 表,其中 source 和 target 字段分别引用 Node 和 Comb 表的主键。

CREATE TABLE Link (
  id INT PRIMARY KEY,
  source_node_id INT,
  source_comb_id INT,
  target_node_id INT,
  target_comb_id INT,
  FOREIGN KEY (source_node_id) REFERENCES Node(id),
  FOREIGN KEY (source_comb_id) REFERENCES Comb(id),
  FOREIGN KEY (target_node_id) REFERENCES Node(id),
  FOREIGN KEY (target_comb_id) REFERENCES Comb(id)
);

在这种设计中,你需要确定 source_node_id 和 source_comb_id 以及 target_node_id 和 target_comb_id 之间的约束关系,以避免数据不一致。

数据来那个不大前两个方案,数据量大就用后面两个试试
1.用一个 source 和一个 target 字段,外再加一个类型字段

Link表 {
  id: number,
  source_id: number,
  source_type: string, 
  target_id: number,
  target_type: string, 
}

用两个外键字段,允许为空

Link表 {
  id: number,
  node_source_id: number, // 引用 Node 表,允许为空
  comb_source_id: number, // 引用 Comb 表,允许为空
  node_target_id: number, // 引用 Node 表,允许为空
  comb_target_id: number, // 引用 Comb 表,允许为空
}

用继承或类似继承的表结构
这个要建三个表:

BaseNode表 { 
  id: number,
  type: string, // 例如:'Node' 或 'Comb'
  // 其他 Node 和 Comb 共有的属性
}

Node表 {
  id: number, // 引用 BaseNode 表
  label: string,
  // 其他 Node 特有的属性
}

Comb表 {
  id: number, // 引用 BaseNode 表
  label: string,
  // 其他 Comb 特有的属性
}

Link表 {
  id: number,
  source_id: number, // 引用 BaseNode 表
  target_id: number, // 引用 BaseNode 表
}

用 JSON


Link表 {
  id: number,
  source: JSON, // 例如:{'type': 'Node', 'id': 1}
  target: JSON, // 例如:{'type': 'Comb', 'id': 2}
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏