DB2 WITH语句可以用作UPDATE或MERGE的一部分吗?

时间:2011-02-01 15:20:05

标签: join merge db2 with-statement

我需要更新数据库表中的某些行。我如何识别要更新的行涉及一系列复杂的语句,我设法将它们归结为一系列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

现在我有两列数据,我想用它们来更新表。因此,我没有在底部选择,而是尝试了各种合并和更新组合,包括在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的例子。我有一些WITH语句与INSERT一起使用的例子,所以相信它可能是可能的。

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

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

6 个答案:

答案 0 :(得分:4)

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

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

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;

同样,这是令人费解的,但它告诉你它至少是可能的。

答案 1 :(得分:1)

我现在正在查找语法,但我很确定答案是否定的。至少在我上次使用的DB2版本中没有。查看updatemerge doc页面的语法。即使您在语法中看到 fullselect ,也无法使用with,因为根据select文档页面明确区分了{{1>}。

答案 2 :(得分:1)

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

编辑此处进行了一次修正 - 我认为在V9中引入了从UPDATE语句中选择,因此上述内容适用于V8或更高版本的插入,以及V9或更高版本的更新。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

WITH TEMP_TABLE AS (
    SELECT [...]
)
SELECT * FROM FINAL TABLE (
    UPDATE TABLE_A SET (COL1, COL2) = (SELECT [...] TEMP_TABLE)
    WHERE [...]
);

答案 5 :(得分: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,将put放在结束括号后(删除逗号),然后将AS放在Q1的前面。
  4. 取下这个新的Q1块并将其剪切并在FROM Q1之后将其粘贴到Q2块中(用剪贴板中的查询替换Q1)注意:单独留下Q1的其他引用(在内部连接键中),当然。
  5. 现在你有一个更大的Q2查询。再次执行步骤3和4,这次使用剪贴板中较大的Q2查询替换主选择中的Q2(在FROM之后)。
  6. 最后,您将看到一个类似于此的直接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
    

    我是根据自己的亲身经历(实际上是这样)完成的,而且效果很好。

    祝你好运。