我需要更新数据库表中的某些行。我如何识别要更新的行涉及一系列复杂的语句,我设法将它们归结为一系列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一起使用的例子,所以相信它可能是可能的。
如果有人可以提供帮助,那就太棒了,如果我遗漏了任何有助于解决问题的信息,请告诉我。
免责声明:我提供的示例是我正在尝试做的简化版本,实际上可能没有任何意义!
答案 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版本中没有。查看update和merge 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的内容:
最后,您将看到一个类似于此的直接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
我是根据自己的亲身经历(实际上是这样)完成的,而且效果很好。
祝你好运。