sql—删除主键与其他表连接的重复行

yftpprvb  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(254)

某个进程导致表中不应有重复行的表中出现重复行。在线删除重复行有几个很好的答案。但是,如果那些具有id主键的副本在其他表中都有数据绑定到它们呢?
有没有办法删除第一个表中的所有重复项,并将绑定到这些键的所有数据迁移到未删除的单个pk id?
例如:

  1. TABLE 1
  2. +-------+----------+----------+------------+
  3. | ID(PK)| Model | ItemType | Color |
  4. +-------+----------+----------+------------+
  5. | 1 | 4 | B | Red |
  6. | 2 | 4 | B | Red |
  7. | 3 | 5 | A | Blue |
  8. +-------+----------+----------+------------+
  9. TABLE 2
  10. +-------+----------+---------+
  11. | ID(PK)| OtherID | Type |
  12. +-------+----------+---------+
  13. | 1 | 1 | Type1 |
  14. | 2 | 1 | Type2 |
  15. | 3 | 2 | Type3 |
  16. | 4 | 2 | Type4 |
  17. | 5 | 2 | Type5 |
  18. +-------+----------+---------+

所以理论上我想从表1中删除id为2的条目,然后让表2中的otherid字段切换到1。这实际上是x个表所需要的。这种特殊情况有4个表连接到它的id pk。

jaxagkaj

jaxagkaj1#

您不能自动执行此操作。但您可以通过一些查询来实现这一点。首先,将所有外键设置为正确的id,这可能是最小的id:

  1. with ids (
  2. select t1.*, min(id) over (partition by Model, ItemType, Color) as min_id
  3. from table1 t1
  4. )
  5. update t2
  6. set t2.otherid = ids.min_id
  7. from table2 t2 join
  8. ids
  9. on t2.otherid = ids.id
  10. where ids.id <> ids.min_id;

然后删除中重复或未引用的ID table2 (取决于你真正想要的):

  1. with ids (
  2. select t1.*, min(id) over (partition by Model, ItemType, Color) as min_id
  3. from table1 t1
  4. )
  5. delete from ids
  6. where id <> min_id;

注意:如果数据库有并发用户,您可能希望将其置于单用户模式下执行此操作,或者锁定表,以便在这两个操作期间不修改它们。

展开查看全部
dy1byipe

dy1byipe2#

要做到这一点,您需要将所有内容打包到单个事务中,并在常规维护期间执行此操作。其他任何事情都会让事情变得像现在这样不一致。
决定你要用哪把“钥匙”。
更新所有子表以使用新的“键”,其中值是旧的“键”。
重复记录上不应有fk依赖项,请删除它们。
一旦所有的歧义都解决了,就在 (ItemType,Color) (或者不管真正的列是什么)。
如果有很多示例,您可能需要编写一个脚本来处理这个问题,并使用中的信息 sys.foreign_keys 以及 sys.foreign_key_columns 确定要更新哪些记录以及更新顺序。

相关问题