2

我需要更新数据库表中的一些行。我如何识别要更新的行涉及一系列复杂的语句,我设法将它们归结为一系列 WITH 语句。现在我有了正确的数据值,我需要更新表格。

由于我设法通过 WITH 语句获取这些值,因此我希望在 UPDATE/MERGE 中使用它。一个简化的例子如下:

with data1
(
    ID_1
)
as
(
    Select ID
    from  ID_TABLE
    where ID > 10
)
,
cmedb.data2
(
     MIN_ORIGINAL_ID
    ,OTHER_ID
)
as
(
    Select min(ORIGINAL_ID)
           ,OTHER_ID
    from   OTHER_ID_TABLE
    where  OTHER_ID in
    (
        Select distinct ID_1
        From   data1
    )
    group by OTHER_ID

)
select MIN_ORIGINAL_ID
      ,OTHER_ID
from cmedb.data2

现在我有两列数据,我想用它们来更新一个表。因此,我没有在底部使用 select,而是尝试了各种合并和更新的组合,包括在 UPDATE/MERGE 上方使用 WITH 语句,或者作为 UPDATE/MERGE 语句的一部分。以下是我认为最接近我想做的事情:

merge into ID_TABLE as it
using
(
    select MIN_ORIGINAL_ID
          ,OTHER_ID
    from cmedb.data2

) AS SEL
ON
(
    it.ID = sel.OTHER_ID
)
when matched then
update
set it.ORIGINAL_ID = sel.MIN_ORIGINAL_ID

所以它不起作用。我不确定这是否可行,因为我在互联网上没有找到将 WITH 语句与 UPDATE 或 MERGE 结合使用的示例。我有与 INSERT 一起使用 WITH 语句的示例,因此相信它是可能的。

如果有人可以提供帮助,那就太好了,如果我遗漏了任何有助于解决问题的信息,请告诉我。

免责声明:我提供的示例是我正在尝试做的简化版本,实际上可能没有任何意义!

4

6 回答 6

4

正如@Andrew White 所说,您不能在 MERGE 语句中使用公用表表达式。

但是,您可以使用嵌套子选择消除公用表表达式。这是您的示例选择语句,使用嵌套子选择重写:

select min_original_id, other_id
from (
   select min(original_id), other_id
   from   other_id_table
   where  other_id in (
      select distinct id_1 from (select id from id_table where id > 10) AS DATA1 (ID_1)
   )
   group by other_id
) AS T (MIN_ORIGINAL_ID, OTHER_ID);

这有点令人费解(确切的陈述可以写得更好),但我意识到你只是给出了一个简化的例子。

您可以使用嵌套子选择而不是公用表表达式来重写您的 MERGE 语句。这在语法上当然是可能的。

例如:

merge into other_id_table x
using (
   select min_original_id, other_id
   from (
      select min(original_id), other_id
      from   other_id_table
      where  other_id in (
         select distinct id_1 from (select id from id_table where id > 10) AS DATA1 (ID_1)
      )
      group by other_id
   ) AS T (MIN_ORIGINAL_ID, OTHER_ID)
) as y
on y.other_id = x.other_id
when matched 
   then update set other_id = y.min_original_id;

同样,这是令人费解的,但它向您表明它至少是可能的。

于 2011-02-01T17:38:55.333 回答
2

WITH语句与UPDATE(以及INSERT)一起使用的一种方法是使用SELECT FROM UPDATE语句(此处):

WITH TEMP_TABLE AS (
    SELECT [...]
)
SELECT * FROM FINAL TABLE (
    UPDATE TABLE_A SET (COL1, COL2) = (SELECT [...] FROM TEMP_TABLE)
    WHERE [...]
);
于 2018-02-23T19:24:11.883 回答
1

如果您运行的是 DB2 V8 或更高版本,这里有一个有趣的 SQL hack 它允许您在带有 WITH 语句的查询中进行 UPDATE/INSERT。对于需要大量初步数据准备的插入和更新,我发现这种方法提供了很多清晰度。

编辑这里的一个更正-我相信在 V9 中引入了从 UPDATE 语句中选择,因此上述内容适用于 V8 或更高版本的插入,以及 V9 或更高版本的更新。

于 2012-02-03T15:15:11.333 回答
1

