【问题标题】:Can I change foreign key IDs when deleting the FK row?删除 FK 行时可以更改外键 ID 吗?
【发布时间】:2009-06-24 21:34:37
【问题描述】:

我需要在我们的一个数据库表中创建一个唯一的列,并且我们希望从表中完全删除所有重复项。但是有一个障碍,因为对其他表的大量依赖项会受到影响。

例如,假设我们有以下关系:

-------------------   -------------------
*     Customer    *   *      Order      *
-------------------   -------------------
* ID              *   * ID              *
* Name            *   * CustomerID      *
* Address         *   * Item            *
-------------------   -------------------

那里的关系相当明显——订单需要一个 CustomerID,这是一个外键。所以我们不能删除客户并保留订单数据。

在示例中,我完全可以丢失多余的客户数据,但为了以后参考,我想将 CustomerID 从 Order 更改为“Deleted Customer”行的客户 ID。

有没有办法说“删除这个,如果有外键约束,把 CustomerID 改成那个 ID”?数据库是 MS SQL 2005。

【问题讨论】:

    标签: sql-server database tsql


    【解决方案1】:

    我会说:

    第 1 步:创建要删除的重复 ID 列表以及要保留的相应 ID。 该方法实际上取决于您如何检测重复项。假设你有一张桌子:

    -------------
    *  Dupes    *
    -------------
    * del_id    *
    * keep_id   *
    -------------
    

    第 2 步:重新关联订单

    update order o
    set CustomerID=(select keep_id from Dupes d where d.del_id=o.CustomerID)
    where CustomerID in (select del_id from Dupes)
    

    第三步:删除老客户

    delete from Customer
    where ID in (select del_id from Dupes)
    

    然后瞧。

    【讨论】:

      【解决方案2】:

      AFAIK,它不能在一条 SQL 语句中完成。

      但对于 CUSTOMER 上的 BEFORE DELETE 触发器来说,这听起来很公平。

      您只需要确保这两个操作是一个工作单元。

      【讨论】:

        【解决方案3】:

        可以在客户表上使用删除触发器。 Books online on create trigger.

        但是你为什么不在删除客户之前更新订单记录呢?它更容易,避免了痛苦的触发,而且 IMO 会将逻辑保持在同一个地方。

        【讨论】:

          【解决方案4】:

          无论如何,你必须有两个 id:dupCustomerIdnewCustomerId,所以你为什么不先更新引用呢?

          UPDATE Order set CustomerID = newCustomerId WHERE CustomerID = dupCustomerId
          

          然后从 clients 表中删除重复项:

          DELETE from Customer WHERE ID = dupCustomerId
          

          或者我在这里遗漏了什么?

          【讨论】:

            【解决方案5】:

            您是说您有重复的客户记录,即客户详细信息相同但客户 ID 不同,因此存在引用同一客户的多个版本的订单?

            如果是这样,我会进行数据清理练习

            使用列创建/构建查找表

            • 客户 ID
            • 订单编号
            • PrimaryCustomerID -(需要计算)

            然后您可以对 Orders 表执行更新,以确保每个 Order 仅引用 PrimaryCustomerID。

            然后,您可以删除订单不再引用的客户记录(即它们是重复的)。或者,您可以向 Customer 表添加一个属性以标记记录而不是删除(即 duplicateFlag 或 isDeleted)。

            希望这是有道理的。

            【讨论】:

              【解决方案6】:

              我们已经构建了一个重复数据删除工具(您也应该如此),它首先查找存在数据冲突的地方(例如两个不同的企业电话号码),并允许执行重复数据删除的人员选择正确的数据。然后,该工具将 id 更改为您保留的 id,从最底部的子表开始并遍历所有相关表。一旦删除了对它正在删除的记录的所有引用,它就会删除父记录。重复数据删除通常是一个复杂的过程,应仔细设计此工具以处理需要处理的内容,并允许在添加新外键表时更改工具。您可以将其设置为在发生数据冲突时选择您保存的记录中的信息,但在没有人工干预的情况下这样做通常是一个糟糕的主意。这是因为您经常需要了解客户的人的意见。否则,您最终可能会用坏地址替换好地址。这是 dup 最初是如何到达那里的常见场景。客户 A 成为客户有一段时间了,有几个订单。他再次下订单,接单员要求提供他的电话号码或其他一些可识别信息以帮助查找他。客户 A 最近搬家并拥有新的电话号码和地址,因此找不到他并创建了新记录。后来发现它是重复的,但自动重复数据删除过程会选择较旧的记录,因为它有更多的订单,因此用当前的新地址和电话替换记录。客户再次打电话订购并创建另一个重复,因为订单接受者再次找不到他。这就是为什么我强烈认为重复数据删除必须是部分手动过程。

              【讨论】:

                猜你喜欢
                • 2015-03-09
                • 2016-09-16
                • 1970-01-01
                • 1970-01-01
                • 2017-10-20
                • 1970-01-01
                • 1970-01-01
                • 2013-03-24
                • 2014-10-27
                相关资源
                最近更新 更多