Может ли оператор DB2 WITH использоваться как часть UPDATE или MERGE? - PullRequest
2 голосов
/ 01 февраля 2011

Мне нужно обновить несколько строк в таблице БД.То, как я определял строки, подлежащие обновлению, включало в себя ряд сложных операторов, и мне удалось свести их к серии операторов 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

Теперь у меня есть два столбца данных, и я хочу использовать их для обновления таблицы.Таким образом, вместо выбора в нижней части, я попробовал все виды комбинаций слияний и обновлений, включая использование оператора 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, поэтому поверьте, что это возможно.

Если кто-то может помочь, это было бы здорово, и, пожалуйста, дайте мне знать, если я опущу любую информацию,быть полезным для решения проблемы.

Отказ от ответственности: Приведенный мною пример представляет собой упрощенную версию того, что я пытаюсь сделать, и на самом деле может не иметь никакого смысла!

Ответы [ 6 ]

4 голосов
/ 01 февраля 2011

Как говорит @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 голос
/ 23 февраля 2018

Способ использования оператора WITH с UPDATE INSERT тоже) использует оператор SELECT FROM UPDATE ( здесь ):

WITH TEMP_TABLE AS (
    SELECT [...]
)
SELECT * FROM FINAL TABLE (
    UPDATE TABLE_A SET (COL1, COL2) = (SELECT [...] TEMP_TABLE)
    WHERE [...]
);
1 голос
/ 10 октября 2017

Поместите CTE в представление и выберите из представления в слиянии. Таким образом, вы получите чистое, читаемое представление и чистое читаемое слияние.

1 голос
/ 03 февраля 2012

Если вы работаете с DB2 V8 или новее, есть интересный взлом SQL здесь , который позволяет вам ОБНОВИТЬ / ВСТАВИТЬ в запрос с оператором WITH. Я считаю, что для вставок и обновлений, которые требуют много предварительной подготовки данных, этот метод дает большую ясность.

Редактировать Одно исправление здесь - выбор из операторов UPDATE был введен в V9, я полагаю, что вышеописанное будет работать для вставок на V8 или выше и обновлений для V9 или выше.

1 голос
/ 01 февраля 2011

Я сейчас ищу грамматику, но я почти уверен, что ответ - нет.По крайней мере, не в той версии DB2, которую я использовал в последний раз.Взгляните на update и merge doc страницы для их синтаксиса.Даже если вы видите полную выборку в синтаксисе, вы не можете использовать with, поскольку она явно отделена в соответствии с select страницей документа.

0 голосов
/ 28 июня 2013

Другой метод состоит в том, чтобы просто заменить ваши запросы 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, вырежьте его и вставьте в блок Q2 после FROM 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

Я сделал это на собственном личном опыте (только сейчас на самом деле), и он отлично работает.

Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...