【问题标题】:在 SQL 中将一对多关系转换为一对一
【发布时间】:2022-01-23 05:31:55
【问题描述】:

我有两张桌子,A 和 B 表 A: 标识整数 Id_B int (FK with B)

表 B: 身份证

当前状态:表A中的一个Id可以有多个Id_B关系,表A中的两个Id可以有相同的Id_B

新状态:我希望使表 A 中的两个 Id 不能具有相同的 Id_b。如果我找到这样的关系,则在表 B 中创建一个新的 Id 并将其链接到表 A 中的 Id 以强制执行上述约束

我不知道在 SQL 中从哪里开始。

之前

表 A

Id Id_B
1 1
1 4
2 1
3 2
4 3

表 B

Id
1
2
3
4

之后(由于Id_B列中出现了两次1,我在表B中创建了一个新行(id为5),并将其的Id分配给表A中的Id 2以强制唯一性)

表 A

Id Id_B
1 1
1 4
2 5
3 2
4 3

表 B

Id
1
2
3
4
5

【问题讨论】:

  • 通常我们通过创建一个位于 A 和 B 之间的表(可能称为 AB)并将 A 映射到 B 来将 M:M 分解为两个 1:M。它最终可能会获得更多的列并成为一个“适当的”表,而不仅仅是一个映射 A:B
  • 您的要求更改不足以删除M:M 要求。您可以通过在M:M 映射表中添加UNIQUE (id_b) 来处理约束,这样(id_a, id_b) 对将不会多次使用特定的id_b。确保添加 M:M 映射表。
  • 也就是说,我在这里看不到的是 M:M;对于 TableA 有一个 ID_B 列,这意味着 A 只能映射到一个 B。一个 B 可以映射到许多不同的 A,但似乎没有 M:M 机制。任何给定的 A 行如何链接到 B 中的多行?您是否禁用了 A 中的主键,这样您有两个 A 行具有相同的 ID 值,具有不同的 ID_B 值,并且您仅根据 ID 值将它们视为“相同的 A 行”?
  • 我希望使表 A 中的两个 Id 不能具有相同的 Id_b - 然后您希望使 A:B 为 1:1 或 1:0 ..1 如果 ID_b 可以为空?我认为也许您需要考虑您希望这些表具有什么关系(如果它们有帮助,将它们称为真实姓名也可能会有所帮助;与 A 相比,可视化 Orders 和 Products 之间的对象图映射要容易得多和 B..)
  • 我已经更新了示例以显示表 A 如何具有相同的 Id 指向表 B 中的两个不同的 Id

标签: sql sql-server


【解决方案1】:
  1. 查找所有重复的 A.B_ID 行,为重复项添加新的 B 行并更新相应的 A.B_ID。

从如下查询开始:

with q as 
(
  select *, row_number() over (partition by B_ID, order by ID) rn
  from A
)
select * 
from q
where rn > 1
  1. 在 A.B_ID 上添加唯一约束

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    相关资源
    最近更新 更多