删除FK行时可以更改外键ID吗?

时间:2009-06-24 09:13:56

标签: sql-server database tsql

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

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

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

那里的关系相当明显 - 订单需要一个CustomerID,而这是一个外键。因此,我们无法删除客户并保留订单数据。

在示例中,我完全可以丢失冗余的客户数据,但是为了以后的参考,我想将CustomerID从Order更改为“已删除客户”的客户ID。

有没有办法说“删除这个,如果有外键约束,请将CustomerID更改为该ID”?数据库是MS SQL 2005。

6 个答案:

答案 0 :(得分:4)

我会说:

步骤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)

第3步:删除旧客户

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

瞧瞧。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

无论如何,您必须有两个ID:dupCustomerIdnewCustomerId,那么为什么不先更新参考?

UPDATE Order set CustomerID = newCustomerId WHERE CustomerID = dupCustomerId

然后从clients表中删除副本:

DELETE from Customer WHERE ID = dupCustomerId

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

答案 4 :(得分:1)

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

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

使用列

创建/构建查找表
  • CustomerID
  • 订单ID
  • PrimaryCustomerID - (需要计算)

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

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

希望这是有道理的。

答案 5 :(得分:-1)

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