【问题标题】:Update query with correlated subquery can't go through table alias具有相关子查询的更新查询不能通过表别名
【发布时间】:2020-09-23 08:58:09
【问题描述】:

我的 SQL Server 上有这个更新查询

UPDATE BK_TT_DELIVERY_PLAN TDP
SET (PACK_TYPE) = 
            (SELECT OPD.PACKING_TYPE
               FROM TT_OM_PACK_DISCREPANCY OPD
              WHERE ISNULL(TDP.PO_REF,TDP.PO_NUMBER) = OPD.PO_NUMBER
                    AND TDP.PO_ITEM = ODP.PO_ITEM)
WHERE 
    EXISTS (SELECT 1
            FROM TT_OM_PACK_DISCREPANCY OPD
            WHERE ISNULL(TDP.PO_REF,TDP.PO_NUMBER) = OPD.PO_NUMBER
              AND TDP.PO_ITEM = ODP.PO_ITEM) 

当我尝试执行时,我总是收到此错误:

查找错误 - SQL Server 数据库错误:“TDP”附近的语法不正确

我在 Oracle 上试了一下,效果很好。

此问题的任何解决方法?

谢谢。

【问题讨论】:

    标签: sql sql-server sql-update subquery


    【解决方案1】:

    您不在UPDATE 子句中为表设置别名,而是在FROM 中这样做。由于此语句中没有FROM,因此您不要为表指定别名。但是,这意味着您必须将查询中的所有别名更改为表的名称:

    UPDATE dbo.BK_TT_DELIVERY_PLAN
       SET (PACK_TYPE) = 
                (SELECT OPD.PACKING_TYPE
                   FROM TT_OM_PACK_DISCREPANCY OPD
                  WHERE ISNULL(BK_TT_DELIVERY_PLAN.PO_REF,BK_TT_DELIVERY_PLAN.PO_NUMBER) = OPD.PO_NUMBER
                        AND BK_TT_DELIVERY_PLAN.PO_ITEM = ODP.PO_ITEM)
     WHERE EXISTS
          (SELECT 1
             FROM TT_OM_PACK_DISCREPANCY OPD
                  WHERE ISNULL(BK_TT_DELIVERY_PLAN.PO_REF,BK_TT_DELIVERY_PLAN.PO_NUMBER) = OPD.PO_NUMBER
                        AND BK_TT_DELIVERY_PLAN.PO_ITEM = ODP.PO_ITEM);
    

    因此使用FROM 可能是一个更好的主意,然后在UPDATE 子句中引用别名:

    UPDATE TDP
       SET (PACK_TYPE) = 
                (SELECT OPD.PACKING_TYPE
                   FROM TT_OM_PACK_DISCREPANCY OPD
                  WHERE ISNULL(TDP.PO_REF,TDP.PO_NUMBER) = OPD.PO_NUMBER
                        AND TDP.PO_ITEM = ODP.PO_ITEM)
    FROM dbo.BK_TT_DELIVERY_PLAN TDP
    WHERE EXISTS
          (SELECT 1
             FROM TT_OM_PACK_DISCREPANCY OPD
                  WHERE ISNULL(TDP.PO_REF,TDP.PO_NUMBER) = OPD.PO_NUMBER
                        AND TDP.PO_ITEM = OPD.PO_ITEM);
    

    另外注意,您不应该使用ISNULLWHERE(或ON),因为它会导致查询变得不可搜索。使用正确的布尔逻辑。同样,使用 JOIN 而不是 2 个子查询,这似乎也可以变得更小。

    UPDATE TDP
    SET PACK_TYPE = OPD.PACKING_TYPE
    FROM dbo.BK_TT_DELIVERY_PLAN TDP
         JOIN TT_OM_PACK_DISCREPANCY OPD ON (TDP.PO_REF = OPD.PO_NUMBER 
                                         OR  (TDP.PO_REF IS NULL AND TDP.PO_NUMBER = OPD.PO_NUMBER))
                                        AND TDP.PO_ITEM = OPD.PO_ITEM;
    

    【讨论】:

    • 使用第二个查询返回:无法绑定多部分标识符“ODP.PO_ITEM”。
    • 正如 Gordon 刚刚通过他们的编辑 @Syns 演示的那样,这确实是您原始代码中的一个印刷错误。你有AND TDP.PO_ITEM = ODP.PO_ITEM,但将对象TT_OM_PACK_DISCREPANCY别名为OPD,而不是ODP;因此错误。
    • @lamu 哦该死,我没有注意到印刷错误。我的错。感谢指正
    • @gordon-linoff 谢谢,这是我的新见解,我将使用第三个查询,
    【解决方案2】:

    简单查询,请按照以下查询。在哪里使用联合查询结果和更新记录。

    UPDATE TDP
    SET TDP.PACK_TYPE = OPD.PACKING_TYPE
    FROM dbo.BK_TT_DELIVERY_PLAN TDP
    LEFT OUTER JOIN TT_OM_PACK_DISCREPANCY OPD ON ISNULL(TDP.PO_REF,TDP.PO_NUMBER) = OPD.PO_NUMBER AND TDP.PO_ITEM = ODP.PO_ITEM
    WHERE OPD.PACKING_TYPE IS NOT null
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      相关资源
      最近更新 更多