【问题标题】:How to enforce a unique list of names associated with a name in another table如何强制执行与另一个表中的名称关联的唯一名称列表
【发布时间】:2022-08-18 21:43:27
【问题描述】:

考虑两个相关的表,T1 和 T2,其中 T2.T1_ID 值指的是 T1.ID 值。 我正在寻找如何使用约束、唯一索引、巧妙的插入/选择或其他一些方法来防止出现与同一 T2.NAMES 列表相关联的重复 T1.NAME。

表 T1

ID   NAME
 1  \'fred\'

表 T2

T1_ID  NAME
  1    \'joe\'
  1    \'jane\'

因此,\'fred\' 与 \'joe\' 和 \'jane\' 相关联。我想要防止插入 T1 和 T2 以便我最终得到多个具有相同关联 T2 名称的 T1 名称。

也就是说,我希望执行以下插入的整体尝试失败:

INSERT INTO T1 (ID, NAME) VALUES (3, \'fred\');
INSERT INTO T2 (T1_ID, NAME) VALUES (3, \'joe\');
INSERT INTO T2 (T1_ID, NAME) VALUES (3, \'jane\');

因为它会导致以下(无效的)表格内容:

表 T1

ID   NAME
 1  \'fred\'
 3  \'fred\'

表 T2

T1_ID  NAME
  1    \'joe\'
  1    \'jane\'
  3    \'joe\'
  3    \'jane\'

也就是说,\'fred\' 将与列表 \'joe\' 和 \'jane\' 关联两次。

请注意,这将是好的因为有一个不同的列表与相同的 T1 NAME 关联的 T2 NAME。也就是说,应该允许以下情况:

INSERT INTO T1 (ID, NAME) VALUES (3, \'fred\');
INSERT INTO T2 (T1_ID, NAME) VALUES (3, \'joe\');
INSERT INTO T2 (T1_ID, NAME) VALUES (3, \'jane\');
INSERT INTO T2 (T1_ID, NAME) VALUES (3, \'kimberly\');

因为它会导致以下结果(有效的) 表格内容:

表 T1

ID   NAME
 1  \'fred\'
 3  \'fred\'

表 T2

T1_ID  NAME
  1    \'joe\'
  1    \'jane\'
  3    \'joe\'
  3    \'jane\'
  3    \'kimberly\'

以下也可以:

INSERT INTO T1 (ID, NAME) VALUES (3, \'fred\');
INSERT INTO T2 (T1_ID, NAME) VALUES (3, \'joe\');

因为它会导致以下结果(有效的) 表格内容:

表 T1

ID   NAME
 1  \'fred\'
 3  \'fred\'

表 T2

T1_ID  NAME
  1    \'joe\'
  1    \'jane\'
  3    \'joe\'
  • 您可以使用开始/提交/回滚事务并在事务内部检查是否会出现这种情况并在必要时回滚。实际语法取决于您使用的 rdbms 产品。
  • 谢谢,@tinazmu!这似乎很有希望。我会试一试。

标签: sql


【解决方案1】:

你应该重新设计你的设计

首先有一个名字表

用户表

ID   NAME
 1  'fred'
 2  'jane'
 3  'joe'
 4  'kimberly'

她的 eon ID 是主 KEY 并且 NAE 被禁止唯一约束

和第二个表关系

FK_ID1 FK_ID2
1      2
1      3
2      4

她你有一个主键(FK ID1,FK ID2)

这将强制 fred 只能与 jane 成为朋友一次,因为添加另一行会违反主键约束

从我的评论:

如果您想知道 Fred 是否与 Jane 有相同的朋友。计数为 0

SELECt Count(*) 
FROM (SELECT FK_ID2 FROM relationships WHERE FK_ID1  = 1) f1 
LEFT JOIN (SELECT FK_ID2 FROM relationships WHERE FK_ID1  = 2) f2 ON  f1.FK_ID2 = f2. FK_ID2 
WHERE f2. FK_ID2 is NULL

这种定义两个实体之间关系的桥表可以包含其他列,但您还应该牢记规范化。

【讨论】:

  • 感谢您的回复,@nbk。但是,如果我理解您的建议,恐怕这对我不起作用,因为只要好友列表不同,我需要让 fred 与 jane 成为两次(或更多)好友。也就是说,fred 也可以与 jane 成为朋友,或者也可以与 jane 和 joe 成为朋友。 (我想友谊在这里不是很恰当的比喻。)
  • 我看不出你为什么需要 joe 2 行,对于更多选项,你可以在第二个表中添加一列或两列来定义附加信息,如果 joe 有相同的朋友,你可以使用SELECt Count(*) FROM (SELECT FK_ID2 FROM relationships WHERE FK_ID1 = 1) f1 LEFT JOIN (SELECT FK_ID2 FROM relationships WHERE FK_ID1 = 2) f2 ON f1.FK_ID2 = f2. FK_ID2 WHERE f2. FK_ID2 is NULL与计数简,如果你想知道乔​​和弗雷德的相同情况,你只需查查身份证,所以基本上所有信息都在那里
猜你喜欢
  • 1970-01-01
  • 2021-12-08
  • 2019-08-31
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 2019-11-11
相关资源
最近更新 更多