当列已经包含数据时,将列升级为外键

时间:2013-12-19 16:57:29

标签: sql sql-server foreign-keys

我正在使用SQL Server Management Studio中的数据库,我有两个表,Route和Tractor(这是一个简化的例子)。目前,Route表包含一个名为TractorID的列。它不是Tractor表的ID列的外键或索引,但在我们的应用程序中使用它来按其ID搜索Tractor表。这使我们的用户过去可以删除拖拉机,而不会影响拖拉机使用的任何路线。

我现在正在升级数据库,以便TractorID列是Tractor表的ID列的外键,但我遇到了一个问题。由于用户一直在删除拖拉机并且未在路径表中更新,因此TractorID中有一些路径不再存在于Tractor表中。我需要事先将这些假ID设置为null,以便我可以将列升级为外键。

我使用以下声明完成了这项工作:

UPDATE Route SET Route.TractorID = NULL 
WHERE Route.TractorID IS NOT NULL AND NOT EXISTS(SELECT * FROM Tractor 
WHERE Tractor.ID = Route.TractorID)

到目前为止,这句话似乎已经成功了,但我担心它的效率如何。我们有一些数据库,每个月需要升级250万条路线。我认为这个子查询触发每一行,所以我希望找到一个可能涉及将路由和拖拉机表连接在一起的解决方案(JOIN Tractor ON Route.TractorID = Tractor.ID),然后将TractorID设置为{{1}如果该行的连接不成功(即NULL与任何TractorID都不匹配。)

这可能吗?或者我目前的解决方案是否足够好?提前谢谢。

2 个答案:

答案 0 :(得分:1)

第一步是确保路由表中的TractorID列有索引。

CREATE NONCLUSTERED INDEX IX_Route_TracorID ON Route(TractorID)

对于更新,您可以使用左外连接查找所有孤立的TractorID并将它们设置为NULL

UPDATE Route
SET TractorID = NULL
FROM Route AS R
LEFT OUTER JOIN Tractor AS T
ON R.TractorID = T.ID
WHERE T.ID IS NULL

左连接应该比NOT EXISTS快得多。

答案 1 :(得分:0)

最好的解决方案是简单地清理数据,你的更新声明没问题。