我现在正在查找语法,但我很确定答案是否定的。至少在我上次使用的 DB2 版本中没有。查看更新合并文档页面的语法。即使您在语法中看到全选,也不能使用with,因为根据选择文档页面,它是明确分开的。

于 2011-02-01T15:29:02.510 回答
1

将 CTE 放入视图中,然后从合并中的视图中进行选择。通过这种方式,您将获得一个干净、可读的视图,以及一个干净、可读的合并。

于 2017-10-10T14:06:38.657 回答
0

另一种方法是简单地替换您的 WITH 查询并仅使用子选择。

例如,如果您有(并且我试图包含一个带有一些 WHERE 逻辑、聚合函数 (MAX) 和 GROUP BY 的稍微复杂的示例,只是为了展示它更真实的世界):

WITH
  Q1 AS (
    SELECT
      A.X,
      A.Y,
      A.Z,
      MAX(A.W) AS W
    FROM
      TABLEB B
      INNER JOIN TABLEA A ON B.X = A.X AND B.Y = A.Y AND B.Z = A.Z
    WHERE A.W <= DATE('2013-01-01') 
    GROUP BY
      A.X,
      A.Y,
      A.Z
  ),

  Q2 AS (
    SELECT
      A.X,
      A.Y,
      A.Z,
      A.W,
      MAX(A.V) AS V
    FROM
      Q1
      INNER JOIN TABLEA A ON Q1.X = A.X AND Q1.Y = A.Y AND Q1.Z = A.Z AND Q1.W = A.W
    GROUP BY
      A.X,
      A.Y,
      A.Z,
      A.W
  )

SELECT
  B.U,
  A.T
FROM
  Q2
  INNER JOIN TABLEA A ON Q2.X = A.X AND Q2.Y = A.Y AND Q2.Z = A.Z AND Q2.W = A.W AND Q2.V = A.V)
  RIGHT OUTER JOIN TABLEB B ON Q2.X = B.X AND Q2.Y = B.Y AND Q2.Z = B.Z

...您可以通过执行以下操作将其变成适合 MERGE INTO 的内容:

  1. 删除顶部的 WITH
  2. 从 Q1 块的末尾删除逗号(在右括号之后)
  3. 从左括号之前取出 Q1 AS 并将 is 放在结尾括号之后(删除逗号),然后将 AS 放在 Q1 前面。
  4. 获取这个新的 Q1 块并将其剪切并粘贴到 FROM Q1 之后的 Q2 块中(用剪贴板中的查询替换 Q1)注意:当然,不要理会 Q1 的其他引用(在内部连接键中)。
  5. 现在你有一个更大的 Q2 查询。再次执行步骤 3 和 4,这次将主选择中的 Q2(在 FROM 之后)替换为剪贴板中较大的 Q2 查询。

最后,您将获得一个如下所示的直接 SELECT 查询(重新格式化以显示正确的缩进):

SELECT
  B.U,
  A.T
FROM
  (SELECT
     A.X,
     A.Y,
     A.Z,
     A.W,
     MAX(A.V) AS V
   FROM
     (SELECT
        A.X,
        A.Y,
        A.Z,
        MAX(A.W) AS W
      FROM
        TABLEB B
        INNER JOIN TABLEA A ON B.X = A.X AND B.Y = A.Y AND B.Z = A.Z
      WHERE A.W <= DATE('2013-01-01') 
      GROUP BY
        A.X,
        A.Y,
        A.Z) AS Q1
     INNER JOIN TABLEA A ON Q1.X = A.X AND Q1.Y = A.Y AND Q1.Z = A.Z AND Q1.W = A.W
     GROUP BY
       A.X,
       A.Y,
       A.Z,
       A.W) AS Q2
INNER JOIN TABLEA A ON Q2.X = A.X AND Q2.Y = A.Y AND Q2.Z = A.Z AND Q2.W = A.W AND Q2.V = A.V
RIGHT OUTER JOIN TABLEB B ON Q2.X = B.X AND Q2.Y = B.Y AND Q2.Z = B.Z

我已经根据自己的个人经验(实际上只是现在)做到了这一点,并且效果很好。

祝你好运。

于 2013-06-28T14:53:48.767 回答