【问题标题】:Is there a way to write an UPDATE statement to fix multiple rows with bad data?有没有办法编写一个 UPDATE 语句来修复多行的错误数据?
【发布时间】:2021-12-05 20:15:12
【问题描述】:

我正在尝试修复 SQL Server 数据库中的数据错误。

有些值使用了来自错误工厂的错误 partId。

我可以得到一个包含错误零件的所有机器的列表,如下所示:

---machines using wrong parts from wrong factory 88 and 89:
SELECT ml.machineId, ml.machineName, mp.machineId, mp.partId, pc.officialIdentifierId 
FROM industry.machineParts mp
INNER JOIN partsCatalog pc ON mp.partId = pc.partId
INNER JOIN machineList ml ON mp.machineId = ml.machineId
WHERE pc.factoryId IN (88,89)

我有一个在 machineParts 表中常见的 ID,即officialIdentifierId ID。

但我不确定如何使用工厂 88 中的 partId 更改 machineParts 表中的所有行,以及使用新工厂 100 partIds 更改 machineParts 表中的所有行。

machineParts 表如下所示:

machineId       partId
----------------------
7623741         123 
8927661         124
6471982         125

所以如果一台机器有一个来自工厂 88 或 89 的旧 partId,我需要用工厂 100 的 partId 替换它。

partsCatalog 表具有 factoryId 值,如下所示:

partId  |   name        |   factoryId   |   officialIdentifierId
--------------------------------------------------------------
123           OilFil                88          A-00-900c     
124           O_Filter              89          A-00-900c
125           Oil Filter            100         A-00-900c

因此,修复后正确的 machineParts 表应如下所示:

machineId       partId
----------------------
7623741         125
8927661         125
6471982         125

我尝试了这个更新语句来修复所有坏行:

UPDATE machineParts SET partID = (SELECT partID FROM  partsCatalog WHERE factoryId = 100)
WHERE partID IN(123, 124)

但我收到此错误:

子查询返回超过 1 个值。这是不允许的,当 子查询遵循 =、!=、、>= 或当子查询用作 一种表达。声明已终止。

有没有办法用一个查询来修复所有坏行?

谢谢!

【问题讨论】:

  • 错误在这里告诉你问题,你不确定错误呢?
  • SQL Server 期望您的子查询产生单个值;当你自己运行它时,你会得到多少行?超过 1 个。
  • @Larnu 我在 Microsoft 站点上查找了 SQL Server 的错误。我想我明白为什么我会收到这个错误。但我想我很幸运我得到了错误,因为我认为如果该查询有效,它会破坏表数据。
  • @Stu 谢谢我现在明白了这个错误,但我很幸运我得到了错误。你知道修复我的machineParts 表中所有使用旧工厂错误partId 的条目的方法吗?我可以自己修复每一行,但这将超过 5000 行。
  • 您需要构建查询以选择正确的值,然后您可以将其转换为更新语句,或者可能在可更新的 CTE 中使用。

标签: sql sql-server tsql sql-server-2012


【解决方案1】:

这里的问题是您有多个带有factoryId = 100 的记录。您可以使用如下所示的 TOP 1“修复”此问题,但您必须确定 partID 在所有记录上与子查询的 factoryId 相同:

UPDATE machineParts SET partID = (SELECT TOP(1) partID FROM  partsCatalog WHERE factoryId = 100)
WHERE partID IN(123, 124);

这表示“只需给我 first 记录上的 partID,工厂ID 为 100”。您还可以调整子查询以提供最新的查询,假设有一个 createdOn 字段作为示例:

UPDATE machineParts SET partID = (SELECT TOP(1) partID FROM  partsCatalog WHERE factoryId = 100 ORDER BY createdOn DESC)
WHERE partID IN(123, 124);

【讨论】:

  • 谢谢,我的partsCatalog 表中有多个记录,factoryId = 100。但统一数据的是名为officialIdentifierId 的列。所以即使machineParts 表有错误的partIds。我可以使用officialIdentifierId 来查找它们,因为错误的 factoryId 和正确的 factoryId 都是一样的。但我试图找到一个查询来一次更新它们。
  • 没有订单条件,top (1) 没有得到 first 行,没有 first 行,它下次执行时可能会有所不同。
  • 没错@Stu,考虑到它这次提出的任何查询计划,它是引擎遇到的“第一个”。
【解决方案2】:

在工厂 100 中是否只有一个部件的 officialIdentifierId 为 A-00-900c?

如果是这样,

UPDATE machineParts 
    SET partID = (SELECT partID 
                  FROM  partsCatalog 
                  WHERE factoryId = 100
                    AND officialIdentifierId = 'A-00-900c'
                 )
WHERE partID IN (123, 124)

【讨论】:

  • 是的,partsCatalog 包含 officialIdentifierId 列。所以只有一行的 factoryId 为 100,officialIdentifierId 为 A-00-900c。
  • @SkyeBoniwell,给定的查询是否符合您的要求?
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 2016-03-27
  • 2014-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-01
相关资源
最近更新 更多