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

发布于 2024-10-15 10:21:05 字数 1100 浏览 5 评论 0 原文

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

由于我设法使用WITH语句获取这些值,因此我希望在更新/合并中使用它。一个简化的示例如下:

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

现在我有两列数据,我想用它们来更新表。因此,我没有将选择放在底部,而是尝试了各种合并和更新的组合,包括将WITH语句放在UPDATE/MERGE之上,或者作为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结合使用的例子,所以相信这是可能的。

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

免责声明:我提供的示例是我想要做的事情的简化版本,实际上可能没有任何意义!

I need to update some rows in a DB table. How I identify the rows to be updated involved a series of complicated statements, and I managed to boil them down to a series of WITH statements. Now I have the correct data values, I need to update the table.

Since I managed to get these values with a WITH statement, I was hoping to use it in the UPDATE/MERGE. A simplified example follows:

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

Now I have the two columns of data, I want to use them to update a table. So instead of having the select at the bottom, I've tried all sorts of combinations of merges and updates, including having the WITH statement above the UPDATE/MERGE, or as part of the UPDATE/MERGE statement. The following is what comes closest in my mind to what I want to do:

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

So it doesn't work. I'm unsure if this is even possible, as I've found no examples on the internet using WITH statements in combination with UPDATE or MERGE. I have examples of WITH statements being used in conjunction with INSERT, so believe it might be possible.

If anyone can help it would be great, and please let me know if I've left out any information that would be useful to solve the problem.

Disclaimer: The example I've provided is a boiled down version of what I'm trying to do, and may not actually make any sense!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

孤云独去闲 2024-10-22 10:21:05

正如 @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;

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

As @Andrew White says, you can't use a common table expression in a MERGE statement.

However, you can eliminate the common table expressions with nested subselects. Here is your example select statement, rewritten using nested subselects:

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);

This is somewhat convoluted (the exact statement could be written better), but I realize that you were just giving a simplified example.

You may be able to rewrite your MERGE statement using nested subselects instead of common table expressions. It is certainly syntactically possible.

For example:

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;

Again, this is convoluted, but it shows you that it is at least possible.

慕烟庭风 2024-10-22 10:21:05

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 [...]
);

A way to use WITH statement with UPDATE (and INSERT too) is using SELECT FROM UPDATE statement (here):

WITH TEMP_TABLE AS (
    SELECT [...]
)
SELECT * FROM FINAL TABLE (
    UPDATE TABLE_A SET (COL1, COL2) = (SELECT [...] FROM TEMP_TABLE)
    WHERE [...]
);
神经大条 2024-10-22 10:21:05

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

I'm looking up the grammar now but I am pretty sure the answer is no. At least not in the version of DB2 I last used. Take a peek at the update and merge doc pages for their syntax. Even if you see the fullselect in the syntax you can't use with as that is explicitly separate according to the select doc page.

沉睡月亮 2024-10-22 10:21:05

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

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

If you're running DB2 V8 or later, there's an interesting SQL hack here that allows you to UPDATE/INSERT in a query with a WITH statement. For inserts & updates that require a lot of preliminary data prepping, I find this method offers a lot of clarity.

Edit One correction here - selecting from UPDATE statements was introduced in V9 i believe, so the above will work for inserts on V8 or greater, and updates for V9 or greater.

浅听莫相离 2024-10-22 10:21:05

将 CTE 放入视图中,然后从合并视图中进行选择。这样你就可以获得一个干净、可读的视图,以及一个干净、可读的合并。

Put the CTEs into a view, and select from the view in the merge. You get a clean, readable view that way, and a clean, readable merge.

小霸王臭丫头 2024-10-22 10:21:05

另一种方法是简单地替换您的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,并将其放在结束括号之后(删除逗号),然后将 AS 放在 Q1 前面。
  4. 取出这个新的 Q1 块,将其剪切并粘贴到 FROM Q1 之后的 Q2 块中(用剪贴板中的查询替换 Q1) 注意:当然,单独保留对 Q1 的其他引用(在内部连接键中)。
  5. 现在您有一个更大的第二季度查询。再次执行步骤 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

我已经根据自己的个人经验(实际上现在)完成了此操作,并且效果非常好。

祝你好运。

Another method is to simply substitute your WITH queries and just use subselects.

For example, if you had (and I tried to include a somewhat complex example with some WHERE logic, an aggregate function (MAX) and a GROUP BY, just to show it more real world):

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

... you could turn this into something appropriate for a MERGE INTO by doing the following:

  1. remove the WITH at the top
  2. remove the comma from the end of the Q1 block (after the closing parenthesis)
  3. take the Q1 AS from before the opening parenthesis and put is after the ending parenthesis (remove the comma) and then put the AS in front of the Q1.
  4. take this new Q1 block and cut it and paste it into the Q2 block after the FROM Q1 (replacing the Q1 with the query in your clipboard) NOTE: leave the other references to Q1 (in the inner join keys) alone, of course.
  5. Now you have a bigger Q2 query. Do steps 3 and 4 again, this time replacing the Q2 (after the FROM) in your main select with the bigger Q2 query in your clipboard.

In the end, you'll have a straight SELECT query that looks like this (reformatted to show proper indentation):

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

I have done this in my own personal experience (just now actually) and it works perfectly.

Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文